commons-net-2.2/0000755000175000017500000000000011617452470013561 5ustar twernertwernercommons-net-2.2/src/0000755000175000017500000000000011617452470014350 5ustar twernertwernercommons-net-2.2/src/assembly/0000755000175000017500000000000011617452465016173 5ustar twernertwernercommons-net-2.2/src/assembly/bin.xml0000644000175000017500000000326311470611172017456 0ustar twernertwerner bin tar.gz tar.bz2 zip README* LICENSE* NOTICE* RELEASE-NOTES.txt target commons-net-${project.version}.jar target/site/apidocs apidocs **/* commons-net-2.2/src/assembly/src.xml0000644000175000017500000000245311470611172017475 0ustar twernertwerner src tar.gz tar.bz2 zip ${artifactId}-${version}-src README* LICENSE* NOTICE* RELEASE-NOTES.txt pom.xml src commons-net-2.2/src/main/0000755000175000017500000000000011617452466015301 5ustar twernertwernercommons-net-2.2/src/main/java/0000755000175000017500000000000011617452467016223 5ustar twernertwernercommons-net-2.2/src/main/java/examples/0000755000175000017500000000000011617452467020041 5ustar twernertwernercommons-net-2.2/src/main/java/examples/ntp/0000755000175000017500000000000011617452467020642 5ustar twernertwernercommons-net-2.2/src/main/java/examples/ntp/TimeClient.java0000644000175000017500000000567711014672436023550 0ustar twernertwernerpackage examples.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.io.IOException; import java.net.InetAddress; import org.apache.commons.net.time.TimeTCPClient; import org.apache.commons.net.time.TimeUDPClient; /*** * This is an example program demonstrating how to use the TimeTCPClient * and TimeUDPClient classes. * This program connects to the default time service port of a * specified server, retrieves the time, and prints it to standard output. * See the spec * for details. The default is to use the TCP port. Use the -udp flag to * use the UDP port. *

* Usage: TimeClient [-udp] *

***/ public final class TimeClient { public static final void timeTCP(String host) throws IOException { TimeTCPClient client = new TimeTCPClient(); try { // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(host); System.out.println(client.getDate()); } finally { client.disconnect(); } } public static final void timeUDP(String host) throws IOException { TimeUDPClient client = new TimeUDPClient(); // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.open(); System.out.println(client.getDate(InetAddress.getByName(host))); client.close(); } public static final void main(String[] args) { if (args.length == 1) { try { timeTCP(args[0]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else if (args.length == 2 && args[0].equals("-udp")) { try { timeUDP(args[1]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else { System.err.println("Usage: TimeClient [-udp] "); System.exit(1); } } } commons-net-2.2/src/main/java/examples/ntp/NTPClient.java0000644000175000017500000001712110757034423023277 0ustar twernertwernerpackage examples.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.io.IOException; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.text.NumberFormat; import org.apache.commons.net.ntp.*; /*** * This is an example program demonstrating how to use the NTPUDPClient * class. This program sends a Datagram client request packet to a * Network time Protocol (NTP) service port on a specified server, * retrieves the time, and prints it to standard output along with * the fields from the NTP message header (e.g. stratum level, reference id, * poll interval, root delay, mode, ...) * See the spec * for details. *

* Usage: NTPClient *
* Example: NTPClient clock.psu.edu * * @author Jason Mathews, MITRE Corp ***/ public final class NTPClient { private static final NumberFormat numberFormat = new java.text.DecimalFormat("0.00"); /** * Process TimeInfo object and print its details. * @param info TimeInfo object. */ public static void processResponse(TimeInfo info) { NtpV3Packet message = info.getMessage(); int stratum = message.getStratum(); String refType; if (stratum <= 0) refType = "(Unspecified or Unavailable)"; else if (stratum == 1) refType = "(Primary Reference; e.g., GPS)"; // GPS, radio clock, etc. else refType = "(Secondary Reference; e.g. via NTP or SNTP)"; // stratum should be 0..15... System.out.println(" Stratum: " + stratum + " " + refType); int version = message.getVersion(); int li = message.getLeapIndicator(); System.out.println(" leap=" + li + ", version=" + version + ", precision=" + message.getPrecision()); System.out.println(" mode: " + message.getModeName() + " (" + message.getMode() + ")"); int poll = message.getPoll(); // poll value typically btwn MINPOLL (4) and MAXPOLL (14) System.out.println(" poll: " + (poll <= 0 ? 1 : (int) Math.pow(2, poll)) + " seconds" + " (2 ** " + poll + ")"); double disp = message.getRootDispersionInMillisDouble(); System.out.println(" rootdelay=" + numberFormat.format(message.getRootDelayInMillisDouble()) + ", rootdispersion(ms): " + numberFormat.format(disp)); int refId = message.getReferenceId(); String refAddr = NtpUtils.getHostAddress(refId); String refName = null; if (refId != 0) { if (refAddr.equals("127.127.1.0")) { refName = "LOCAL"; // This is the ref address for the Local Clock } else if (stratum >= 2) { // If reference id has 127.127 prefix then it uses its own reference clock // defined in the form 127.127.clock-type.unit-num (e.g. 127.127.8.0 mode 5 // for GENERIC DCF77 AM; see refclock.htm from the NTP software distribution. if (!refAddr.startsWith("127.127")) { try { InetAddress addr = InetAddress.getByName(refAddr); String name = addr.getHostName(); if (name != null && !name.equals(refAddr)) refName = name; } catch (UnknownHostException e) { // some stratum-2 servers sync to ref clock device but fudge stratum level higher... (e.g. 2) // ref not valid host maybe it's a reference clock name? // otherwise just show the ref IP address. refName = NtpUtils.getReferenceClock(message); } } } else if (version >= 3 && (stratum == 0 || stratum == 1)) { refName = NtpUtils.getReferenceClock(message); // refname usually have at least 3 characters (e.g. GPS, WWV, LCL, etc.) } // otherwise give up on naming the beast... } if (refName != null && refName.length() > 1) refAddr += " (" + refName + ")"; System.out.println(" Reference Identifier:\t" + refAddr); TimeStamp refNtpTime = message.getReferenceTimeStamp(); System.out.println(" Reference Timestamp:\t" + refNtpTime + " " + refNtpTime.toDateString()); // Originate Time is time request sent by client (t1) TimeStamp origNtpTime = message.getOriginateTimeStamp(); System.out.println(" Originate Timestamp:\t" + origNtpTime + " " + origNtpTime.toDateString()); long destTime = info.getReturnTime(); // Receive Time is time request received by server (t2) TimeStamp rcvNtpTime = message.getReceiveTimeStamp(); System.out.println(" Receive Timestamp:\t" + rcvNtpTime + " " + rcvNtpTime.toDateString()); // Transmit time is time reply sent by server (t3) TimeStamp xmitNtpTime = message.getTransmitTimeStamp(); System.out.println(" Transmit Timestamp:\t" + xmitNtpTime + " " + xmitNtpTime.toDateString()); // Destination time is time reply received by client (t4) TimeStamp destNtpTime = TimeStamp.getNtpTime(destTime); System.out.println(" Destination Timestamp:\t" + destNtpTime + " " + destNtpTime.toDateString()); info.computeDetails(); // compute offset/delay if not already done Long offsetValue = info.getOffset(); Long delayValue = info.getDelay(); String delay = (delayValue == null) ? "N/A" : delayValue.toString(); String offset = (offsetValue == null) ? "N/A" : offsetValue.toString(); System.out.println(" Roundtrip delay(ms)=" + delay + ", clock offset(ms)=" + offset); // offset in ms } public static final void main(String[] args) { if (args == null || args.length == 0) { System.err.println("Usage: NTPClient "); System.exit(1); } NTPUDPClient client = new NTPUDPClient(); // We want to timeout if a response takes longer than 10 seconds client.setDefaultTimeout(10000); try { client.open(); for (int i = 0; i < args.length; i++) { System.out.println(); try { InetAddress hostAddr = InetAddress.getByName(args[i]); System.out.println("> " + hostAddr.getHostName() + "/" + hostAddr.getHostAddress()); TimeInfo info = client.getTime(hostAddr); processResponse(info); } catch (IOException ioe) { ioe.printStackTrace(); } } } catch (SocketException e) { e.printStackTrace(); } client.close(); } } commons-net-2.2/src/main/java/examples/util/0000755000175000017500000000000011617452467021016 5ustar twernertwernercommons-net-2.2/src/main/java/examples/util/IOUtil.java0000644000175000017500000000650411165732051023017 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.util; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.net.io.Util; /*** * This is a utility class providing a reader/writer capability required * by the weatherTelnet, rexec, rshell, and rlogin example programs. * The only point of the class is to hold the static method readWrite * which spawns a reader thread and a writer thread. The reader thread * reads from a local input source (presumably stdin) and writes the * data to a remote output destination. The writer thread reads from * a remote input source and writes to a local output destination. * The threads terminate when the remote input source closes. *

***/ public final class IOUtil { public static final void readWrite(final InputStream remoteInput, final OutputStream remoteOutput, final InputStream localInput, final OutputStream localOutput) { Thread reader, writer; reader = new Thread() { public void run() { int ch; try { while (!interrupted() && (ch = localInput.read()) != -1) { remoteOutput.write(ch); remoteOutput.flush(); } } catch (IOException e) { //e.printStackTrace(); } } } ; writer = new Thread() { public void run() { try { Util.copyStream(remoteInput, localOutput); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } }; writer.setPriority(Thread.currentThread().getPriority() + 1); writer.start(); reader.setDaemon(true); reader.start(); try { writer.join(); reader.interrupt(); } catch (InterruptedException e) { } } } commons-net-2.2/src/main/java/examples/mail/0000755000175000017500000000000011617452467020763 5ustar twernertwernercommons-net-2.2/src/main/java/examples/mail/POP3Mail.java0000644000175000017500000001025311165734447023152 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.mail; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import org.apache.commons.net.pop3.POP3Client; import org.apache.commons.net.pop3.POP3MessageInfo; /*** * This is an example program demonstrating how to use the POP3Client class. * This program connects to a POP3 server and retrieves the message * headers of all the messages, printing the From: and Subject: header * entries for each message. *

* Usage: messages *

***/ public final class POP3Mail { public static final void printMessageInfo(BufferedReader reader, int id) throws IOException { String line, lower, from, subject; from = ""; subject = ""; while ((line = reader.readLine()) != null) { lower = line.toLowerCase(); if (lower.startsWith("from: ")) from = line.substring(6).trim(); else if (lower.startsWith("subject: ")) subject = line.substring(9).trim(); } System.out.println(Integer.toString(id) + " From: " + from + " Subject: " + subject); } public static final void main(String[] args) { int message; String server, username, password; POP3Client pop3; Reader reader; POP3MessageInfo[] messages; if (args.length < 3) { System.err.println( "Usage: messages "); System.exit(1); } server = args[0]; username = args[1]; password = args[2]; pop3 = new POP3Client(); // We want to timeout if a response takes longer than 60 seconds pop3.setDefaultTimeout(60000); try { pop3.connect(server); } catch (IOException e) { System.err.println("Could not connect to server."); e.printStackTrace(); System.exit(1); } try { if (!pop3.login(username, password)) { System.err.println("Could not login to server. Check password."); pop3.disconnect(); System.exit(1); } messages = pop3.listMessages(); if (messages == null) { System.err.println("Could not retrieve message list."); pop3.disconnect(); System.exit(1); } else if (messages.length == 0) { System.out.println("No messages"); pop3.logout(); pop3.disconnect(); System.exit(1); } for (message = 0; message < messages.length; message++) { reader = pop3.retrieveMessageTop(messages[message].number, 0); if (reader == null) { System.err.println("Could not retrieve message header."); pop3.disconnect(); System.exit(1); } printMessageInfo(new BufferedReader(reader), messages[message].number); } pop3.logout(); pop3.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } } commons-net-2.2/src/main/java/examples/mail/SMTPMail.java0000644000175000017500000001102011165734447023205 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.mail; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.io.Util; import org.apache.commons.net.smtp.SMTPClient; import org.apache.commons.net.smtp.SMTPReply; import org.apache.commons.net.smtp.SimpleSMTPHeader; /*** * This is an example program using the SMTP package to send a message * to the specified recipients. It prompts you for header information and * a filename containing the message. *

***/ public final class SMTPMail { public final static void main(String[] args) { String sender, recipient, subject, filename, server, cc; List ccList = new ArrayList(); BufferedReader stdin; FileReader fileReader = null; Writer writer; SimpleSMTPHeader header; SMTPClient client; Enumeration en; if (args.length < 1) { System.err.println("Usage: mail smtpserver"); System.exit(1); } server = args[0]; stdin = new BufferedReader(new InputStreamReader(System.in)); try { System.out.print("From: "); System.out.flush(); sender = stdin.readLine(); System.out.print("To: "); System.out.flush(); recipient = stdin.readLine(); System.out.print("Subject: "); System.out.flush(); subject = stdin.readLine(); header = new SimpleSMTPHeader(sender, recipient, subject); while (true) { System.out.print("CC : "); System.out.flush(); // Of course you don't want to do this because readLine() may be null cc = stdin.readLine().trim(); if (cc.length() == 0) break; header.addCC(cc); ccList.add(cc); } System.out.print("Filename: "); System.out.flush(); filename = stdin.readLine(); try { fileReader = new FileReader(filename); } catch (FileNotFoundException e) { System.err.println("File not found. " + e.getMessage()); } client = new SMTPClient(); client.addProtocolCommandListener(new PrintCommandListener( new PrintWriter(System.out))); client.connect(server); if (!SMTPReply.isPositiveCompletion(client.getReplyCode())) { client.disconnect(); System.err.println("SMTP server refused connection."); System.exit(1); } client.login(); client.setSender(sender); client.addRecipient(recipient); for (String recpt : ccList) client.addRecipient(recpt); writer = client.sendMessageData(); if (writer != null) { writer.write(header.toString()); Util.copyReader(fileReader, writer); writer.close(); client.completePendingCommand(); } fileReader.close(); client.logout(); client.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } } commons-net-2.2/src/main/java/examples/nntp/0000755000175000017500000000000011617452467021020 5ustar twernertwernercommons-net-2.2/src/main/java/examples/nntp/PostMessage.java0000644000175000017500000001161311165727602024111 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.nntp; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.Writer; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.io.Util; import org.apache.commons.net.nntp.NNTPClient; import org.apache.commons.net.nntp.NNTPReply; import org.apache.commons.net.nntp.SimpleNNTPHeader; /*** * This is an example program using the NNTP package to post an article * to the specified newsgroup(s). It prompts you for header information and * a filename to post. *

***/ public final class PostMessage { public final static void main(String[] args) { String from, subject, newsgroup, filename, server, organization; String references; BufferedReader stdin; FileReader fileReader = null; SimpleNNTPHeader header; NNTPClient client; if (args.length < 1) { System.err.println("Usage: post newsserver"); System.exit(1); } server = args[0]; stdin = new BufferedReader(new InputStreamReader(System.in)); try { System.out.print("From: "); System.out.flush(); from = stdin.readLine(); System.out.print("Subject: "); System.out.flush(); subject = stdin.readLine(); header = new SimpleNNTPHeader(from, subject); System.out.print("Newsgroup: "); System.out.flush(); newsgroup = stdin.readLine(); header.addNewsgroup(newsgroup); while (true) { System.out.print("Additional Newsgroup : "); System.out.flush(); // Of course you don't want to do this because readLine() may be null newsgroup = stdin.readLine().trim(); if (newsgroup.length() == 0) break; header.addNewsgroup(newsgroup); } System.out.print("Organization: "); System.out.flush(); organization = stdin.readLine(); System.out.print("References: "); System.out.flush(); references = stdin.readLine(); if (organization != null && organization.length() > 0) header.addHeaderField("Organization", organization); if (references != null && organization.length() > 0) header.addHeaderField("References", references); header.addHeaderField("X-Newsreader", "NetComponents"); System.out.print("Filename: "); System.out.flush(); filename = stdin.readLine(); try { fileReader = new FileReader(filename); } catch (FileNotFoundException e) { System.err.println("File not found. " + e.getMessage()); System.exit(1); } client = new NNTPClient(); client.addProtocolCommandListener(new PrintCommandListener( new PrintWriter(System.out))); client.connect(server); if (!NNTPReply.isPositiveCompletion(client.getReplyCode())) { client.disconnect(); System.err.println("NNTP server refused connection."); System.exit(1); } if (client.isAllowedToPost()) { Writer writer = client.postArticle(); if (writer != null) { writer.write(header.toString()); Util.copyReader(fileReader, writer); writer.close(); client.completePendingCommand(); } } fileReader.close(); client.logout(); client.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } } commons-net-2.2/src/main/java/examples/nntp/NNTPUtils.java0000644000175000017500000000770511354512541023460 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.nntp; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import java.util.StringTokenizer; import org.apache.commons.net.io.DotTerminatedMessageReader; import org.apache.commons.net.nntp.Article; import org.apache.commons.net.nntp.NNTPClient; /** * * Some convenience methods for NNTP example classes. * * @author Rory Winston */ public class NNTPUtils { /** * Given an {@link NNTPClient} instance, and an integer range of messages, return * an array of {@link Article} instances. * @param client * @param lowArticleNumber * @param highArticleNumber * @return Article[] An array of Article * @throws IOException */ public static List

getArticleInfo(NNTPClient client, long lowArticleNumber, long highArticleNumber) throws IOException { Reader reader = null; List
articles = new ArrayList
(); reader = (DotTerminatedMessageReader) client.retrieveArticleInfo( lowArticleNumber, highArticleNumber); if (reader != null) { String theInfo = readerToString(reader); StringTokenizer st = new StringTokenizer(theInfo, "\n"); // Extract the article information // Mandatory format (from NNTP RFC 2980) is : // Subject\tAuthor\tDate\tID\tReference(s)\tByte Count\tLine Count int count = st.countTokens(); int index = 0; while (st.hasMoreTokens()) { String msg = st.nextToken(); System.out.println("Message:" + msg); StringTokenizer stt = new StringTokenizer(msg, "\t"); try { Article article = new Article(); article.setArticleNumber(Integer.parseInt(stt.nextToken())); article.setSubject(stt.nextToken()); article.setFrom(stt.nextToken()); article.setDate(stt.nextToken()); article.setArticleId(stt.nextToken()); article.addHeaderField("References", stt.nextToken()); articles.add(article); } catch (NoSuchElementException nse) { // ignore this message } } } else { return null; } return articles; } /** * Convert a {@link Reader} instance to a String * @param reader The Reader instance * @return String */ public static String readerToString(Reader reader) { String temp = null; BufferedReader bufReader = new BufferedReader(reader); StringBuilder sb = new StringBuilder(); try { temp = bufReader.readLine(); while (temp != null) { sb.append(temp); sb.append("\n"); temp = bufReader.readLine(); } } catch (IOException e) { e.printStackTrace(); } return sb.toString(); } } commons-net-2.2/src/main/java/examples/nntp/MessageThreading.java0000644000175000017500000000532411200025274025055 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.nntp; import java.io.IOException; import java.io.PrintWriter; import java.net.SocketException; import java.util.List; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.nntp.Article; import org.apache.commons.net.nntp.NNTPClient; import org.apache.commons.net.nntp.NewsgroupInfo; import org.apache.commons.net.nntp.Threader; public class MessageThreading { public MessageThreading() { } public static void main(String[] args) throws SocketException, IOException { if (args.length != 3) usage(); String hostname = args[0]; String user = args[1]; String password = args[2]; NNTPClient client = new NNTPClient(); client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); client.connect(hostname); // optional authentication // // if(!client.authenticate(user, password)) { // System.out.println("Authentication failed for user " + user + "!"); // // System.exit(1); // } // NewsgroupInfo group = new NewsgroupInfo(); client.selectNewsgroup("alt.test", group); long lowArticleNumber = group.getFirstArticle(); long highArticleNumber = lowArticleNumber + 5000; System.out.println("Retrieving articles between [" + lowArticleNumber + "] and [" + highArticleNumber + "]"); List
articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber); System.out.println("Building message thread tree..."); Threader threader = new Threader(); Article root = (Article)threader.thread(articles); Article.printThread(root, 0); } public static void usage() { System.out.println("Usage: MessageThreading "); System.exit(0); } } commons-net-2.2/src/main/java/examples/nntp/ExtendedNNTPOps.java0000644000175000017500000000625411200025274024570 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.nntp; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.nntp.Article; import org.apache.commons.net.nntp.NNTPClient; import org.apache.commons.net.nntp.NewsgroupInfo; /** * Simple class showing some of the extended commands (AUTH, XOVER, LIST ACTIVE) * * @author Rory Winston */ public class ExtendedNNTPOps { NNTPClient client; public ExtendedNNTPOps() { client = new NNTPClient(); client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); } public void demo(String host, String user, String password) { try { client.connect(host); // AUTHINFO USER/AUTHINFO PASS boolean success = client.authenticate(user, password); if (success) { System.out.println("Authentication succeeded"); } else { System.out.println("Authentication failed, error =" + client.getReplyString()); } // XOVER NewsgroupInfo testGroup = new NewsgroupInfo(); client.selectNewsgroup("alt.test", testGroup); long lowArticleNumber = testGroup.getFirstArticle(); long highArticleNumber = lowArticleNumber + 100; List
articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber); for (Article article : articles) { System.out.println(article.getSubject()); } // LIST ACTIVE NewsgroupInfo[] fanGroups = client.listNewsgroups("alt.fan.*"); for (int i = 0; i < fanGroups.length; ++i) { System.out.println(fanGroups[i].getNewsgroup()); } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { ExtendedNNTPOps ops; if (args.length != 3) { System.err.println("usage: ExtendedNNTPOps nntpserver username password"); System.exit(1); } ops = new ExtendedNNTPOps(); ops.demo(args[0], args[1], args[2]); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/examples/nntp/ListNewsgroups.java0000644000175000017500000000502111165727332024663 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.nntp; import java.io.IOException; import org.apache.commons.net.nntp.NNTPClient; import org.apache.commons.net.nntp.NewsgroupInfo; /*** * This is a trivial example using the NNTP package to approximate the * Unix newsgroups command. It merely connects to the specified news * server and issues fetches the list of newsgroups stored by the server. * On servers that store a lot of newsgroups, this command can take a very * long time (listing upwards of 30,000 groups). *

***/ public final class ListNewsgroups { public final static void main(String[] args) { NNTPClient client; NewsgroupInfo[] list; if (args.length < 1) { System.err.println("Usage: newsgroups newsserver"); System.exit(1); } client = new NNTPClient(); try { client.connect(args[0]); list = client.listNewsgroups(); if (list != null) { for (int i = 0; i < list.length; i++) System.out.println(list[i].getNewsgroup()); } else { System.err.println("LIST command failed."); System.err.println("Server reply: " + client.getReplyString()); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (client.isConnected()) client.disconnect(); } catch (IOException e) { System.err.println("Error disconnecting from server."); e.printStackTrace(); System.exit(1); } } } } commons-net-2.2/src/main/java/examples/unix/0000755000175000017500000000000011617452467021024 5ustar twernertwernercommons-net-2.2/src/main/java/examples/unix/rexec.java0000644000175000017500000000603111165734447022774 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import org.apache.commons.net.bsd.RExecClient; import examples.util.IOUtil; /*** * This is an example program demonstrating how to use the RExecClient class. * This program connects to an rexec server and requests that the * given command be executed on the server. It then reads input from stdin * (this will be line buffered on most systems, so don't expect character * at a time interactivity), passing it to the remote process and writes * the process stdout and stderr to local stdout. *

* Example: java rexec myhost myusername mypassword "ps -aux" *

* Usage: rexec *

***/ // This class requires the IOUtil support class! public final class rexec { public static final void main(String[] args) { String server, username, password, command; RExecClient client; if (args.length != 4) { System.err.println( "Usage: rexec "); System.exit(1); return ; // so compiler can do proper flow control analysis } client = new RExecClient(); server = args[0]; username = args[1]; password = args[2]; command = args[3]; try { client.connect(server); } catch (IOException e) { System.err.println("Could not connect to server."); e.printStackTrace(); System.exit(1); } try { client.rexec(username, password, command); } catch (IOException e) { try { client.disconnect(); } catch (IOException f) {} e.printStackTrace(); System.err.println("Could not execute command."); System.exit(1); } IOUtil.readWrite(client.getInputStream(), client.getOutputStream(), System.in, System.out); try { client.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } System.exit(0); } } commons-net-2.2/src/main/java/examples/unix/finger.java0000644000175000017500000001057411165734447023147 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import org.apache.commons.net.finger.FingerClient; /*** * This is an example of how you would implement the finger command * in Java using NetComponents. The Java version is much shorter. * But keep in mind that the Unix finger command reads all sorts of * local files to output local finger information. This program only * queries the finger daemon. *

* The -l flag is used to request long output from the server. *

***/ public final class finger { public static final void main(String[] args) { boolean longOutput = false; int arg = 0, index; String handle, host; FingerClient finger; InetAddress address = null; // Get flags. If an invalid flag is present, exit with usage message. while (arg < args.length && args[arg].startsWith("-")) { if (args[arg].equals("-l")) longOutput = true; else { System.err.println("usage: finger [-l] [[[handle][@]] ...]"); System.exit(1); } ++arg; } finger = new FingerClient(); // We want to timeout if a response takes longer than 60 seconds finger.setDefaultTimeout(60000); if (arg >= args.length) { // Finger local host try { address = InetAddress.getLocalHost(); } catch (UnknownHostException e) { System.err.println("Error unknown host: " + e.getMessage()); System.exit(1); } try { finger.connect(address); System.out.print(finger.query(longOutput)); finger.disconnect(); } catch (IOException e) { System.err.println("Error I/O exception: " + e.getMessage()); System.exit(1); } return ; } // Finger each argument while (arg < args.length) { index = args[arg].lastIndexOf("@"); if (index == -1) { handle = args[arg]; try { address = InetAddress.getLocalHost(); } catch (UnknownHostException e) { System.err.println("Error unknown host: " + e.getMessage()); System.exit(1); } } else { handle = args[arg].substring(0, index); host = args[arg].substring(index + 1); try { address = InetAddress.getByName(host); } catch (UnknownHostException e) { System.err.println("Error unknown host: " + e.getMessage()); System.exit(1); } } System.out.println("[" + address.getHostName() + "]"); try { finger.connect(address); System.out.print(finger.query(longOutput, handle)); finger.disconnect(); } catch (IOException e) { System.err.println("Error I/O exception: " + e.getMessage()); System.exit(1); } ++arg; if (arg != args.length) System.out.print("\n"); } } } commons-net-2.2/src/main/java/examples/unix/fwhois.java0000644000175000017500000000475411165734447023177 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import org.apache.commons.net.whois.WhoisClient; /*** * This is an example of how you would implement the Linux fwhois command * in Java using NetComponents. The Java version is much shorter. *

***/ public final class fwhois { public static final void main(String[] args) { int index; String handle, host; InetAddress address = null; WhoisClient whois; if (args.length != 1) { System.err.println("usage: fwhois handle[@]"); System.exit(1); } index = args[0].lastIndexOf("@"); whois = new WhoisClient(); // We want to timeout if a response takes longer than 60 seconds whois.setDefaultTimeout(60000); if (index == -1) { handle = args[0]; host = WhoisClient.DEFAULT_HOST; } else { handle = args[0].substring(0, index); host = args[0].substring(index + 1); } try { address = InetAddress.getByName(host); } catch (UnknownHostException e) { System.err.println("Error unknown host: " + e.getMessage()); System.exit(1); } System.out.println("[" + address.getHostName() + "]"); try { whois.connect(address); System.out.print(whois.query(handle)); whois.disconnect(); } catch (IOException e) { System.err.println("Error I/O exception: " + e.getMessage()); System.exit(1); } } } commons-net-2.2/src/main/java/examples/unix/chargen.java0000644000175000017500000001127111165734447023277 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.net.InetAddress; import java.net.SocketException; import org.apache.commons.net.chargen.CharGenTCPClient; import org.apache.commons.net.chargen.CharGenUDPClient; /*** * This is an example program demonstrating how to use the CharGenTCPClient * and CharGenUDPClient classes. This program connects to the default * chargen service port of a specified server, then reads 100 lines from * of generated output, writing each line to standard output, and then * closes the connection. The UDP invocation of the program sends 50 * datagrams, printing the reply to each. * The default is to use the TCP port. Use the -udp flag to use the UDP * port. *

* Usage: chargen [-udp] *

***/ public final class chargen { public static final void chargenTCP(String host) throws IOException { int lines = 100; String line; CharGenTCPClient client = new CharGenTCPClient(); BufferedReader chargenInput; // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(host); chargenInput = new BufferedReader(new InputStreamReader(client.getInputStream())); // We assume the chargen service outputs lines, but it really doesn't // have to, so this code might actually not work if no newlines are // present. while (lines-- > 0) { if ((line = chargenInput.readLine()) == null) break; System.out.println(line); } client.disconnect(); } public static final void chargenUDP(String host) throws IOException { int packets = 50; byte[] data; InetAddress address; CharGenUDPClient client; address = InetAddress.getByName(host); client = new CharGenUDPClient(); client.open(); // If we don't receive a return packet within 5 seconds, assume // the packet is lost. client.setSoTimeout(5000); while (packets-- > 0) { client.send(address); try { data = client.receive(); } // Here we catch both SocketException and InterruptedIOException, // because even though the JDK 1.1 docs claim that // InterruptedIOException is thrown on a timeout, it seems // SocketException is also thrown. catch (SocketException e) { // We timed out and assume the packet is lost. System.err.println("SocketException: Timed out and dropped packet"); continue; } catch (InterruptedIOException e) { // We timed out and assume the packet is lost. System.err.println( "InterruptedIOException: Timed out and dropped packet"); continue; } System.out.write(data); System.out.flush(); } client.close(); } public static final void main(String[] args) { if (args.length == 1) { try { chargenTCP(args[0]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else if (args.length == 2 && args[0].equals("-udp")) { try { chargenUDP(args[1]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else { System.err.println("Usage: chargen [-udp] "); System.exit(1); } } } commons-net-2.2/src/main/java/examples/unix/rdate.java0000644000175000017500000000602611165734447022771 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import java.net.InetAddress; import org.apache.commons.net.time.TimeTCPClient; import org.apache.commons.net.time.TimeUDPClient; /*** * This is an example program demonstrating how to use the TimeTCPClient * and TimeUDPClient classes. It's very similar to the simple Unix rdate * command. This program connects to the default time service port of a * specified server, retrieves the time, and prints it to standard output. * The default is to use the TCP port. Use the -udp flag to use the UDP * port. You can test this program by using the NIST time server at * 132.163.135.130 (warning: the IP address may change). *

* Usage: rdate [-udp] *

*

* @author Daniel F. Savarese ***/ public final class rdate { public static final void timeTCP(String host) throws IOException { TimeTCPClient client = new TimeTCPClient(); // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(host); System.out.println(client.getDate().toString()); client.disconnect(); } public static final void timeUDP(String host) throws IOException { TimeUDPClient client = new TimeUDPClient(); // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.open(); System.out.println(client.getDate(InetAddress.getByName(host)).toString()); client.close(); } public static final void main(String[] args) { if (args.length == 1) { try { timeTCP(args[0]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else if (args.length == 2 && args[0].equals("-udp")) { try { timeUDP(args[1]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else { System.err.println("Usage: rdate [-udp] "); System.exit(1); } } } commons-net-2.2/src/main/java/examples/unix/daytime.java0000644000175000017500000000562311165734447023330 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import java.net.InetAddress; import org.apache.commons.net.daytime.DaytimeTCPClient; import org.apache.commons.net.daytime.DaytimeUDPClient; /*** * This is an example program demonstrating how to use the DaytimeTCP * and DaytimeUDP classes. * This program connects to the default daytime service port of a * specified server, retrieves the daytime, and prints it to standard output. * The default is to use the TCP port. Use the -udp flag to use the UDP * port. *

* Usage: daytime [-udp] *

***/ public final class daytime { public static final void daytimeTCP(String host) throws IOException { DaytimeTCPClient client = new DaytimeTCPClient(); // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(host); System.out.println(client.getTime().trim()); client.disconnect(); } public static final void daytimeUDP(String host) throws IOException { DaytimeUDPClient client = new DaytimeUDPClient(); // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.open(); System.out.println(client.getTime( InetAddress.getByName(host)).trim()); client.close(); } public static final void main(String[] args) { if (args.length == 1) { try { daytimeTCP(args[0]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else if (args.length == 2 && args[0].equals("-udp")) { try { daytimeUDP(args[1]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else { System.err.println("Usage: daytime [-udp] "); System.exit(1); } } } commons-net-2.2/src/main/java/examples/unix/echo.java0000644000175000017500000001244311165734447022610 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.SocketException; import org.apache.commons.net.echo.EchoTCPClient; import org.apache.commons.net.echo.EchoUDPClient; /*** * This is an example program demonstrating how to use the EchoTCPClient * and EchoUDPClient classes. This program connects to the default echo * service port of a specified server, then reads lines from standard * input, writing them to the echo server, and then printing the echo. * The default is to use the TCP port. Use the -udp flag to use the UDP * port. *

* Usage: echo [-udp] *

***/ public final class echo { public static final void echoTCP(String host) throws IOException { EchoTCPClient client = new EchoTCPClient(); BufferedReader input, echoInput; PrintWriter echoOutput; String line; // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(host); System.out.println("Connected to " + host + "."); input = new BufferedReader(new InputStreamReader(System.in)); echoOutput = new PrintWriter(new OutputStreamWriter(client.getOutputStream()), true); echoInput = new BufferedReader(new InputStreamReader(client.getInputStream())); while ((line = input.readLine()) != null) { echoOutput.println(line); System.out.println(echoInput.readLine()); } client.disconnect(); } public static final void echoUDP(String host) throws IOException { int length, count; byte[] data; String line; BufferedReader input; InetAddress address; EchoUDPClient client; input = new BufferedReader(new InputStreamReader(System.in)); address = InetAddress.getByName(host); client = new EchoUDPClient(); client.open(); // If we don't receive an echo within 5 seconds, assume the packet is lost. client.setSoTimeout(5000); System.out.println("Ready to echo to " + host + "."); // Remember, there are no guarantees about the ordering of returned // UDP packets, so there is a chance the output may be jumbled. while ((line = input.readLine()) != null) { data = line.getBytes(); client.send(data, address); count = 0; do { try { length = client.receive(data); } // Here we catch both SocketException and InterruptedIOException, // because even though the JDK 1.1 docs claim that // InterruptedIOException is thrown on a timeout, it seems // SocketException is also thrown. catch (SocketException e) { // We timed out and assume the packet is lost. System.err.println( "SocketException: Timed out and dropped packet"); break; } catch (InterruptedIOException e) { // We timed out and assume the packet is lost. System.err.println( "InterruptedIOException: Timed out and dropped packet"); break; } System.out.print(new String(data, 0, length)); count += length; } while (count < data.length); System.out.println(); } client.close(); } public static final void main(String[] args) { if (args.length == 1) { try { echoTCP(args[0]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else if (args.length == 2 && args[0].equals("-udp")) { try { echoUDP(args[1]); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } else { System.err.println("Usage: echo [-udp] "); System.exit(1); } } } commons-net-2.2/src/main/java/examples/unix/rlogin.java0000644000175000017500000000722511165734447023166 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import org.apache.commons.net.bsd.RLoginClient; import examples.util.IOUtil; /*** * This is an example program demonstrating how to use the RLoginClient * class. This program connects to an rlogin daemon and begins to * interactively read input from stdin (this will be line buffered on most * systems, so don't expect character at a time interactivity), passing it * to the remote login process and writing the remote stdout and stderr * to local stdout. If you don't have .rhosts or hosts.equiv files set up, * the rlogin daemon will prompt you for a password. *

* On Unix systems you will not be able to use the rshell capability * unless the process runs as root since only root can bind port addresses * lower than 1024. *

* JVM's using green threads will likely have problems if the rlogin daemon * requests a password. This program is merely a demonstration and is * not suitable for use as an application, especially given that it relies * on line buffered input from System.in. The best way to run this example * is probably from a Win95 dos box into a Unix host. *

* Example: java rlogin myhost localusername remoteusername vt100 *

* Usage: rlogin *

***/ // This class requires the IOUtil support class! public final class rlogin { public static final void main(String[] args) { String server, localuser, remoteuser, terminal; RLoginClient client; if (args.length != 4) { System.err.println( "Usage: rlogin "); System.exit(1); return ; // so compiler can do proper flow control analysis } client = new RLoginClient(); server = args[0]; localuser = args[1]; remoteuser = args[2]; terminal = args[3]; try { client.connect(server); } catch (IOException e) { System.err.println("Could not connect to server."); e.printStackTrace(); System.exit(1); } try { client.rlogin(localuser, remoteuser, terminal); } catch (IOException e) { try { client.disconnect(); } catch (IOException f) {} e.printStackTrace(); System.err.println("rlogin authentication failed."); System.exit(1); } IOUtil.readWrite(client.getInputStream(), client.getOutputStream(), System.in, System.out); try { client.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } System.exit(0); } } commons-net-2.2/src/main/java/examples/unix/rshell.java0000644000175000017500000000635611165734447023171 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.unix; import java.io.IOException; import org.apache.commons.net.bsd.RCommandClient; import examples.util.IOUtil; /*** * This is an example program demonstrating how to use the RCommandClient * class. This program connects to an rshell daemon and requests that the * given command be executed on the server. It then reads input from stdin * (this will be line buffered on most systems, so don't expect character * at a time interactivity), passing it to the remote process and writes * the process stdout and stderr to local stdout. *

* On Unix systems you will not be able to use the rshell capability * unless the process runs as root since only root can bind port addresses * lower than 1024. *

* Example: java rshell myhost localusername remoteusername "ps -aux" *

* Usage: rshell *

***/ // This class requires the IOUtil support class! public final class rshell { public static final void main(String[] args) { String server, localuser, remoteuser, command; RCommandClient client; if (args.length != 4) { System.err.println( "Usage: rshell "); System.exit(1); return ; // so compiler can do proper flow control analysis } client = new RCommandClient(); server = args[0]; localuser = args[1]; remoteuser = args[2]; command = args[3]; try { client.connect(server); } catch (IOException e) { System.err.println("Could not connect to server."); e.printStackTrace(); System.exit(1); } try { client.rcommand(localuser, remoteuser, command); } catch (IOException e) { try { client.disconnect(); } catch (IOException f) {} e.printStackTrace(); System.err.println("Could not execute command."); System.exit(1); } IOUtil.readWrite(client.getInputStream(), client.getOutputStream(), System.in, System.out); try { client.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } System.exit(0); } } commons-net-2.2/src/main/java/examples/cidr/0000755000175000017500000000000011617452467020762 5ustar twernertwernercommons-net-2.2/src/main/java/examples/cidr/SubnetUtilsExample.java0000644000175000017500000000642211165734447025425 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.cidr; import java.util.Arrays; import java.util.Scanner; import org.apache.commons.net.util.SubnetUtils; import org.apache.commons.net.util.SubnetUtils.SubnetInfo; /** * Example class that shows how to use the {@link SubnetUtils} class. * @author Rory Winston * */ public class SubnetUtilsExample { public static void main(String[] args) { String subnet = "192.168.0.3/31"; SubnetUtils utils = new SubnetUtils(subnet); SubnetInfo info = utils.getInfo(); System.out.printf("Subnet Information for %s:\n", subnet); System.out.println("--------------------------------------"); System.out.printf("IP Address:\t\t\t%s\t[%s]\n", info.getAddress(), Integer.toBinaryString(info.asInteger(info.getAddress()))); System.out.printf("Netmask:\t\t\t%s\t[%s]\n", info.getNetmask(), Integer.toBinaryString(info.asInteger(info.getNetmask()))); System.out.printf("CIDR Representation:\t\t%s\n\n", info.getCidrSignature()); System.out.printf("Supplied IP Address:\t\t%s\n\n", info.getAddress()); System.out.printf("Network Address:\t\t%s\t[%s]\n", info.getNetworkAddress(), Integer.toBinaryString(info.asInteger(info.getNetworkAddress()))); System.out.printf("Broadcast Address:\t\t%s\t[%s]\n", info.getBroadcastAddress(), Integer.toBinaryString(info.asInteger(info.getBroadcastAddress()))); System.out.printf("Low Address:\t\t\t%s\t[%s]\n", info.getLowAddress(), Integer.toBinaryString(info.asInteger(info.getLowAddress()))); System.out.printf("High Address:\t\t\t%s\t[%s]\n", info.getHighAddress(), Integer.toBinaryString(info.asInteger(info.getHighAddress()))); System.out.printf("Total usable addresses: \t%d\n", info.getAddressCount()); System.out.printf("Address List: %s\n\n", Arrays.toString(info.getAllAddresses())); final String prompt ="Enter an IP address (e.g. 192.168.0.10):"; System.out.println(prompt); Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { String address = scanner.nextLine(); System.out.println("The IP address [" + address + "] is " + (info.isInRange(address) ? "" : "not ") + "within the subnet [" + subnet + "]"); System.out.println(prompt); } } } commons-net-2.2/src/main/java/examples/telnet/0000755000175000017500000000000011617452467021334 5ustar twernertwernercommons-net-2.2/src/main/java/examples/telnet/WeatherTelnet.java0000644000175000017500000000442211165734447024753 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.telnet; import java.io.IOException; import org.apache.commons.net.telnet.TelnetClient; import examples.util.IOUtil; /*** * This is an example of a trivial use of the TelnetClient class. * It connects to the weather server at the University of Michigan, * um-weather.sprl.umich.edu port 3000, and allows the user to interact * with the server via standard input. You could use this example to * connect to any telnet server, but it is obviously not general purpose * because it reads from standard input a line at a time, making it * inconvenient for use with a remote interactive shell. The TelnetClient * class used by itself is mostly intended for automating access to telnet * resources rather than interactive use. *

***/ // This class requires the IOUtil support class! public final class WeatherTelnet { public final static void main(String[] args) { TelnetClient telnet; telnet = new TelnetClient(); try { telnet.connect("rainmaker.wunderground.com", 3000); } catch (IOException e) { e.printStackTrace(); System.exit(1); } IOUtil.readWrite(telnet.getInputStream(), telnet.getOutputStream(), System.in, System.out); try { telnet.disconnect(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } System.exit(0); } } commons-net-2.2/src/main/java/examples/telnet/TelnetClientExample.java0000644000175000017500000003206511165734447026112 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.telnet; import java.io.InputStream; import java.io.OutputStream; import java.io.FileOutputStream; import java.io.IOException; import org.apache.commons.net.telnet.TelnetClient; import org.apache.commons.net.telnet.TelnetNotificationHandler; import org.apache.commons.net.telnet.SimpleOptionHandler; import org.apache.commons.net.telnet.EchoOptionHandler; import org.apache.commons.net.telnet.TerminalTypeOptionHandler; import org.apache.commons.net.telnet.SuppressGAOptionHandler; import org.apache.commons.net.telnet.InvalidTelnetOptionException; import java.util.StringTokenizer; /*** * This is a simple example of use of TelnetClient. * An external option handler (SimpleTelnetOptionHandler) is used. * Initial configuration requested by TelnetClient will be: * WILL ECHO, WILL SUPPRESS-GA, DO SUPPRESS-GA. * VT100 terminal type will be subnegotiated. *

* Also, use of the sendAYT(), getLocalOptionState(), getRemoteOptionState() * is demonstrated. * When connected, type AYT to send an AYT command to the server and see * the result. * Type OPT to see a report of the state of the first 25 options. *

* @author Bruno D'Avanzo ***/ public class TelnetClientExample implements Runnable, TelnetNotificationHandler { static TelnetClient tc = null; /*** * Main for the TelnetClientExample. ***/ public static void main(String[] args) throws IOException { FileOutputStream fout = null; if(args.length < 1) { System.err.println("Usage: TelnetClientExample1 []"); System.exit(1); } String remoteip = args[0]; int remoteport; if (args.length > 1) { remoteport = (new Integer(args[1])).intValue(); } else { remoteport = 23; } try { fout = new FileOutputStream ("spy.log", true); } catch (Exception e) { System.err.println( "Exception while opening the spy file: " + e.getMessage()); } tc = new TelnetClient(); TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false); EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false); SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true); try { tc.addOptionHandler(ttopt); tc.addOptionHandler(echoopt); tc.addOptionHandler(gaopt); } catch (InvalidTelnetOptionException e) { System.err.println("Error registering option handlers: " + e.getMessage()); } while (true) { boolean end_loop = false; try { tc.connect(remoteip, remoteport); Thread reader = new Thread (new TelnetClientExample()); tc.registerNotifHandler(new TelnetClientExample()); System.out.println("TelnetClientExample"); System.out.println("Type AYT to send an AYT telnet command"); System.out.println("Type OPT to print a report of status of options (0-24)"); System.out.println("Type REGISTER to register a new SimpleOptionHandler"); System.out.println("Type UNREGISTER to unregister an OptionHandler"); System.out.println("Type SPY to register the spy (connect to port 3333 to spy)"); System.out.println("Type UNSPY to stop spying the connection"); reader.start(); OutputStream outstr = tc.getOutputStream(); byte[] buff = new byte[1024]; int ret_read = 0; do { try { ret_read = System.in.read(buff); if(ret_read > 0) { if((new String(buff, 0, ret_read)).startsWith("AYT")) { try { System.out.println("Sending AYT"); System.out.println("AYT response:" + tc.sendAYT(5000)); } catch (Exception e) { System.err.println("Exception waiting AYT response: " + e.getMessage()); } } else if((new String(buff, 0, ret_read)).startsWith("OPT")) { System.out.println("Status of options:"); for(int ii=0; ii<25; ii++) System.out.println("Local Option " + ii + ":" + tc.getLocalOptionState(ii) + " Remote Option " + ii + ":" + tc.getRemoteOptionState(ii)); } else if((new String(buff, 0, ret_read)).startsWith("REGISTER")) { StringTokenizer st = new StringTokenizer(new String(buff)); try { st.nextToken(); int opcode = (new Integer(st.nextToken())).intValue(); boolean initlocal = (new Boolean(st.nextToken())).booleanValue(); boolean initremote = (new Boolean(st.nextToken())).booleanValue(); boolean acceptlocal = (new Boolean(st.nextToken())).booleanValue(); boolean acceptremote = (new Boolean(st.nextToken())).booleanValue(); SimpleOptionHandler opthand = new SimpleOptionHandler(opcode, initlocal, initremote, acceptlocal, acceptremote); tc.addOptionHandler(opthand); } catch (Exception e) { if(e instanceof InvalidTelnetOptionException) { System.err.println("Error registering option: " + e.getMessage()); } else { System.err.println("Invalid REGISTER command."); System.err.println("Use REGISTER optcode initlocal initremote acceptlocal acceptremote"); System.err.println("(optcode is an integer.)"); System.err.println("(initlocal, initremote, acceptlocal, acceptremote are boolean)"); } } } else if((new String(buff, 0, ret_read)).startsWith("UNREGISTER")) { StringTokenizer st = new StringTokenizer(new String(buff)); try { st.nextToken(); int opcode = (new Integer(st.nextToken())).intValue(); tc.deleteOptionHandler(opcode); } catch (Exception e) { if(e instanceof InvalidTelnetOptionException) { System.err.println("Error unregistering option: " + e.getMessage()); } else { System.err.println("Invalid UNREGISTER command."); System.err.println("Use UNREGISTER optcode"); System.err.println("(optcode is an integer)"); } } } else if((new String(buff, 0, ret_read)).startsWith("SPY")) { try { tc.registerSpyStream(fout); } catch (Exception e) { System.err.println("Error registering the spy"); } } else if((new String(buff, 0, ret_read)).startsWith("UNSPY")) { tc.stopSpyStream(); } else { try { outstr.write(buff, 0 , ret_read); outstr.flush(); } catch (Exception e) { end_loop = true; } } } } catch (Exception e) { System.err.println("Exception while reading keyboard:" + e.getMessage()); end_loop = true; } } while((ret_read > 0) && (end_loop == false)); try { tc.disconnect(); } catch (Exception e) { System.err.println("Exception while connecting:" + e.getMessage()); } } catch (Exception e) { System.err.println("Exception while connecting:" + e.getMessage()); System.exit(1); } } } /*** * Callback method called when TelnetClient receives an option * negotiation command. *

* @param negotiation_code - type of negotiation command received * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT) *

* @param option_code - code of the option negotiated *

***/ public void receivedNegotiation(int negotiation_code, int option_code) { String command = null; if(negotiation_code == TelnetNotificationHandler.RECEIVED_DO) { command = "DO"; } else if(negotiation_code == TelnetNotificationHandler.RECEIVED_DONT) { command = "DONT"; } else if(negotiation_code == TelnetNotificationHandler.RECEIVED_WILL) { command = "WILL"; } else if(negotiation_code == TelnetNotificationHandler.RECEIVED_WONT) { command = "WONT"; } System.out.println("Received " + command + " for option code " + option_code); } /*** * Reader thread. * Reads lines from the TelnetClient and echoes them * on the screen. ***/ public void run() { InputStream instr = tc.getInputStream(); try { byte[] buff = new byte[1024]; int ret_read = 0; do { ret_read = instr.read(buff); if(ret_read > 0) { System.out.print(new String(buff, 0, ret_read)); } } while (ret_read >= 0); } catch (Exception e) { System.err.println("Exception while reading socket:" + e.getMessage()); } try { tc.disconnect(); } catch (Exception e) { System.err.println("Exception while closing telnet:" + e.getMessage()); } } } commons-net-2.2/src/main/java/examples/ftp/0000755000175000017500000000000011617452467020632 5ustar twernertwernercommons-net-2.2/src/main/java/examples/ftp/ServerToServerFTP.java0000644000175000017500000001510211165730111024765 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.ftp; import java.io.IOException; import java.io.PrintWriter; import java.net.InetAddress; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.ProtocolCommandListener; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; /*** * This is an example program demonstrating how to use the FTPClient class. * This program arranges a server to server file transfer that transfers * a file from host1 to host2. Keep in mind, this program might only work * if host2 is the same as the host you run it on (for security reasons, * some ftp servers only allow PORT commands to be issued with a host * argument equal to the client host). *

* Usage: ftp *

***/ public final class ServerToServerFTP { public static final void main(String[] args) { String server1, username1, password1, file1; String server2, username2, password2, file2; FTPClient ftp1, ftp2; ProtocolCommandListener listener; if (args.length < 8) { System.err.println( "Usage: ftp " ); System.exit(1); } server1 = args[0]; username1 = args[1]; password1 = args[2]; file1 = args[3]; server2 = args[4]; username2 = args[5]; password2 = args[6]; file2 = args[7]; listener = new PrintCommandListener(new PrintWriter(System.out)); ftp1 = new FTPClient(); ftp1.addProtocolCommandListener(listener); ftp2 = new FTPClient(); ftp2.addProtocolCommandListener(listener); try { int reply; ftp1.connect(server1); System.out.println("Connected to " + server1 + "."); reply = ftp1.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp1.disconnect(); System.err.println("FTP server1 refused connection."); System.exit(1); } } catch (IOException e) { if (ftp1.isConnected()) { try { ftp1.disconnect(); } catch (IOException f) { // do nothing } } System.err.println("Could not connect to server1."); e.printStackTrace(); System.exit(1); } try { int reply; ftp2.connect(server2); System.out.println("Connected to " + server2 + "."); reply = ftp2.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp2.disconnect(); System.err.println("FTP server2 refused connection."); System.exit(1); } } catch (IOException e) { if (ftp2.isConnected()) { try { ftp2.disconnect(); } catch (IOException f) { // do nothing } } System.err.println("Could not connect to server2."); e.printStackTrace(); System.exit(1); } __main: try { if (!ftp1.login(username1, password1)) { System.err.println("Could not login to " + server1); break __main; } if (!ftp2.login(username2, password2)) { System.err.println("Could not login to " + server2); break __main; } // Let's just assume success for now. ftp2.enterRemotePassiveMode(); ftp1.enterRemoteActiveMode(InetAddress.getByName(ftp2.getPassiveHost()), ftp2.getPassivePort()); // Although you would think the store command should be sent to server2 // first, in reality, ftp servers like wu-ftpd start accepting data // connections right after entering passive mode. Additionally, they // don't even send the positive preliminary reply until after the // transfer is completed (in the case of passive mode transfers). // Therefore, calling store first would hang waiting for a preliminary // reply. if (ftp1.remoteRetrieve(file1) && ftp2.remoteStoreUnique(file2)) { // if(ftp1.remoteRetrieve(file1) && ftp2.remoteStore(file2)) { // We have to fetch the positive completion reply. ftp1.completePendingCommand(); ftp2.completePendingCommand(); } else { System.err.println( "Couldn't initiate transfer. Check that filenames are valid."); break __main; } } catch (IOException e) { e.printStackTrace(); System.exit(1); } finally { try { if (ftp1.isConnected()) { ftp1.logout(); ftp1.disconnect(); } } catch (IOException e) { // do nothing } try { if (ftp2.isConnected()) { ftp2.logout(); ftp2.disconnect(); } } catch (IOException e) { // do nothing } } } } commons-net-2.2/src/main/java/examples/ftp/FTPSExample.java0000644000175000017500000001327311165730111023552 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.ftp; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.security.NoSuchAlgorithmException; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPConnectionClosedException; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.net.ftp.FTPSClient; /*** * This is an example program demonstrating how to use the FTPSClient class. * This program connects to an FTP server and retrieves the specified * file. If the -s flag is used, it stores the local file at the FTP server. * Just so you can see what's happening, all reply strings are printed. * If the -b flag is used, a binary transfer is assumed (default is ASCII). *

* Usage: ftp [-s] [-b] *

***/ public final class FTPSExample { public static final String USAGE = "Usage: ftp [-s] [-b] \n" + "\nDefault behavior is to download a file and use ASCII transfer mode.\n" + "\t-s store file on server (upload)\n" + "\t-b use binary transfer mode\n"; public static final void main(String[] args) throws NoSuchAlgorithmException { int base = 0; boolean storeFile = false, binaryTransfer = false, error = false; String server, username, password, remote, local; String protocol = "SSL"; // SSL/TLS FTPSClient ftps; for (base = 0; base < args.length; base++) { if (args[base].startsWith("-s")) storeFile = true; else if (args[base].startsWith("-b")) binaryTransfer = true; else break; } if ((args.length - base) != 5) { System.err.println(USAGE); System.exit(1); } server = args[base++]; username = args[base++]; password = args[base++]; remote = args[base++]; local = args[base]; ftps = new FTPSClient(protocol); ftps.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); try { int reply; ftps.connect(server); System.out.println("Connected to " + server + "."); // After connection attempt, you should check the reply code to verify // success. reply = ftps.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftps.disconnect(); System.err.println("FTP server refused connection."); System.exit(1); } } catch (IOException e) { if (ftps.isConnected()) { try { ftps.disconnect(); } catch (IOException f) { // do nothing } } System.err.println("Could not connect to server."); e.printStackTrace(); System.exit(1); } __main: try { ftps.setBufferSize(1000); if (!ftps.login(username, password)) { ftps.logout(); error = true; break __main; } System.out.println("Remote system is " + ftps.getSystemName()); if (binaryTransfer) ftps.setFileType(FTP.BINARY_FILE_TYPE); // Use passive mode as default because most of us are // behind firewalls these days. ftps.enterLocalPassiveMode(); if (storeFile) { InputStream input; input = new FileInputStream(local); ftps.storeFile(remote, input); input.close(); } else { OutputStream output; output = new FileOutputStream(local); ftps.retrieveFile(remote, output); output.close(); } ftps.logout(); } catch (FTPConnectionClosedException e) { error = true; System.err.println("Server closed connection."); e.printStackTrace(); } catch (IOException e) { error = true; e.printStackTrace(); } finally { if (ftps.isConnected()) { try { ftps.disconnect(); } catch (IOException f) { // do nothing } } } System.exit(error ? 1 : 0); } // end main } commons-net-2.2/src/main/java/examples/ftp/TFTPExample.java0000644000175000017500000002022411165730111023545 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.ftp; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.SocketException; import java.net.UnknownHostException; import org.apache.commons.net.tftp.TFTP; import org.apache.commons.net.tftp.TFTPClient; /*** * This is an example of a simple Java tftp client using NetComponents. * Notice how all of the code is really just argument processing and * error handling. *

* Usage: tftp [options] hostname localfile remotefile * hostname - The name of the remote host * localfile - The name of the local file to send or the name to use for * the received file * remotefile - The name of the remote file to receive or the name for * the remote server to use to name the local file being sent. * options: (The default is to assume -r -b) * -s Send a local file * -r Receive a remote file * -a Use ASCII transfer mode * -b Use binary transfer mode *

***/ public final class TFTPExample { static final String USAGE = "Usage: tftp [options] hostname localfile remotefile\n\n" + "hostname - The name of the remote host\n" + "localfile - The name of the local file to send or the name to use for\n" + "\tthe received file\n" + "remotefile - The name of the remote file to receive or the name for\n" + "\tthe remote server to use to name the local file being sent.\n\n" + "options: (The default is to assume -r -b)\n" + "\t-s Send a local file\n" + "\t-r Receive a remote file\n" + "\t-a Use ASCII transfer mode\n" + "\t-b Use binary transfer mode\n"; public final static void main(String[] args) { boolean receiveFile = true, closed; int transferMode = TFTP.BINARY_MODE, argc; String arg, hostname, localFilename, remoteFilename; TFTPClient tftp; // Parse options for (argc = 0; argc < args.length; argc++) { arg = args[argc]; if (arg.startsWith("-")) { if (arg.equals("-r")) receiveFile = true; else if (arg.equals("-s")) receiveFile = false; else if (arg.equals("-a")) transferMode = TFTP.ASCII_MODE; else if (arg.equals("-b")) transferMode = TFTP.BINARY_MODE; else { System.err.println("Error: unrecognized option."); System.err.print(USAGE); System.exit(1); } } else break; } // Make sure there are enough arguments if (args.length - argc != 3) { System.err.println("Error: invalid number of arguments."); System.err.print(USAGE); System.exit(1); } // Get host and file arguments hostname = args[argc]; localFilename = args[argc + 1]; remoteFilename = args[argc + 2]; // Create our TFTP instance to handle the file transfer. tftp = new TFTPClient(); // We want to timeout if a response takes longer than 60 seconds tftp.setDefaultTimeout(60000); // Open local socket try { tftp.open(); } catch (SocketException e) { System.err.println("Error: could not open local UDP socket."); System.err.println(e.getMessage()); System.exit(1); } // We haven't closed the local file yet. closed = false; // If we're receiving a file, receive, otherwise send. if (receiveFile) { FileOutputStream output = null; File file; file = new File(localFilename); // If file exists, don't overwrite it. if (file.exists()) { System.err.println("Error: " + localFilename + " already exists."); System.exit(1); } // Try to open local file for writing try { output = new FileOutputStream(file); } catch (IOException e) { tftp.close(); System.err.println("Error: could not open local file for writing."); System.err.println(e.getMessage()); System.exit(1); } // Try to receive remote file via TFTP try { tftp.receiveFile(remoteFilename, transferMode, output, hostname); } catch (UnknownHostException e) { System.err.println("Error: could not resolve hostname."); System.err.println(e.getMessage()); System.exit(1); } catch (IOException e) { System.err.println( "Error: I/O exception occurred while receiving file."); System.err.println(e.getMessage()); System.exit(1); } finally { // Close local socket and output file tftp.close(); try { output.close(); closed = true; } catch (IOException e) { closed = false; System.err.println("Error: error closing file."); System.err.println(e.getMessage()); } } if (!closed) System.exit(1); } else { // We're sending a file FileInputStream input = null; // Try to open local file for reading try { input = new FileInputStream(localFilename); } catch (IOException e) { tftp.close(); System.err.println("Error: could not open local file for reading."); System.err.println(e.getMessage()); System.exit(1); } // Try to send local file via TFTP try { tftp.sendFile(remoteFilename, transferMode, input, hostname); } catch (UnknownHostException e) { System.err.println("Error: could not resolve hostname."); System.err.println(e.getMessage()); System.exit(1); } catch (IOException e) { System.err.println( "Error: I/O exception occurred while sending file."); System.err.println(e.getMessage()); System.exit(1); } finally { // Close local socket and input file tftp.close(); try { input.close(); closed = true; } catch (IOException e) { closed = false; System.err.println("Error: error closing file."); System.err.println(e.getMessage()); } } if (!closed) System.exit(1); } } } commons-net-2.2/src/main/java/examples/ftp/FTPClientExample.java0000644000175000017500000001303511351143411024560 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 examples.ftp; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPConnectionClosedException; import org.apache.commons.net.ftp.FTPReply; /*** * This is an example program demonstrating how to use the FTPClient class. * This program connects to an FTP server and retrieves the specified * file. If the -s flag is used, it stores the local file at the FTP server. * Just so you can see what's happening, all reply strings are printed. * If the -b flag is used, a binary transfer is assumed (default is ASCII). *

* Usage: ftp [-s] [-b] *

***/ public final class FTPClientExample { public static final String USAGE = "Usage: ftp [-s] [-b] \n" + "\nDefault behavior is to download a file and use ASCII transfer mode.\n" + "\t-s store file on server (upload)\n" + "\t-b use binary transfer mode\n"; public static final void main(String[] args) { int base = 0; boolean storeFile = false, binaryTransfer = false, error = false; String server, username, password, remote, local; FTPClient ftp; for (base = 0; base < args.length; base++) { if (args[base].startsWith("-s")) storeFile = true; else if (args[base].startsWith("-b")) binaryTransfer = true; else break; } if ((args.length - base) != 5) { System.err.println(USAGE); System.exit(1); } server = args[base++]; username = args[base++]; password = args[base++]; remote = args[base++]; local = args[base]; ftp = new FTPClient(); ftp.addProtocolCommandListener(new PrintCommandListener( new PrintWriter(System.out))); try { int reply; ftp.connect(server); System.out.println("Connected to " + server + "."); // After connection attempt, you should check the reply code to verify // success. reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); System.err.println("FTP server refused connection."); System.exit(1); } } catch (IOException e) { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException f) { // do nothing } } System.err.println("Could not connect to server."); e.printStackTrace(); System.exit(1); } __main: try { if (!ftp.login(username, password)) { ftp.logout(); error = true; break __main; } System.out.println("Remote system is " + ftp.getSystemName()); if (binaryTransfer) ftp.setFileType(FTP.BINARY_FILE_TYPE); // Use passive mode as default because most of us are // behind firewalls these days. ftp.enterLocalPassiveMode(); if (storeFile) { InputStream input; input = new FileInputStream(local); ftp.storeFile(remote, input); input.close(); } else { OutputStream output; output = new FileOutputStream(local); ftp.retrieveFile(remote, output); output.close(); } ftp.logout(); } catch (FTPConnectionClosedException e) { error = true; System.err.println("Server closed connection."); e.printStackTrace(); } catch (IOException e) { error = true; e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException f) { // do nothing } } } System.exit(error ? 1 : 0); } // end main } commons-net-2.2/src/main/java/org/0000755000175000017500000000000011617452466017011 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/0000755000175000017500000000000011617452466020232 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/0000755000175000017500000000000011617452466021705 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/0000755000175000017500000000000011617452467022474 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/ntp/0000755000175000017500000000000011617452467023275 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/ntp/TimeInfo.java0000644000175000017500000002523311354710167025647 0ustar twernertwernerpackage org.apache.commons.net.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.util.ArrayList; import java.util.List; /** * Wrapper class to network time packet messages (NTP, etc) that computes * related timing info and stats. * * @author Jason Mathews, MITRE Corp * * @version $Revision: 929649 $ $Date: 2010-03-31 20:12:07 +0200 (Mi, 31. Mär 2010) $ */ public class TimeInfo { private final NtpV3Packet _message; private List _comments; private Long _delay; private Long _offset; /** * time at which time message packet was received by local machine */ private final long _returnTime; /** * flag indicating that the TimeInfo details was processed and delay/offset were computed */ private boolean _detailsComputed; /** * Create TimeInfo object with raw packet message and destination time received. * * @param message NTP message packet * @param returnTime destination receive time * @throws IllegalArgumentException if message is null */ public TimeInfo(NtpV3Packet message, long returnTime) { this(message, returnTime, null, true); } /** * Create TimeInfo object with raw packet message and destination time received. * * @param message NTP message packet * @param returnTime destination receive time * @param comments List of errors/warnings identified during processing * @throws IllegalArgumentException if message is null */ public TimeInfo(NtpV3Packet message, long returnTime, List comments) { this(message, returnTime, comments, true); } /** * Create TimeInfo object with raw packet message and destination time received. * Auto-computes details if computeDetails flag set otherwise this is delayed * until computeDetails() is called. Delayed computation is for fast * intialization when sub-millisecond timing is needed. * * @param msgPacket NTP message packet * @param returnTime destination receive time * @param doComputeDetails flag to pre-compute delay/offset values * @throws IllegalArgumentException if message is null */ public TimeInfo(NtpV3Packet msgPacket, long returnTime, boolean doComputeDetails) { this(msgPacket, returnTime, null, doComputeDetails); } /** * Create TimeInfo object with raw packet message and destination time received. * Auto-computes details if computeDetails flag set otherwise this is delayed * until computeDetails() is called. Delayed computation is for fast * intialization when sub-millisecond timing is needed. * * @param message NTP message packet * @param returnTime destination receive time * @param comments list of comments used to store errors/warnings with message * @param doComputeDetails flag to pre-compute delay/offset values * @throws IllegalArgumentException if message is null */ public TimeInfo(NtpV3Packet message, long returnTime, List comments, boolean doComputeDetails) { if (message == null) throw new IllegalArgumentException("message cannot be null"); this._returnTime = returnTime; this._message = message; this._comments = comments; if (doComputeDetails) computeDetails(); } /** * Add comment (error/warning) to list of comments associated * with processing of NTP parameters. If comment list not create * then one will be created. * * @param comment */ public void addComment(String comment) { if (_comments == null) { _comments = new ArrayList(); } _comments.add(comment); } /** * Compute and validate details of the NTP message packet. Computed * fields include the offset and delay. */ public void computeDetails() { if (_detailsComputed) { return; // details already computed - do nothing } _detailsComputed = true; if (_comments == null) { _comments = new ArrayList(); } TimeStamp origNtpTime = _message.getOriginateTimeStamp(); long origTime = origNtpTime.getTime(); // Receive Time is time request received by server (t2) TimeStamp rcvNtpTime = _message.getReceiveTimeStamp(); long rcvTime = rcvNtpTime.getTime(); // Transmit time is time reply sent by server (t3) TimeStamp xmitNtpTime = _message.getTransmitTimeStamp(); long xmitTime = xmitNtpTime.getTime(); /* * Round-trip network delay and local clock offset (or time drift) is calculated * according to this standard NTP equation: * * LocalClockOffset = ((ReceiveTimestamp - OriginateTimestamp) + * (TransmitTimestamp - DestinationTimestamp)) / 2 * * equations from RFC-1305 (NTPv3) * roundtrip delay = (t4 - t1) - (t3 - t2) * local clock offset = ((t2 - t1) + (t3 - t4)) / 2 * * It takes into account network delays and assumes that they are symmetrical. * * Note the typo in SNTP RFCs 1769/2030 which state that the delay * is (T4 - T1) - (T2 - T3) with the "T2" and "T3" switched. */ if (origNtpTime.ntpValue() == 0) { // without originate time cannot determine when packet went out // might be via a broadcast NTP packet... if (xmitNtpTime.ntpValue() != 0) { _offset = Long.valueOf(xmitTime - _returnTime); _comments.add("Error: zero orig time -- cannot compute delay"); } else _comments.add("Error: zero orig time -- cannot compute delay/offset"); } else if (rcvNtpTime.ntpValue() == 0 || xmitNtpTime.ntpValue() == 0) { _comments.add("Warning: zero rcvNtpTime or xmitNtpTime"); // assert destTime >= origTime since network delay cannot be negative if (origTime > _returnTime) _comments.add("Error: OrigTime > DestRcvTime"); else { // without receive or xmit time cannot figure out processing time // so delay is simply the network travel time _delay = Long.valueOf(_returnTime - origTime); } // TODO: is offset still valid if rcvNtpTime=0 || xmitNtpTime=0 ??? // Could always hash origNtpTime (sendTime) but if host doesn't set it // then it's an malformed ntp host anyway and we don't care? // If server is in broadcast mode then we never send out a query in first place... if (rcvNtpTime.ntpValue() != 0) { // xmitTime is 0 just use rcv time _offset = Long.valueOf(rcvTime - origTime); } else if (xmitNtpTime.ntpValue() != 0) { // rcvTime is 0 just use xmitTime time _offset = Long.valueOf(xmitTime - _returnTime); } } else { long delayValue = _returnTime - origTime; // assert xmitTime >= rcvTime: difference typically < 1ms if (xmitTime < rcvTime) { // server cannot send out a packet before receiving it... _comments.add("Error: xmitTime < rcvTime"); // time-travel not allowed } else { // subtract processing time from round-trip network delay long delta = xmitTime - rcvTime; // in normal cases the processing delta is less than // the total roundtrip network travel time. if (delta <= delayValue) { delayValue -= delta; // delay = (t4 - t1) - (t3 - t2) } else { // if delta - delayValue == 1 ms then it's a round-off error // e.g. delay=3ms, processing=4ms if (delta - delayValue == 1) { // delayValue == 0 -> local clock saw no tick change but destination clock did if (delayValue != 0) { _comments.add("Info: processing time > total network time by 1 ms -> assume zero delay"); delayValue = 0; } } else _comments.add("Warning: processing time > total network time"); } } _delay = Long.valueOf(delayValue); if (origTime > _returnTime) // assert destTime >= origTime _comments.add("Error: OrigTime > DestRcvTime"); _offset = Long.valueOf(((rcvTime - origTime) + (xmitTime - _returnTime)) / 2); } } /** * Return list of comments (if any) during processing of NTP packet. * * @return List or null if not yet computed */ public List getComments() { return _comments; } /** * Get round-trip network delay. If null then could not compute the delay. * * @return Long or null if delay not available. */ public Long getDelay() { return _delay; } /** * Get clock offset needed to adjust local clock to match remote clock. If null then could not * compute the offset. * * @return Long or null if offset not available. */ public Long getOffset() { return _offset; } /** * Returns NTP message packet. * * @return NTP message packet. */ public NtpV3Packet getMessage() { return _message; } /** * Returns time at which time message packet was received by local machine. * * @return packet return time. */ public long getReturnTime() { return _returnTime; } } commons-net-2.2/src/main/java/org/apache/commons/net/ntp/NtpUtils.java0000644000175000017500000000752211354512541025714 0ustar twernertwernerpackage org.apache.commons.net.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ /*** * Common NtpUtils Helper class. * * @author Jason Mathews, MITRE Corp * * @version $Revision: 929344 $ $Date: 2010-03-31 02:20:49 +0200 (Mi, 31. Mär 2010) $ */ public final class NtpUtils { /*** * Returns 32-bit integer address to IPv4 address string "%d.%d.%d.%d" format. * * @param address the 32-bit address * @return the raw IP address in a string format. */ public static String getHostAddress(int address) { return ((address >>> 24) & 0xFF) + "." + ((address >>> 16) & 0xFF) + "." + ((address >>> 8) & 0xFF) + "." + ((address >>> 0) & 0xFF); } /*** * Returns NTP packet reference identifier as IP address. * * @param packet NTP packet * @return the packet reference id (as IP address) in "%d.%d.%d.%d" format. */ public static String getRefAddress(NtpV3Packet packet) { int address = (packet == null) ? 0 : packet.getReferenceId(); return getHostAddress(address); } /*** * Get refId as reference clock string (e.g. GPS, WWV, LCL). If string is * invalid (non-ASCII character) then returns empty string "". * For details refer to the Comprehensive * List of Clock Drivers. * * @param message * @return reference clock string if primary NTP server */ public static String getReferenceClock(NtpV3Packet message) { if (message == null) return ""; int refId = message.getReferenceId(); if (refId == 0) return ""; StringBuilder buf = new StringBuilder(4); // start at highest-order byte (0x4c434c00 -> LCL) for (int shiftBits = 24; shiftBits >= 0; shiftBits -= 8) { char c = (char) ((refId >>> shiftBits) & 0xff); if (c == 0) break; // 0-terminated ASCII string if (!Character.isLetterOrDigit(c)) return ""; buf.append(c); } return buf.toString(); } /*** * Return human-readable name of message mode type (RFC 1305). * * @param mode * @return mode name */ public static String getModeName(int mode) { switch (mode) { case NtpV3Packet.MODE_RESERVED: return "Reserved"; case NtpV3Packet.MODE_SYMMETRIC_ACTIVE: return "Symmetric Active"; case NtpV3Packet.MODE_SYMMETRIC_PASSIVE: return "Symmetric Passive"; case NtpV3Packet.MODE_CLIENT: return "Client"; case NtpV3Packet.MODE_SERVER: return "Server"; case NtpV3Packet.MODE_BROADCAST: return "Broadcast"; case NtpV3Packet.MODE_CONTROL_MESSAGE: return "Control"; case NtpV3Packet.MODE_PRIVATE: return "Private"; default: return "Unknown"; } } } commons-net-2.2/src/main/java/org/apache/commons/net/ntp/TimeStamp.java0000644000175000017500000003761411354512541026042 0ustar twernertwernerpackage org.apache.commons.net.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.lang.ref.SoftReference; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; /*** * TimeStamp class represents the Network Time Protocol (NTP) timestamp * as defined in RFC-1305 and SNTP (RFC-2030). It is represented as a * 64-bit unsigned fixed-point number in seconds relative to 0-hour on 1-January-1900. * The 32-bit low-order bits are the fractional seconds whose precision is * about 200 picoseconds. Assumes overflow date when date passes MAX_LONG * and reverts back to 0 is 2036 and not 1900. Test for most significant * bit: if MSB=0 then 2036 basis is used otherwise 1900 if MSB=1. *

* Methods exist to convert NTP timestamps to and from the equivalent Java date * representation, which is the number of milliseconds since the standard base * time known as "the epoch", namely January 1, 1970, 00:00:00 GMT. *

* * @author Jason Mathews, MITRE Corp * @version $Revision: 929344 $ $Date: 2010-03-31 02:20:49 +0200 (Mi, 31. Mär 2010) $ * @see java.util.Date */ public class TimeStamp implements java.io.Serializable, Comparable { /** * baseline NTP time if bit-0=0 -> 7-Feb-2036 @ 06:28:16 UTC */ protected static final long msb0baseTime = 2085978496000L; /** * baseline NTP time if bit-0=1 -> 1-Jan-1900 @ 01:00:00 UTC */ protected static final long msb1baseTime = -2208988800000L; /** * Default NTP date string format. E.g. Fri, Sep 12 2003 21:06:23.860. * See java.text.SimpleDateFormat for code descriptions. */ public final static String NTP_DATE_FORMAT = "EEE, MMM dd yyyy HH:mm:ss.SSS"; /* * Caches for the DateFormatters used by various toString methods. */ private static SoftReference simpleFormatter = null; private static SoftReference utcFormatter = null; /** * NTP timestamp value: 64-bit unsigned fixed-point number as defined in RFC-1305 * with high-order 32 bits the seconds field and the low-order 32-bits the * fractional field. */ private final long ntpTime; private static final long serialVersionUID = 8139806907588338737L; // initialization of static time bases /* static { TimeZone utcZone = TimeZone.getTimeZone("UTC"); Calendar calendar = Calendar.getInstance(utcZone); calendar.set(1900, Calendar.JANUARY, 1, 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); msb1baseTime = calendar.getTime().getTime(); calendar.set(2036, Calendar.FEBRUARY, 7, 6, 28, 16); calendar.set(Calendar.MILLISECOND, 0); msb0baseTime = calendar.getTime().getTime(); } */ /*** * Constructs a newly allocated NTP timestamp object * that represents the native 64-bit long argument. */ public TimeStamp(long ntpTime) { this.ntpTime = ntpTime; } /*** * Constructs a newly allocated NTP timestamp object * that represents the value represented by the string * in hexdecimal form (e.g. "c1a089bd.fc904f6d"). * * @throws NumberFormatException - if the string does not contain a parsable timestamp. */ public TimeStamp(String s) throws NumberFormatException { ntpTime = decodeNtpHexString(s); } /*** * Constructs a newly allocated NTP timestamp object * that represents the Java Date argument. * * @param d - the Date to be represented by the Timestamp object. */ public TimeStamp(Date d) { ntpTime = (d == null) ? 0 : toNtpTime(d.getTime()); } /*** * Returns the value of this Timestamp as a long value. * * @return the 64-bit long value represented by this object. */ public long ntpValue() { return ntpTime; } /*** * Returns high-order 32-bits representing the seconds of this NTP timestamp. * * @return seconds represented by this NTP timestamp. */ public long getSeconds() { return (ntpTime >>> 32) & 0xffffffffL; } /*** * Returns low-order 32-bits representing the fractional seconds. * * @return fractional seconds represented by this NTP timestamp. */ public long getFraction() { return ntpTime & 0xffffffffL; } /*** * Convert NTP timestamp to Java standard time. * * @return NTP Timestamp in Java time */ public long getTime() { return getTime(ntpTime); } /*** * Convert NTP timestamp to Java Date object. * * @return NTP Timestamp in Java Date */ public Date getDate() { long time = getTime(ntpTime); return new Date(time); } /*** * Convert 64-bit NTP timestamp to Java standard time. * * Note that java time (milliseconds) by definition has less precision * then NTP time (picoseconds) so converting NTP timestamp to java time and back * to NTP timestamp loses precision. For example, Tue, Dec 17 2002 09:07:24.810 EST * is represented by a single Java-based time value of f22cd1fc8a, but its * NTP equivalent are all values ranging from c1a9ae1c.cf5c28f5 to c1a9ae1c.cf9db22c. * * @param ntpTimeValue * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT * represented by this NTP timestamp value. */ public static long getTime(long ntpTimeValue) { long seconds = (ntpTimeValue >>> 32) & 0xffffffffL; // high-order 32-bits long fraction = ntpTimeValue & 0xffffffffL; // low-order 32-bits // Use round-off on fractional part to preserve going to lower precision fraction = Math.round(1000D * fraction / 0x100000000L); /* * If the most significant bit (MSB) on the seconds field is set we use * a different time base. The following text is a quote from RFC-2030 (SNTP v4): * * If bit 0 is set, the UTC time is in the range 1968-2036 and UTC time * is reckoned from 0h 0m 0s UTC on 1 January 1900. If bit 0 is not set, * the time is in the range 2036-2104 and UTC time is reckoned from * 6h 28m 16s UTC on 7 February 2036. */ long msb = seconds & 0x80000000L; if (msb == 0) { // use base: 7-Feb-2036 @ 06:28:16 UTC return msb0baseTime + (seconds * 1000) + fraction; } else { // use base: 1-Jan-1900 @ 01:00:00 UTC return msb1baseTime + (seconds * 1000) + fraction; } } /*** * Helper method to convert Java time to NTP timestamp object. * Note that Java time (milliseconds) by definition has less precision * then NTP time (picoseconds) so converting Ntptime to Javatime and back * to Ntptime loses precision. For example, Tue, Dec 17 2002 09:07:24.810 * is represented by a single Java-based time value of f22cd1fc8a, but its * NTP equivalent are all values from c1a9ae1c.cf5c28f5 to c1a9ae1c.cf9db22c. * @param date the milliseconds since January 1, 1970, 00:00:00 GMT. * @return NTP timestamp object at the specified date. */ public static TimeStamp getNtpTime(long date) { return new TimeStamp(toNtpTime(date)); } /*** * Constructs a NTP timestamp object and initializes it so that * it represents the time at which it was allocated, measured to the * nearest millisecond. * @return NTP timestamp object set to the current time. * @see java.lang.System#currentTimeMillis() */ public static TimeStamp getCurrentTime() { return getNtpTime(System.currentTimeMillis()); } /*** * Convert NTP timestamp hexstring (e.g. "c1a089bd.fc904f6d") to the NTP * 64-bit unsigned fixed-point number. * * @return NTP 64-bit timestamp value. * @throws NumberFormatException - if the string does not contain a parsable timestamp. */ protected static long decodeNtpHexString(String s) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } int ind = s.indexOf('.'); if (ind == -1) { if (s.length() == 0) return 0; return Long.parseLong(s, 16) << 32; // no decimal } return Long.parseLong(s.substring(0, ind), 16) << 32 | Long.parseLong(s.substring(ind + 1), 16); } /*** * Parses the string argument as a NTP hexidecimal timestamp representation string * (e.g. "c1a089bd.fc904f6d"). * * @param s - hexstring. * @return the Timestamp represented by the argument in hexidecimal. * @throws NumberFormatException - if the string does not contain a parsable timestamp. */ public static TimeStamp parseNtpString(String s) throws NumberFormatException { return new TimeStamp(decodeNtpHexString(s)); } /*** * Converts Java time to 64-bit NTP time representation. * * @param t Java time * @return NTP timestamp representation of Java time value. */ protected static long toNtpTime(long t) { boolean useBase1 = t < msb0baseTime; // time < Feb-2036 long baseTime; if (useBase1) { baseTime = t - msb1baseTime; // dates <= Feb-2036 } else { // if base0 needed for dates >= Feb-2036 baseTime = t - msb0baseTime; } long seconds = baseTime / 1000; long fraction = ((baseTime % 1000) * 0x100000000L) / 1000; if (useBase1) { seconds |= 0x80000000L; // set high-order bit if msb1baseTime 1900 used } long time = seconds << 32 | fraction; return time; } /*** * Computes a hashcode for this Timestamp. The result is the exclusive * OR of the two halves of the primitive long value * represented by this TimeStamp object. That is, the hashcode * is the value of the expression: *
     * (int)(this.ntpValue()^(this.ntpValue() >>> 32))
     * 
* * @return a hash code value for this object. */ @Override public int hashCode() { return (int) (ntpTime ^ (ntpTime >>> 32)); } /*** * Compares this object against the specified object. * The result is true if and only if the argument is * not null and is a Long object that * contains the same long value as this object. * * @param obj the object to compare with. * @return true if the objects are the same; * false otherwise. */ @Override public boolean equals(Object obj) { if (obj instanceof TimeStamp) { return ntpTime == ((TimeStamp) obj).ntpValue(); } return false; } /*** * Converts this TimeStamp object to a String. * The NTP timestamp 64-bit long value is represented as hex string with * seconds separated by fractional seconds by a decimal point; * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986 * * @return NTP timestamp 64-bit long value as hex string with seconds * separated by fractional seconds. */ @Override public String toString() { return toString(ntpTime); } /*** * Left-pad 8-character hex string with 0's * * @param buf - StringBuilder which is appended with leading 0's. * @param l - a long. */ private static void appendHexString(StringBuilder buf, long l) { String s = Long.toHexString(l); for (int i = s.length(); i < 8; i++) buf.append('0'); buf.append(s); } /*** * Converts 64-bit NTP timestamp value to a String. * The NTP timestamp value is represented as hex string with * seconds separated by fractional seconds by a decimal point; * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986 * * @return NTP timestamp 64-bit long value as hex string with seconds * separated by fractional seconds. */ public static String toString(long ntpTime) { StringBuilder buf = new StringBuilder(); // high-order second bits (32..63) as hexstring appendHexString(buf, (ntpTime >>> 32) & 0xffffffffL); // low-order fractional seconds bits (0..31) as hexstring buf.append('.'); appendHexString(buf, ntpTime & 0xffffffffL); return buf.toString(); } /*** * Converts this TimeStamp object to a String * of the form: *
     * EEE, MMM dd yyyy HH:mm:ss.SSS
* See java.text.SimpleDataFormat for code descriptions. * * @return a string representation of this date. */ public String toDateString() { DateFormat formatter = null; if (simpleFormatter != null) { formatter = simpleFormatter.get(); } if (formatter == null) { // No cache yet, or cached formatter GC'd formatter = new SimpleDateFormat(NTP_DATE_FORMAT, Locale.US); formatter.setTimeZone(TimeZone.getDefault()); simpleFormatter = new SoftReference(formatter); } Date ntpDate = getDate(); synchronized (formatter) { return formatter.format(ntpDate); } } /*** * Converts this TimeStamp object to a String * of the form: *
     * EEE, MMM dd yyyy HH:mm:ss.SSS UTC
* See java.text.SimpleDataFormat for code descriptions. * * @return a string representation of this date in UTC. */ public String toUTCString() { DateFormat formatter = null; if (utcFormatter != null) formatter = utcFormatter.get(); if (formatter == null) { // No cache yet, or cached formatter GC'd formatter = new SimpleDateFormat(NTP_DATE_FORMAT + " 'UTC'", Locale.US); formatter.setTimeZone(TimeZone.getTimeZone("UTC")); utcFormatter = new SoftReference(formatter); } Date ntpDate = getDate(); synchronized (formatter) { return formatter.format(ntpDate); } } /*** * Compares two Timestamps numerically. * * @param anotherTimeStamp - the TimeStamp to be compared. * @return the value 0 if the argument TimeStamp is equal to * this TimeStamp; a value less than 0 if this TimeStamp * is numerically less than the TimeStamp argument; and a * value greater than 0 if this TimeStamp is * numerically greater than the TimeStamp argument * (signed comparison). */ public int compareTo(TimeStamp anotherTimeStamp) { long thisVal = this.ntpTime; long anotherVal = anotherTimeStamp.ntpTime; return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); } } commons-net-2.2/src/main/java/org/apache/commons/net/ntp/NtpV3Packet.java0000644000175000017500000001450710542533103026230 0ustar twernertwernerpackage org.apache.commons.net.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.net.DatagramPacket; /** * Interface for a NtpV3Packet with get/set methods corresponding to the fields * in the NTP Data Message Header described in RFC 1305. * * @author Naz Irizarry, MITRE Corp * @author Jason Mathews, MITRE Corp * @version $Revision: 489397 $ $Date: 2006-12-21 17:28:51 +0100 (Do, 21. Dez 2006) $ */ public interface NtpV3Packet { /** * Standard NTP UDP port */ public static final int NTP_PORT = 123; public static final int LI_NO_WARNING = 0; public static final int LI_LAST_MINUTE_HAS_61_SECONDS = 1; public static final int LI_LAST_MINUTE_HAS_59_SECONDS = 2; public static final int LI_ALARM_CONDITION = 3; /* mode options */ public static final int MODE_RESERVED = 0; public static final int MODE_SYMMETRIC_ACTIVE = 1; public static final int MODE_SYMMETRIC_PASSIVE = 2; public static final int MODE_CLIENT = 3; public static final int MODE_SERVER = 4; public static final int MODE_BROADCAST = 5; public static final int MODE_CONTROL_MESSAGE = 6; public static final int MODE_PRIVATE = 7; public static final int NTP_MINPOLL = 4; // 16 seconds public static final int NTP_MAXPOLL = 14; // 16284 seconds public static final int NTP_MINCLOCK = 1; public static final int NTP_MAXCLOCK = 10; public static final int VERSION_3 = 3; public static final int VERSION_4 = 4; /* possible getType values such that other time-related protocols can * have its information represented as NTP packets */ public static final String TYPE_NTP = "NTP"; // RFC-1305/2030 public static final String TYPE_ICMP = "ICMP"; // RFC-792 public static final String TYPE_TIME = "TIME"; // RFC-868 public static final String TYPE_DAYTIME = "DAYTIME"; // RFC-867 /** * @return a datagram packet with the NTP parts already filled in */ public DatagramPacket getDatagramPacket(); /** * Set the contents of this object from the datagram packet */ public void setDatagramPacket(DatagramPacket dp); /** * @return leap indicator as defined in RFC-1305 */ public int getLeapIndicator(); /** * Set leap indicator. * @param li - leap indicator code */ public void setLeapIndicator(int li); /** * @return mode as defined in RFC-1305 */ public int getMode(); /** * @return mode as human readable string; e.g. 3=Client */ public String getModeName(); /** * Set mode as defined in RFC-1305 */ public void setMode(int mode); /** * @return poll interval as defined in RFC-1305. * Field range between NTP_MINPOLL and NTP_MAXPOLL. */ public int getPoll(); /** * Set poll interval as defined in RFC-1305. * Field range between NTP_MINPOLL and NTP_MAXPOLL. */ public void setPoll(int poll); /** * @return precision as defined in RFC-1305 */ public int getPrecision(); /** * @return root delay as defined in RFC-1305 */ public int getRootDelay(); /** * @return root delay in milliseconds */ public double getRootDelayInMillisDouble(); /** * @return root dispersion as defined in RFC-1305 */ public int getRootDispersion(); /** * @return root dispersion in milliseconds */ public long getRootDispersionInMillis(); /** * @return root dispersion in milliseconds */ public double getRootDispersionInMillisDouble(); /** * @return version as defined in RFC-1305 */ public int getVersion(); /** * Set version as defined in RFC-1305 */ public void setVersion(int mode); /** * @return stratum as defined in RFC-1305 */ public int getStratum(); /** * Set stratum as defined in RFC-1305 */ public void setStratum(int stratum); /** * @return the reference id string */ public String getReferenceIdString(); /** * @return the reference id (32-bit code) as defined in RFC-1305 */ public int getReferenceId(); /** * Set reference clock identifier field. * @param refId */ public void setReferenceId(int refId); /** * @return the transmit timestamp as defined in RFC-1305 */ public TimeStamp getTransmitTimeStamp(); /** * @return the reference time as defined in RFC-1305 */ public TimeStamp getReferenceTimeStamp(); /** * @return the originate time as defined in RFC-1305 */ public TimeStamp getOriginateTimeStamp(); /** * @return the receive time as defined in RFC-1305 */ public TimeStamp getReceiveTimeStamp(); /** * Set the transmit timestamp given NTP TimeStamp object. * @param ts - timestamp */ public void setTransmitTime(TimeStamp ts); /** * Set the reference timestamp given NTP TimeStamp object. * @param ts - timestamp */ public void setReferenceTime(TimeStamp ts); /** * Set originate timestamp given NTP TimeStamp object. * @param ts - timestamp */ public void setOriginateTimeStamp(TimeStamp ts); /** * Set receive timestamp given NTP TimeStamp object. * @param ts - timestamp */ public void setReceiveTimeStamp(TimeStamp ts); /** * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...) * correspond to the protocol used to obtain the timing information. * * @return packet type string identifier */ public String getType(); } commons-net-2.2/src/main/java/org/apache/commons/net/ntp/NTPUDPClient.java0000644000175000017500000001251610542533103026275 0ustar twernertwernerpackage org.apache.commons.net.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import org.apache.commons.net.DatagramSocketClient; /*** * The NTPUDPClient class is a UDP implementation of a client for the * Network Time Protocol (NTP) described in RFC 1305 as well as the * Simple Network Time Protocol (SNTP) in RFC-2030. To use the class, * merely open a local datagram socket with open * and call getTime to retrieve the time. Then call * close * to close the connection properly. * Successive calls to getTime are permitted * without re-establishing a connection. That is because UDP is a * connectionless protocol and the Network Time Protocol is stateless. * * @author Jason Mathews, MITRE Corp * @version $Revision: 489397 $ $Date: 2006-12-21 17:28:51 +0100 (Do, 21. Dez 2006) $ ***/ public final class NTPUDPClient extends DatagramSocketClient { /*** The default NTP port. It is set to 123 according to RFC 1305. ***/ public static final int DEFAULT_PORT = 123; private int _version = NtpV3Packet.VERSION_3; /*** * Retrieves the time information from the specified server and port and * returns it. The time is the number of miliiseconds since * 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305. * This method reads the raw NTP packet and constructs a TimeInfo * object that allows access to all the fields of the NTP message header. *

* @param host The address of the server. * @param port The port of the service. * @return The time value retrieved from the server. * @exception IOException If an error occurs while retrieving the time. ***/ public TimeInfo getTime(InetAddress host, int port) throws IOException { // if not connected then open to next available UDP port if (!isOpen()) { open(); } NtpV3Packet message = new NtpV3Impl(); message.setMode(NtpV3Packet.MODE_CLIENT); message.setVersion(_version); DatagramPacket sendPacket = message.getDatagramPacket(); sendPacket.setAddress(host); sendPacket.setPort(port); NtpV3Packet recMessage = new NtpV3Impl(); DatagramPacket receivePacket = recMessage.getDatagramPacket(); /* * Must minimize the time between getting the current time, * timestamping the packet, and sending it out which * introduces an error in the delay time. * No extraneous logging and initializations here !!! */ TimeStamp now = TimeStamp.getCurrentTime(); // Note that if you do not set the transmit time field then originating time // in server response is all 0's which is "Thu Feb 07 01:28:16 EST 2036". message.setTransmitTime(now); _socket_.send(sendPacket); _socket_.receive(receivePacket); long returnTime = System.currentTimeMillis(); // create TimeInfo message container but don't pre-compute the details yet TimeInfo info = new TimeInfo(recMessage, returnTime, false); return info; } /*** * Retrieves the time information from the specified server on the * default NTP port and returns it. The time is the number of miliiseconds * since 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305. * This method reads the raw NTP packet and constructs a TimeInfo * object that allows access to all the fields of the NTP message header. *

* @param host The address of the server. * @return The time value retrieved from the server. * @exception IOException If an error occurs while retrieving the time. ***/ public TimeInfo getTime(InetAddress host) throws IOException { return getTime(host, NtpV3Packet.NTP_PORT); } /*** * Returns the NTP protocol version number that client sets on request packet * that is sent to remote host (e.g. 3=NTP v3, 4=NTP v4, etc.) * * @return the NTP protocol version number that client sets on request packet. * @see #setVersion(int) ***/ public int getVersion() { return _version; } /*** * Sets the NTP protocol version number that client sets on request packet * communicate with remote host. * * @param version the NTP protocol version number ***/ public void setVersion(int version) { _version = version; } } commons-net-2.2/src/main/java/org/apache/commons/net/ntp/NtpV3Impl.java0000644000175000017500000004007611354710167025733 0ustar twernertwernerpackage org.apache.commons.net.ntp; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.net.DatagramPacket; /*** * Implementation of NtpV3Packet with methods converting Java objects to/from * the Network Time Protocol (NTP) data message header format described in RFC-1305. * * @author Naz Irizarry, MITRE Corp * @author Jason Mathews, MITRE Corp * * @version $Revision: 929649 $ $Date: 2010-03-31 20:12:07 +0200 (Mi, 31. Mär 2010) $ */ public class NtpV3Impl implements NtpV3Packet { private static final int MODE_INDEX = 0; private static final int MODE_SHIFT = 0; private static final int VERSION_INDEX = 0; private static final int VERSION_SHIFT = 3; private static final int LI_INDEX = 0; private static final int LI_SHIFT = 6; private static final int STRATUM_INDEX = 1; private static final int POLL_INDEX = 2; private static final int PRECISION_INDEX = 3; private static final int ROOT_DELAY_INDEX = 4; private static final int ROOT_DISPERSION_INDEX = 8; private static final int REFERENCE_ID_INDEX = 12; private static final int REFERENCE_TIMESTAMP_INDEX = 16; private static final int ORIGINATE_TIMESTAMP_INDEX = 24; private static final int RECEIVE_TIMESTAMP_INDEX = 32; private static final int TRANSMIT_TIMESTAMP_INDEX = 40; private static final int KEY_IDENTIFIER_INDEX = 48; private static final int MESSAGE_DIGEST = 54; /* len 16 bytes */ private final byte[] buf = new byte[48]; private volatile DatagramPacket dp; /** Creates a new instance of NtpV3Impl */ public NtpV3Impl() { } /*** * Returns mode as defined in RFC-1305 which is a 3-bit integer * whose value is indicated by the MODE_xxx parameters. * * @return mode as defined in RFC-1305. */ public int getMode() { return (ui(buf[MODE_INDEX]) >> MODE_SHIFT) & 0x7; } /*** * Return human-readable name of message mode type as described in * RFC 1305. * @return mode name as string. */ public String getModeName() { return NtpUtils.getModeName(getMode()); } /*** * Set mode as defined in RFC-1305. * @param mode */ public void setMode(int mode) { buf[MODE_INDEX] = (byte) (buf[MODE_INDEX] & 0xF8 | mode & 0x7); } /*** * Returns leap indicator as defined in RFC-1305 which is a two-bit code: * 0=no warning * 1=last minute has 61 seconds * 2=last minute has 59 seconds * 3=alarm condition (clock not synchronized) * * @return leap indicator as defined in RFC-1305. */ public int getLeapIndicator() { return (ui(buf[LI_INDEX]) >> LI_SHIFT) & 0x3; } /*** * Set leap indicator as defined in RFC-1305. * @param li leap indicator. */ public void setLeapIndicator(int li) { buf[LI_INDEX] = (byte) (buf[LI_INDEX] & 0x3F | ((li & 0x3) << LI_SHIFT)); } /*** * Returns poll interval as defined in RFC-1305, which is an eight-bit * signed integer indicating the maximum interval between successive * messages, in seconds to the nearest power of two (e.g. value of six * indicates an interval of 64 seconds. The values that can appear in * this field range from NTP_MINPOLL to NTP_MAXPOLL inclusive. * * @return poll interval as defined in RFC-1305. */ public int getPoll() { return buf[POLL_INDEX]; } /*** * Set poll interval as defined in RFC-1305. * * @param poll poll interval. */ public void setPoll(int poll) { buf[POLL_INDEX] = (byte) (poll & 0xFF); } /*** * Returns precision as defined in RFC-1305 encoded as an 8-bit signed * integer (seconds to nearest power of two). * Values normally range from -6 to -20. * * @return precision as defined in RFC-1305. */ public int getPrecision() { return buf[PRECISION_INDEX]; } /*** * Set precision as defined in RFC-1305. * @param precision */ public void setPrecision(int precision) { buf[PRECISION_INDEX] = (byte) (precision & 0xFF); } /*** * Returns NTP version number as defined in RFC-1305. * * @return NTP version number. */ public int getVersion() { return (ui(buf[VERSION_INDEX]) >> VERSION_SHIFT) & 0x7; } /*** * Set NTP version as defined in RFC-1305. * * @param version NTP version. */ public void setVersion(int version) { buf[VERSION_INDEX] = (byte) (buf[VERSION_INDEX] & 0xC7 | ((version & 0x7) << VERSION_SHIFT)); } /*** * Returns Stratum as defined in RFC-1305, which indicates the stratum level * of the local clock, with values defined as follows: 0=unspecified, * 1=primary ref clock, and all others a secondary reference (via NTP). * * @return Stratum level as defined in RFC-1305. */ public int getStratum() { return ui(buf[STRATUM_INDEX]); } /*** * Set stratum level as defined in RFC-1305. * * @param stratum stratum level. */ public void setStratum(int stratum) { buf[STRATUM_INDEX] = (byte) (stratum & 0xFF); } /*** * Return root delay as defined in RFC-1305, which is the total roundtrip delay * to the primary reference source, in seconds. Values can take positive and * negative values, depending on clock precision and skew. * * @return root delay as defined in RFC-1305. */ public int getRootDelay() { return getInt(ROOT_DELAY_INDEX); } /*** * Return root delay as defined in RFC-1305 in milliseconds, which is * the total roundtrip delay to the primary reference source, in * seconds. Values can take positive and negative values, depending * on clock precision and skew. * * @return root delay in milliseconds */ public double getRootDelayInMillisDouble() { double l = getRootDelay(); return l / 65.536; } /*** * Returns root dispersion as defined in RFC-1305. * @return root dispersion. */ public int getRootDispersion() { return getInt(ROOT_DISPERSION_INDEX); } /*** * Returns root dispersion (as defined in RFC-1305) in milliseconds. * * @return root dispersion in milliseconds */ public long getRootDispersionInMillis() { long l = getRootDispersion(); return (l * 1000) / 65536L; } /*** * Returns root dispersion (as defined in RFC-1305) in milliseconds * as double precision value. * * @return root dispersion in milliseconds */ public double getRootDispersionInMillisDouble() { double l = getRootDispersion(); return l / 65.536; } /*** * Set reference clock identifier field with 32-bit unsigned integer value. * See RFC-1305 for description. * * @param refId reference clock identifier. */ public void setReferenceId(int refId) { for (int i = 3; i >= 0; i--) { buf[REFERENCE_ID_INDEX + i] = (byte) (refId & 0xff); refId >>>= 8; // shift right one-byte } } /*** * Returns the reference id as defined in RFC-1305, which is * a 32-bit integer whose value is dependent on several criteria. * * @return the reference id as defined in RFC-1305. */ public int getReferenceId() { return getInt(REFERENCE_ID_INDEX); } /*** * Returns the reference id string. String cannot be null but * value is dependent on the version of the NTP spec supported * and stratum level. Value can be an empty string, clock type string, * IP address, or a hex string. * * @return the reference id string. */ public String getReferenceIdString() { int version = getVersion(); int stratum = getStratum(); if (version == VERSION_3 || version == VERSION_4) { if (stratum == 0 || stratum == 1) { return idAsString(); // 4-character ASCII string (e.g. GPS, USNO) } // in NTPv4 servers this is latest transmit timestamp of ref source if (version == VERSION_4) return idAsHex(); } // Stratum 2 and higher this is a four-octet IPv4 address // of the primary reference host. if (stratum >= 2) { return idAsIPAddress(); } return idAsHex(); } /*** * Returns Reference id as dotted IP address. * @return refId as IP address string. */ private String idAsIPAddress() { return ui(buf[REFERENCE_ID_INDEX]) + "." + ui(buf[REFERENCE_ID_INDEX + 1]) + "." + ui(buf[REFERENCE_ID_INDEX + 2]) + "." + ui(buf[REFERENCE_ID_INDEX + 3]); } private String idAsString() { StringBuilder id = new StringBuilder(); for (int i = 0; i <= 3; i++) { char c = (char) buf[REFERENCE_ID_INDEX + i]; if (c == 0) break; // 0-terminated string id.append(c); } return id.toString(); } private String idAsHex() { return Integer.toHexString(getReferenceId()); } /*** * Returns the transmit timestamp as defined in RFC-1305. * * @return the transmit timestamp as defined in RFC-1305. * Never returns a null object. */ public TimeStamp getTransmitTimeStamp() { return getTimestamp(TRANSMIT_TIMESTAMP_INDEX); } /*** * Set transmit time with NTP timestamp. * If ts is null then zero time is used. * * @param ts NTP timestamp */ public void setTransmitTime(TimeStamp ts) { setTimestamp(TRANSMIT_TIMESTAMP_INDEX, ts); } /*** * Set originate timestamp given NTP TimeStamp object. * If ts is null then zero time is used. * * @param ts NTP timestamp */ public void setOriginateTimeStamp(TimeStamp ts) { setTimestamp(ORIGINATE_TIMESTAMP_INDEX, ts); } /*** * Returns the originate time as defined in RFC-1305. * * @return the originate time. * Never returns null. */ public TimeStamp getOriginateTimeStamp() { return getTimestamp(ORIGINATE_TIMESTAMP_INDEX); } /*** * Returns the reference time as defined in RFC-1305. * * @return the reference time as TimeStamp object. * Never returns null. */ public TimeStamp getReferenceTimeStamp() { return getTimestamp(REFERENCE_TIMESTAMP_INDEX); } /*** * Set Reference time with NTP timestamp. If ts is null * then zero time is used. * * @param ts NTP timestamp */ public void setReferenceTime(TimeStamp ts) { setTimestamp(REFERENCE_TIMESTAMP_INDEX, ts); } /*** * Returns receive timestamp as defined in RFC-1305. * * @return the receive time. * Never returns null. */ public TimeStamp getReceiveTimeStamp() { return getTimestamp(RECEIVE_TIMESTAMP_INDEX); } /*** * Set receive timestamp given NTP TimeStamp object. * If ts is null then zero time is used. * * @param ts timestamp */ public void setReceiveTimeStamp(TimeStamp ts) { setTimestamp(RECEIVE_TIMESTAMP_INDEX, ts); } /*** * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...) * correspond to the protocol used to obtain the timing information. * * @return packet type string identifier which in this case is "NTP". */ public String getType() { return "NTP"; } /*** * @return 4 bytes as 32-bit int */ private int getInt(int index) { int i = ui(buf[index]) << 24 | ui(buf[index + 1]) << 16 | ui(buf[index + 2]) << 8 | ui(buf[index + 3]); return i; } /*** * Get NTP Timestamp at specified starting index. * * @param index index into data array * @return TimeStamp object for 64 bits starting at index */ private TimeStamp getTimestamp(int index) { return new TimeStamp(getLong(index)); } /*** * Get Long value represented by bits starting at specified index. * * @return 8 bytes as 64-bit long */ private long getLong(int index) { long i = ul(buf[index]) << 56 | ul(buf[index + 1]) << 48 | ul(buf[index + 2]) << 40 | ul(buf[index + 3]) << 32 | ul(buf[index + 4]) << 24 | ul(buf[index + 5]) << 16 | ul(buf[index + 6]) << 8 | ul(buf[index + 7]); return i; } /*** * Sets the NTP timestamp at the given array index. * * @param index index into the byte array. * @param t TimeStamp. */ private void setTimestamp(int index, TimeStamp t) { long ntpTime = (t == null) ? 0 : t.ntpValue(); // copy 64-bits from Long value into 8 x 8-bit bytes of array // one byte at a time shifting 8-bits for each position. for (int i = 7; i >= 0; i--) { buf[index + i] = (byte) (ntpTime & 0xFF); ntpTime >>>= 8; // shift to next byte } // buf[index] |= 0x80; // only set if 1900 baseline.... } /*** * Returns the datagram packet with the NTP details already filled in. * * @return a datagram packet. */ public synchronized DatagramPacket getDatagramPacket() { if (dp == null) { dp = new DatagramPacket(buf, buf.length); dp.setPort(NTP_PORT); } return dp; } /*** * Set the contents of this object from source datagram packet. * * @param srcDp source DatagramPacket to copy contents from. */ public void setDatagramPacket(DatagramPacket srcDp) { byte[] incomingBuf = srcDp.getData(); int len = srcDp.getLength(); if (len > buf.length) len = buf.length; System.arraycopy(incomingBuf, 0, buf, 0, len); } /*** * Convert byte to unsigned integer. * Java only has signed types so we have to do * more work to get unsigned ops. * * @param b * @return unsigned int value of byte */ protected final static int ui(byte b) { int i = b & 0xFF; return i; } /*** * Convert byte to unsigned long. * Java only has signed types so we have to do * more work to get unsigned ops * * @param b * @return unsigned long value of byte */ protected final static long ul(byte b) { long i = b & 0xFF; return i; } /*** * Returns details of NTP packet as a string. * * @return details of NTP packet as a string. */ @Override public String toString() { return "[" + "version:" + getVersion() + ", mode:" + getMode() + ", poll:" + getPoll() + ", precision:" + getPrecision() + ", delay:" + getRootDelay() + ", dispersion(ms):" + getRootDispersionInMillisDouble() + ", id:" + getReferenceIdString() + ", xmitTime:" + getTransmitTimeStamp().toDateString() + " ]"; } } commons-net-2.2/src/main/java/org/apache/commons/net/util/0000755000175000017500000000000011617452467023451 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/util/ListenerList.java0000644000175000017500000000346311014673543026732 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.util; import java.io.Serializable; import java.util.EventListener; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; /** * @author Daniel F. Savarese */ public class ListenerList implements Serializable, Iterable { private final CopyOnWriteArrayList __listeners; public ListenerList() { __listeners = new CopyOnWriteArrayList(); } public void addListener(EventListener listener) { __listeners.add(listener); } public void removeListener(EventListener listener) { __listeners.remove(listener); } public int getListenerCount() { return __listeners.size(); } /** * Return an {@link Iterator} for the {@link EventListener} instances * * @since 2.0 * TODO Check that this is a good defensive strategy */ public Iterator iterator() { return __listeners.iterator(); } } commons-net-2.2/src/main/java/org/apache/commons/net/util/SubnetUtils.java0000644000175000017500000002375711466231525026603 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.util; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A class that performs some subnet calculations given a network address and a subnet mask. * @see "http://www.faqs.org/rfcs/rfc1519.html" * @author * @since 2.0 */ public class SubnetUtils { private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"; private static final String SLASH_FORMAT = IP_ADDRESS + "/(\\d{1,3})"; private static final Pattern addressPattern = Pattern.compile(IP_ADDRESS); private static final Pattern cidrPattern = Pattern.compile(SLASH_FORMAT); private static final int NBITS = 32; private int netmask = 0; private int address = 0; private int network = 0; private int broadcast = 0; /** Whether the broadcast/network address are included in host count */ private boolean inclusiveHostCount = false; /** * Constructor that takes a CIDR-notation string, e.g. "192.168.0.1/16" * @param cidrNotation A CIDR-notation string, e.g. "192.168.0.1/16" * @throws IllegalArgumentException if the parameter is invalid, * i.e. does not match n.n.n.n/m where n=1-3 decimal digits, m = 1-3 decimal digits in range 1-32 */ public SubnetUtils(String cidrNotation) { calculate(cidrNotation); } /** * Constructor that takes a dotted decimal address and a dotted decimal mask. * @param address An IP address, e.g. "192.168.0.1" * @param mask A dotted decimal netmask e.g. "255.255.0.0" * @throws IllegalArgumentException if the address or mask is invalid, * i.e. does not match n.n.n.n where n=1-3 decimal digits and the mask is not all zeros */ public SubnetUtils(String address, String mask) { calculate(toCidrNotation(address, mask)); } /** * Returns true if the return value of {@link SubnetInfo#getAddressCount()} * includes the network address and broadcast addresses. * @since 2.2 */ public boolean isInclusiveHostCount() { return inclusiveHostCount; } /** * Set to true if you want the return value of {@link SubnetInfo#getAddressCount()} * to include the network and broadcast addresses. * @param inclusiveHostCount * @since 2.2 */ public void setInclusiveHostCount(boolean inclusiveHostCount) { this.inclusiveHostCount = inclusiveHostCount; } /** * Convenience container for subnet summary information. * */ public final class SubnetInfo { private SubnetInfo() {} private int netmask() { return netmask; } private int network() { return network; } private int address() { return address; } private int broadcast() { return broadcast; } private int low() { return network() + (isInclusiveHostCount() ? 0 : 1); } private int high() { return broadcast() - (isInclusiveHostCount() ? 0 : 1); } /** * Returns true if the parameter address is in the * range of usable endpoint addresses for this subnet. This excludes the * network and broadcast adresses. * @param address A dot-delimited IPv4 address, e.g. "192.168.0.1" * @return True if in range, false otherwise */ public boolean isInRange(String address) { return isInRange(toInteger(address)); } private boolean isInRange(int address) { int diff = address-low(); return (diff >= 0 && (diff <= (high()-low()))); } public String getBroadcastAddress() { return format(toArray(broadcast())); } public String getNetworkAddress() { return format(toArray(network())); } public String getNetmask() { return format(toArray(netmask())); } public String getAddress() { return format(toArray(address())); } public String getLowAddress() { return format(toArray(low())); } public String getHighAddress() { return format(toArray(high())); } public int getAddressCount() { return (broadcast() - low() + (isInclusiveHostCount() ? 1 : 0)); } public int asInteger(String address) { return toInteger(address); } public String getCidrSignature() { return toCidrNotation( format(toArray(address())), format(toArray(netmask())) ); } public String[] getAllAddresses() { String[] addresses = new String[getAddressCount()]; for (int add = low(), j=0; add <= high(); ++add, ++j) { addresses[j] = format(toArray(add)); } return addresses; } /** * {@inheritDoc} * @since 2.2 */ @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append("CIDR Signature:\t[").append(getCidrSignature()).append("]") .append(" Netmask: [").append(getNetmask()).append("]\n") .append("Network:\t[").append(getNetworkAddress()).append("]\n") .append("Broadcast:\t[").append(getBroadcastAddress()).append("]\n") .append("First Address:\t[").append(getLowAddress()).append("]\n") .append("Last Address:\t[").append(getHighAddress()).append("]\n") .append("# Addresses:\t[").append(getAddressCount()).append("]\n"); return buf.toString(); } } /** * Return a {@link SubnetInfo} instance that contains subnet-specific statistics * @return new instance */ public final SubnetInfo getInfo() { return new SubnetInfo(); } /* * Initialize the internal fields from the supplied CIDR mask */ private void calculate(String mask) { Matcher matcher = cidrPattern.matcher(mask); if (matcher.matches()) { address = matchAddress(matcher); /* Create a binary netmask from the number of bits specification /x */ int cidrPart = rangeCheck(Integer.parseInt(matcher.group(5)), -1, NBITS); for (int j = 0; j < cidrPart; ++j) { netmask |= (1 << 31-j); } rangeCheck(pop(netmask),0, NBITS); /* Calculate base network address */ network = (address & netmask); /* Calculate broadcast address */ broadcast = network | ~(netmask); } else throw new IllegalArgumentException("Could not parse [" + mask + "]"); } /* * Convert a dotted decimal format address to a packed integer format */ private int toInteger(String address) { Matcher matcher = addressPattern.matcher(address); if (matcher.matches()) { return matchAddress(matcher); } else throw new IllegalArgumentException("Could not parse [" + address + "]"); } /* * Convenience method to extract the components of a dotted decimal address and * pack into an integer using a regex match */ private int matchAddress(Matcher matcher) { int addr = 0; for (int i = 1; i <= 4; ++i) { int n = (rangeCheck(Integer.parseInt(matcher.group(i)), -1, 255)); addr |= ((n & 0xff) << 8*(4-i)); } return addr; } /* * Convert a packed integer address into a 4-element array */ private int[] toArray(int val) { int ret[] = new int[4]; for (int j = 3; j >= 0; --j) ret[j] |= ((val >>> 8*(3-j)) & (0xff)); return ret; } /* * Convert a 4-element array into dotted decimal format */ private String format(int[] octets) { StringBuilder str = new StringBuilder(); for (int i =0; i < octets.length; ++i){ str.append(octets[i]); if (i != octets.length - 1) { str.append("."); } } return str.toString(); } /* * Convenience function to check integer boundaries. * Checks if a value x is in the range (begin,end]. * Returns x if it is in range, throws an exception otherwise. */ private int rangeCheck(int value, int begin, int end) { if (value > begin && value <= end) // (begin,end] return value; throw new IllegalArgumentException("Value [" + value + "] not in range ("+begin+","+end+"]"); } /* * Count the number of 1-bits in a 32-bit integer using a divide-and-conquer strategy * see Hacker's Delight section 5.1 */ int pop(int x) { x = x - ((x >>> 1) & 0x55555555); x = (x & 0x33333333) + ((x >>> 2) & 0x33333333); x = (x + (x >>> 4)) & 0x0F0F0F0F; x = x + (x >>> 8); x = x + (x >>> 16); return x & 0x0000003F; } /* Convert two dotted decimal addresses to a single xxx.xxx.xxx.xxx/yy format * by counting the 1-bit population in the mask address. (It may be better to count * NBITS-#trailing zeroes for this case) */ private String toCidrNotation(String addr, String mask) { return addr + "/" + pop(toInteger(mask)); } } commons-net-2.2/src/main/java/org/apache/commons/net/util/Base64.java0000644000175000017500000011602511466231525025335 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.util; import java.io.UnsupportedEncodingException; import java.math.BigInteger; /** * Provides Base64 encoding and decoding as defined by RFC 2045. * *

* This class implements section 6.8. Base64 Content-Transfer-Encoding from RFC 2045 Multipurpose * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies by Freed and Borenstein. *

*

* The class can be parameterized in the following manner with various constructors: *

    *
  • URL-safe mode: Default off.
  • *
  • Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of * 4 in the encoded data. *
  • Line separator: Default is CRLF ("\r\n")
  • *
*

*

* Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc). *

* * @see RFC 2045 * @author Apache Software Foundation * @since 2.2 * @version $Id$ */ public class Base64 { private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2; private static final int DEFAULT_BUFFER_SIZE = 8192; /** * Chunk size per RFC 2045 section 6.8. * *

* The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any * equal signs. *

* * @see RFC 2045 section 6.8 */ static final int CHUNK_SIZE = 76; /** * Chunk separator per RFC 2045 section 2.1. * *

* N.B. The next major release may break compatibility and make this field private. *

* * @see RFC 2045 section 2.1 */ static final byte[] CHUNK_SEPARATOR = {'\r', '\n'}; /** * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet" * equivalents as specified in Table 1 of RFC 2045. * * Thanks to "commons" project in ws.apache.org for this code. * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ */ private static final byte[] STANDARD_ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / * changed to - and _ to make the encoded Base64 results more URL-SAFE. * This table is only used when the Base64's mode is set to URL-SAFE. */ private static final byte[] URL_SAFE_ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' }; /** * Byte used to pad output. */ private static final byte PAD = '='; /** * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64 * alphabet but fall within the bounds of the array are translated to -1. * * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit). * * Thanks to "commons" project in ws.apache.org for this code. * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ */ private static final byte[] DECODE_TABLE = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; /** Mask used to extract 6 bits, used when encoding */ private static final int MASK_6BITS = 0x3f; /** Mask used to extract 8 bits, used in decoding base64 bytes */ private static final int MASK_8BITS = 0xff; // The static final fields above are used for the original static byte[] methods on Base64. // The private member fields below are used with the new streaming approach, which requires // some state be preserved between calls of encode() and decode(). /** * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch * between the two modes. */ private final byte[] encodeTable; /** * Line length for encoding. Not used when decoding. A value of zero or less implies no chunking of the base64 * encoded data. */ private final int lineLength; /** * Line separator for encoding. Not used when decoding. Only used if lineLength > 0. */ private final byte[] lineSeparator; /** * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. * decodeSize = 3 + lineSeparator.length; */ private final int decodeSize; /** * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. * encodeSize = 4 + lineSeparator.length; */ private final int encodeSize; /** * Buffer for streaming. */ private byte[] buffer; /** * Position where next character should be written in the buffer. */ private int pos; /** * Position where next character should be read from the buffer. */ private int readPos; /** * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to * make sure each encoded line never goes beyond lineLength (if lineLength > 0). */ private int currentLinePos; /** * Writes to the buffer only occur after every 3 reads when encoding, an every 4 reads when decoding. This variable * helps track that. */ private int modulus; /** * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this Base64 object becomes useless, * and must be thrown away. */ private boolean eof; /** * Place holder for the 3 bytes we're dealing with for our base64 logic. Bitwise operations store and extract the * base64 encoding or decoding from this variable. */ private int x; /** * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. *

* When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE. *

* *

* When decoding all variants are supported. *

*/ public Base64() { this(false); } /** * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode. *

* When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE. *

* *

* When decoding all variants are supported. *

* * @param urlSafe * if true, URL-safe encoding is used. In most cases this should be set to * false. * @since 1.4 */ public Base64(boolean urlSafe) { this(CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe); } /** * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. *

* When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is * STANDARD_ENCODE_TABLE. *

*

* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. *

*

* When decoding all variants are supported. *

* * @param lineLength * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4). * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding. * @since 1.4 */ public Base64(int lineLength) { this(lineLength, CHUNK_SEPARATOR); } /** * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. *

* When encoding the line length and line separator are given in the constructor, and the encoding table is * STANDARD_ENCODE_TABLE. *

*

* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. *

*

* When decoding all variants are supported. *

* * @param lineLength * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4). * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding. * @param lineSeparator * Each line of encoded data will end with this sequence of bytes. * @throws IllegalArgumentException * Thrown when the provided lineSeparator included some base64 characters. * @since 1.4 */ public Base64(int lineLength, byte[] lineSeparator) { this(lineLength, lineSeparator, false); } /** * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. *

* When encoding the line length and line separator are given in the constructor, and the encoding table is * STANDARD_ENCODE_TABLE. *

*

* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data. *

*

* When decoding all variants are supported. *

* * @param lineLength * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4). * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding. * @param lineSeparator * Each line of encoded data will end with this sequence of bytes. * @param urlSafe * Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode * operations. Decoding seamlessly handles both modes. * @throws IllegalArgumentException * The provided lineSeparator included some base64 characters. That's not going to work! * @since 1.4 */ public Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) { if (lineSeparator == null) { lineLength = 0; // disable chunk-separating lineSeparator = CHUNK_SEPARATOR; // this just gets ignored } this.lineLength = lineLength > 0 ? (lineLength / 4) * 4 : 0; this.lineSeparator = new byte[lineSeparator.length]; System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length); if (lineLength > 0) { this.encodeSize = 4 + lineSeparator.length; } else { this.encodeSize = 4; } this.decodeSize = this.encodeSize - 1; if (containsBase64Byte(lineSeparator)) { String sep = newStringUtf8(lineSeparator); throw new IllegalArgumentException("lineSeperator must not contain base64 characters: [" + sep + "]"); } this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE; } /** * Returns our current encode mode. True if we're URL-SAFE, false otherwise. * * @return true if we're in URL-SAFE mode, false otherwise. * @since 1.4 */ public boolean isUrlSafe() { return this.encodeTable == URL_SAFE_ENCODE_TABLE; } /** * Returns true if this Base64 object has buffered data for reading. * * @return true if there is Base64 object still available for reading. */ boolean hasData() { return this.buffer != null; } /** * Returns the amount of buffered data available for reading. * * @return The amount of buffered data available for reading. */ int avail() { return buffer != null ? pos - readPos : 0; } /** Doubles our buffer. */ private void resizeBuffer() { if (buffer == null) { buffer = new byte[DEFAULT_BUFFER_SIZE]; pos = 0; readPos = 0; } else { byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR]; System.arraycopy(buffer, 0, b, 0, buffer.length); buffer = b; } } /** * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail * bytes. Returns how many bytes were actually extracted. * * @param b * byte[] array to extract the buffered data into. * @param bPos * position in byte[] array to start extraction at. * @param bAvail * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available). * @return The number of bytes successfully extracted into the provided byte[] array. */ int readResults(byte[] b, int bPos, int bAvail) { if (buffer != null) { int len = Math.min(avail(), bAvail); if (buffer != b) { System.arraycopy(buffer, readPos, b, bPos, len); readPos += len; if (readPos >= pos) { buffer = null; } } else { // Re-using the original consumer's output array is only // allowed for one round. buffer = null; } return len; } return eof ? -1 : 0; } /** * Sets the streaming buffer. This is a small optimization where we try to buffer directly to the consumer's output * array for one round (if the consumer calls this method first) instead of starting our own buffer. * * @param out * byte[] array to buffer directly to. * @param outPos * Position to start buffering into. * @param outAvail * Amount of bytes available for direct buffering. */ void setInitialBuffer(byte[] out, int outPos, int outAvail) { // We can re-use consumer's original output array under // special circumstances, saving on some System.arraycopy(). if (out != null && out.length == outAvail) { buffer = out; pos = outPos; readPos = outPos; } } /** *

* Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last * remaining bytes (if not multiple of 3). *

*

* Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach. * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ *

* * @param in * byte[] array of binary data to base64 encode. * @param inPos * Position to start reading data from. * @param inAvail * Amount of bytes available from input for encoding. */ void encode(byte[] in, int inPos, int inAvail) { if (eof) { return; } // inAvail < 0 is how we're informed of EOF in the underlying data we're // encoding. if (inAvail < 0) { eof = true; if (buffer == null || buffer.length - pos < encodeSize) { resizeBuffer(); } switch (modulus) { case 1 : buffer[pos++] = encodeTable[(x >> 2) & MASK_6BITS]; buffer[pos++] = encodeTable[(x << 4) & MASK_6BITS]; // URL-SAFE skips the padding to further reduce size. if (encodeTable == STANDARD_ENCODE_TABLE) { buffer[pos++] = PAD; buffer[pos++] = PAD; } break; case 2 : buffer[pos++] = encodeTable[(x >> 10) & MASK_6BITS]; buffer[pos++] = encodeTable[(x >> 4) & MASK_6BITS]; buffer[pos++] = encodeTable[(x << 2) & MASK_6BITS]; // URL-SAFE skips the padding to further reduce size. if (encodeTable == STANDARD_ENCODE_TABLE) { buffer[pos++] = PAD; } break; } if (lineLength > 0 && pos > 0) { System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length); pos += lineSeparator.length; } } else { for (int i = 0; i < inAvail; i++) { if (buffer == null || buffer.length - pos < encodeSize) { resizeBuffer(); } modulus = (++modulus) % 3; int b = in[inPos++]; if (b < 0) { b += 256; } x = (x << 8) + b; if (0 == modulus) { buffer[pos++] = encodeTable[(x >> 18) & MASK_6BITS]; buffer[pos++] = encodeTable[(x >> 12) & MASK_6BITS]; buffer[pos++] = encodeTable[(x >> 6) & MASK_6BITS]; buffer[pos++] = encodeTable[x & MASK_6BITS]; currentLinePos += 4; if (lineLength > 0 && lineLength <= currentLinePos) { System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length); pos += lineSeparator.length; currentLinePos = 0; } } } } } /** *

* Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1" * call is not necessary when decoding, but it doesn't hurt, either. *

*

* Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in, * garbage-out philosophy: it will not check the provided data for validity. *

*

* Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach. * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ *

* * @param in * byte[] array of ascii data to base64 decode. * @param inPos * Position to start reading data from. * @param inAvail * Amount of bytes available from input for encoding. */ void decode(byte[] in, int inPos, int inAvail) { if (eof) { return; } if (inAvail < 0) { eof = true; } for (int i = 0; i < inAvail; i++) { if (buffer == null || buffer.length - pos < decodeSize) { resizeBuffer(); } byte b = in[inPos++]; if (b == PAD) { // We're done. eof = true; break; } else { if (b >= 0 && b < DECODE_TABLE.length) { int result = DECODE_TABLE[b]; if (result >= 0) { modulus = (++modulus) % 4; x = (x << 6) + result; if (modulus == 0) { buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS); buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS); buffer[pos++] = (byte) (x & MASK_8BITS); } } } } } // Two forms of EOF as far as base64 decoder is concerned: actual // EOF (-1) and first time '=' character is encountered in stream. // This approach makes the '=' padding characters completely optional. if (eof && modulus != 0) { x = x << 6; switch (modulus) { case 2 : x = x << 6; buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS); break; case 3 : buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS); buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS); break; } } } /** * Returns whether or not the octet is in the base 64 alphabet. * * @param octet * The value to test * @return true if the value is defined in the the base 64 alphabet, false otherwise. * @since 1.4 */ public static boolean isBase64(byte octet) { return octet == PAD || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1); } /** * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the * method treats whitespace as valid. * * @param arrayOctet * byte array to test * @return true if all bytes are valid characters in the Base64 alphabet or if the byte array is empty; * false, otherwise */ public static boolean isArrayByteBase64(byte[] arrayOctet) { for (int i = 0; i < arrayOctet.length; i++) { if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) { return false; } } return true; } /** * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. * * @param arrayOctet * byte array to test * @return true if any byte is a valid character in the Base64 alphabet; false herwise */ private static boolean containsBase64Byte(byte[] arrayOctet) { for (int i = 0; i < arrayOctet.length; i++) { if (isBase64(arrayOctet[i])) { return true; } } return false; } /** * Encodes binary data using the base64 algorithm but does not chunk the output. * * @param binaryData * binary data to encode * @return byte[] containing Base64 characters in their UTF-8 representation. */ public static byte[] encodeBase64(byte[] binaryData) { return encodeBase64(binaryData, false); } /** * Encodes binary data using the base64 algorithm into 76 character blocks separated by CRLF. * * @param binaryData * binary data to encode * @return String containing Base64 characters. * @since 1.4 */ public static String encodeBase64String(byte[] binaryData) { return newStringUtf8(encodeBase64(binaryData, true)); } /** * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The * url-safe variation emits - and _ instead of + and / characters. * * @param binaryData * binary data to encode * @return byte[] containing Base64 characters in their UTF-8 representation. * @since 1.4 */ public static byte[] encodeBase64URLSafe(byte[] binaryData) { return encodeBase64(binaryData, false, true); } /** * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The * url-safe variation emits - and _ instead of + and / characters. * * @param binaryData * binary data to encode * @return String containing Base64 characters * @since 1.4 */ public static String encodeBase64URLSafeString(byte[] binaryData) { return newStringUtf8(encodeBase64(binaryData, false, true)); } /** * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks * * @param binaryData * binary data to encode * @return Base64 characters chunked in 76 character blocks */ public static byte[] encodeBase64Chunked(byte[] binaryData) { return encodeBase64(binaryData, true); } /** * Decodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the * Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String. * * @param pObject * Object to decode * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String supplied. * @throws RuntimeException * if the parameter supplied is not of type byte[] */ public Object decode(Object pObject) { if (pObject instanceof byte[]) { return decode((byte[]) pObject); } else if (pObject instanceof String) { return decode((String) pObject); } else { throw new RuntimeException("Parameter supplied to Base64 decode is not a byte[] or a String"); } } /** * Decodes a String containing containing characters in the Base64 alphabet. * * @param pArray * A String containing Base64 character data * @return a byte array containing binary data * @since 1.4 */ public byte[] decode(String pArray) { return decode(getBytesUtf8(pArray)); } private byte[] getBytesUtf8(String pArray) { try { return pArray.getBytes("UTF8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } /** * Decodes a byte[] containing containing characters in the Base64 alphabet. * * @param pArray * A byte array containing Base64 character data * @return a byte array containing binary data */ public byte[] decode(byte[] pArray) { reset(); if (pArray == null || pArray.length == 0) { return pArray; } long len = (pArray.length * 3) / 4; byte[] buf = new byte[(int) len]; setInitialBuffer(buf, 0, buf.length); decode(pArray, 0, pArray.length); decode(pArray, 0, -1); // Notify decoder of EOF. // Would be nice to just return buf (like we sometimes do in the encode // logic), but we have no idea what the line-length was (could even be // variable). So we cannot determine ahead of time exactly how big an // array is necessary. Hence the need to construct a 2nd byte array to // hold the final result: byte[] result = new byte[pos]; readResults(result, 0, result.length); return result; } /** * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. * * @param binaryData * Array containing binary data to encode. * @param isChunked * if true this encoder will chunk the base64 output into 76 character blocks * @return Base64-encoded data. * @throws IllegalArgumentException * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE} */ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) { return encodeBase64(binaryData, isChunked, false); } /** * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. * * @param binaryData * Array containing binary data to encode. * @param isChunked * if true this encoder will chunk the base64 output into 76 character blocks * @param urlSafe * if true this encoder will emit - and _ instead of the usual + and / characters. * @return Base64-encoded data. * @throws IllegalArgumentException * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE} * @since 1.4 */ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe) { return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE); } /** * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. * * @param binaryData * Array containing binary data to encode. * @param isChunked * if true this encoder will chunk the base64 output into 76 character blocks * @param urlSafe * if true this encoder will emit - and _ instead of the usual + and / characters. * @param maxResultSize * The maximum result size to accept. * @return Base64-encoded data. * @throws IllegalArgumentException * Thrown when the input array needs an output array bigger than maxResultSize * @since 1.4 */ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) { if (binaryData == null || binaryData.length == 0) { return binaryData; } long len = getEncodeLength(binaryData, CHUNK_SIZE, CHUNK_SEPARATOR); if (len > maxResultSize) { throw new IllegalArgumentException("Input array too big, the output array would be bigger (" + len + ") than the specified maxium size of " + maxResultSize); } Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe); return b64.encode(binaryData); } /** * Decodes a Base64 String into octets * * @param base64String * String containing Base64 data * @return Array containing decoded data. * @since 1.4 */ public static byte[] decodeBase64(String base64String) { return new Base64().decode(base64String); } /** * Decodes Base64 data into octets * * @param base64Data * Byte array containing Base64 data * @return Array containing decoded data. */ public static byte[] decodeBase64(byte[] base64Data) { return new Base64().decode(base64Data); } /** * Checks if a byte value is whitespace or not. * * @param byteToCheck * the byte to check * @return true if byte is whitespace, false otherwise */ private static boolean isWhiteSpace(byte byteToCheck) { switch (byteToCheck) { case ' ' : case '\n' : case '\r' : case '\t' : return true; default : return false; } } // Implementation of the Encoder Interface /** * Encodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the * Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[]. * * @param pObject * Object to encode * @return An object (of type byte[]) containing the base64 encoded data which corresponds to the byte[] supplied. * @throws RuntimeException * if the parameter supplied is not of type byte[] */ public Object encode(Object pObject) { if (!(pObject instanceof byte[])) { throw new RuntimeException("Parameter supplied to Base64 encode is not a byte[]"); } return encode((byte[]) pObject); } /** * Encodes a byte[] containing binary data, into a String containing characters in the Base64 alphabet. * * @param pArray * a byte array containing binary data * @return A String containing only Base64 character data * @since 1.4 */ public String encodeToString(byte[] pArray) { return newStringUtf8(encode(pArray)); } private static String newStringUtf8(byte[] encode) { String str = null; try { str = new String(encode, "UTF8"); } catch (UnsupportedEncodingException ue) { throw new RuntimeException(ue); } return str; } /** * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet. * * @param pArray * a byte array containing binary data * @return A byte array containing only Base64 character data */ public byte[] encode(byte[] pArray) { reset(); if (pArray == null || pArray.length == 0) { return pArray; } long len = getEncodeLength(pArray, lineLength, lineSeparator); byte[] buf = new byte[(int) len]; setInitialBuffer(buf, 0, buf.length); encode(pArray, 0, pArray.length); encode(pArray, 0, -1); // Notify encoder of EOF. // Encoder might have resized, even though it was unnecessary. if (buffer != buf) { readResults(buf, 0, buf.length); } // In URL-SAFE mode we skip the padding characters, so sometimes our // final length is a bit smaller. if (isUrlSafe() && pos < buf.length) { byte[] smallerBuf = new byte[pos]; System.arraycopy(buf, 0, smallerBuf, 0, pos); buf = smallerBuf; } return buf; } /** * Pre-calculates the amount of space needed to base64-encode the supplied array. * * @param pArray byte[] array which will later be encoded * @param chunkSize line-length of the output (<= 0 means no chunking) between each * chunkSeparator (e.g. CRLF). * @param chunkSeparator the sequence of bytes used to separate chunks of output (e.g. CRLF). * * @return amount of space needed to encoded the supplied array. Returns * a long since a max-len array will require Integer.MAX_VALUE + 33%. */ private static long getEncodeLength(byte[] pArray, int chunkSize, byte[] chunkSeparator) { // base64 always encodes to multiples of 4. chunkSize = (chunkSize / 4) * 4; long len = (pArray.length * 4) / 3; long mod = len % 4; if (mod != 0) { len += 4 - mod; } if (chunkSize > 0) { boolean lenChunksPerfectly = len % chunkSize == 0; len += (len / chunkSize) * chunkSeparator.length; if (!lenChunksPerfectly) { len += chunkSeparator.length; } } return len; } // Implementation of integer encoding used for crypto /** * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature * * @param pArray * a byte array containing base64 character data * @return A BigInteger * @since 1.4 */ public static BigInteger decodeInteger(byte[] pArray) { return new BigInteger(1, decodeBase64(pArray)); } /** * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature * * @param bigInt * a BigInteger * @return A byte array containing base64 character data * @throws NullPointerException * if null is passed in * @since 1.4 */ public static byte[] encodeInteger(BigInteger bigInt) { if (bigInt == null) { throw new NullPointerException("encodeInteger called with null parameter"); } return encodeBase64(toIntegerBytes(bigInt), false); } /** * Returns a byte-array representation of a BigInteger without sign bit. * * @param bigInt * BigInteger to be converted * @return a byte array representation of the BigInteger parameter */ static byte[] toIntegerBytes(BigInteger bigInt) { int bitlen = bigInt.bitLength(); // round bitlen bitlen = ((bitlen + 7) >> 3) << 3; byte[] bigBytes = bigInt.toByteArray(); if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) { return bigBytes; } // set up params for copying everything but sign bit int startSrc = 0; int len = bigBytes.length; // if bigInt is exactly byte-aligned, just skip signbit in copy if ((bigInt.bitLength() % 8) == 0) { startSrc = 1; len--; } int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec byte[] resizedBytes = new byte[bitlen / 8]; System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len); return resizedBytes; } /** * Resets this Base64 object to its initial newly constructed state. */ private void reset() { buffer = null; pos = 0; readPos = 0; currentLinePos = 0; modulus = 0; eof = false; } } commons-net-2.2/src/main/java/org/apache/commons/net/discard/0000755000175000017500000000000011617452467024105 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/discard/DiscardTCPClient.java0000644000175000017500000000454210761044665030030 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.discard; import java.io.OutputStream; import org.apache.commons.net.SocketClient; /*** * The DiscardTCPClient class is a TCP implementation of a client for the * Discard protocol described in RFC 863. To use the class, merely * establish a connection with * {@link org.apache.commons.net.SocketClient#connect connect } * and call {@link #getOutputStream getOutputStream() } to * retrieve the discard output stream. Don't close the output stream * when you're done writing to it. Rather, call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to clean up properly. *

*

* @author Daniel F. Savarese * @see DiscardUDPClient ***/ public class DiscardTCPClient extends SocketClient { /*** The default discard port. It is set to 9 according to RFC 863. ***/ public static final int DEFAULT_PORT = 9; /*** * The default DiscardTCPClient constructor. It merely sets the default * port to DEFAULT_PORT . ***/ public DiscardTCPClient () { setDefaultPort(DEFAULT_PORT); } /*** * Returns an OutputStream through which you may write data to the server. * You should NOT close the OutputStream when you're finished * reading from it. Rather, you should call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to clean up properly. *

* @return An OutputStream through which you can write data to the server. ***/ public OutputStream getOutputStream() { return _output_; } } commons-net-2.2/src/main/java/org/apache/commons/net/discard/DiscardUDPClient.java0000644000175000017500000000606110761044665030030 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.discard; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import org.apache.commons.net.DatagramSocketClient; /*** * The DiscardUDPClient class is a UDP implementation of a client for the * Discard protocol described in RFC 863. To use the class, * just open a local UDP port * with {@link org.apache.commons.net.DatagramSocketClient#open open } * and call {@link #send send } to send datagrams to the server * After you're done sending discard data, call * {@link org.apache.commons.net.DatagramSocketClient#close close() } * to clean up properly. *

*

* @author Daniel F. Savarese * @see DiscardTCPClient ***/ public class DiscardUDPClient extends DatagramSocketClient { /*** The default discard port. It is set to 9 according to RFC 863. ***/ public static final int DEFAULT_PORT = 9; DatagramPacket _sendPacket; public DiscardUDPClient() { _sendPacket = new DatagramPacket(new byte[0], 0); } /*** * Sends the specified data to the specified server at the specified port. *

* @param data The discard data to send. * @param length The length of the data to send. Should be less than * or equal to the length of the data byte array. * @param host The address of the server. * @param port The service port. * @exception IOException If an error occurs during the datagram send * operation. ***/ public void send(byte[] data, int length, InetAddress host, int port) throws IOException { _sendPacket.setData(data); _sendPacket.setLength(length); _sendPacket.setAddress(host); _sendPacket.setPort(port); _socket_.send(_sendPacket); } /*** * Same as * send(data, length, host. DiscardUDPClient.DEFAULT_PORT). ***/ public void send(byte[] data, int length, InetAddress host) throws IOException { send(data, length, host, DEFAULT_PORT); } /*** * Same as * send(data, data.length, host. DiscardUDPClient.DEFAULT_PORT). ***/ public void send(byte[] data, InetAddress host) throws IOException { send(data, data.length, host, DEFAULT_PORT); } } commons-net-2.2/src/main/java/org/apache/commons/net/DefaultDatagramSocketFactory.java0000644000175000017500000000501510542533103031045 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /*** * DefaultDatagramSocketFactory implements the DatagramSocketFactory * interface by simply wrapping the java.net.DatagramSocket * constructors. It is the default DatagramSocketFactory used by * {@link org.apache.commons.net.DatagramSocketClient} * implementations. *

*

* @author Daniel F. Savarese * @see DatagramSocketFactory * @see DatagramSocketClient * @see DatagramSocketClient#setDatagramSocketFactory ***/ public class DefaultDatagramSocketFactory implements DatagramSocketFactory { /*** * Creates a DatagramSocket on the local host at the first available port. *

* @exception SocketException If the socket could not be created. ***/ public DatagramSocket createDatagramSocket() throws SocketException { return new DatagramSocket(); } /*** * Creates a DatagramSocket on the local host at a specified port. *

* @param port The port to use for the socket. * @exception SocketException If the socket could not be created. ***/ public DatagramSocket createDatagramSocket(int port) throws SocketException { return new DatagramSocket(port); } /*** * Creates a DatagramSocket at the specified address on the local host * at a specified port. *

* @param port The port to use for the socket. * @param laddr The local address to use. * @exception SocketException If the socket could not be created. ***/ public DatagramSocket createDatagramSocket(int port, InetAddress laddr) throws SocketException { return new DatagramSocket(port, laddr); } } commons-net-2.2/src/main/java/org/apache/commons/net/echo/0000755000175000017500000000000011617452467023412 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/echo/EchoUDPClient.java0000644000175000017500000000665411354710167026646 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.echo; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import org.apache.commons.net.discard.DiscardUDPClient; /*** * The EchoUDPClient class is a UDP implementation of a client for the * Echo protocol described in RFC 862. To use the class, * just open a local UDP port * with {@link org.apache.commons.net.DatagramSocketClient#open open } * and call {@link #send send } to send datagrams to the server, * then call {@link #receive receive } to receive echoes. * After you're done echoing data, call * {@link org.apache.commons.net.DatagramSocketClient#close close() } * to clean up properly. *

*

* @author Daniel F. Savarese * @see EchoTCPClient * @see DiscardUDPClient ***/ public final class EchoUDPClient extends DiscardUDPClient { /*** The default echo port. It is set to 7 according to RFC 862. ***/ public static final int DEFAULT_PORT = 7; private final DatagramPacket __receivePacket = new DatagramPacket(new byte[0], 0); /*** * Sends the specified data to the specified server at the default echo * port. *

* @param data The echo data to send. * @param length The length of the data to send. Should be less than * or equal to the length of the data byte array. * @param host The address of the server. * @exception IOException If an error occurs during the datagram send * operation. ***/ @Override public void send(byte[] data, int length, InetAddress host) throws IOException { send(data, length, host, DEFAULT_PORT); } /*** Same as send(data, data.length, host) ***/ @Override public void send(byte[] data, InetAddress host) throws IOException { send(data, data.length, host, DEFAULT_PORT); } /*** * Receives echoed data and returns its length. The data may be divided * up among multiple datagrams, requiring multiple calls to receive. * Also, the UDP packets will not necessarily arrive in the same order * they were sent. *

* @return Length of actual data received. * @exception IOException If an error occurs while receiving the data. ***/ public int receive(byte[] data, int length) throws IOException { __receivePacket.setData(data); __receivePacket.setLength(length); _socket_.receive(__receivePacket); return __receivePacket.getLength(); } /*** Same as receive(data, data.length) ***/ public int receive(byte[] data) throws IOException { return receive(data, data.length); } } commons-net-2.2/src/main/java/org/apache/commons/net/echo/EchoTCPClient.java0000644000175000017500000000474410766022773026647 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.echo; import java.io.InputStream; import org.apache.commons.net.discard.DiscardTCPClient; /*** * The EchoTCPClient class is a TCP implementation of a client for the * Echo protocol described in RFC 862. To use the class, merely * establish a connection with * {@link org.apache.commons.net.SocketClient#connect connect } * and call {@link DiscardTCPClient#getOutputStream getOutputStream() } to * retrieve the echo output stream and * {@link #getInputStream getInputStream() } * to get the echo input stream. * Don't close either stream when you're done using them. Rather, call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to clean up properly. *

*

* @author Daniel F. Savarese * @see EchoUDPClient * @see DiscardTCPClient ***/ public final class EchoTCPClient extends DiscardTCPClient { /*** The default echo port. It is set to 7 according to RFC 862. ***/ public static final int DEFAULT_PORT = 7; /*** * The default EchoTCPClient constructor. It merely sets the default * port to DEFAULT_PORT . ***/ public EchoTCPClient () { setDefaultPort(DEFAULT_PORT); } /*** * Returns an InputStream from which you may read echoed data from * the server. You should NOT close the InputStream when you're finished * reading from it. Rather, you should call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to clean up properly. *

* @return An InputStream from which you can read echoed data from the * server. ***/ public InputStream getInputStream() { return _input_; } } commons-net-2.2/src/main/java/org/apache/commons/net/ProtocolCommandEvent.java0000644000175000017500000001156311416072763027441 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.util.EventObject; /*** * There exists a large class of IETF protocols that work by sending an * ASCII text command and arguments to a server, and then receiving an * ASCII text reply. For debugging and other purposes, it is extremely * useful to log or keep track of the contents of the protocol messages. * The ProtocolCommandEvent class coupled with the * {@link org.apache.commons.net.ProtocolCommandListener} * interface facilitate this process. *

*

* @see ProtocolCommandListener * @see ProtocolCommandSupport * @author Daniel F. Savarese ***/ public class ProtocolCommandEvent extends EventObject { private final int __replyCode; private final boolean __isCommand; private final String __message, __command; /*** * Creates a ProtocolCommandEvent signalling a command was sent to * the server. ProtocolCommandEvents created with this constructor * should only be sent after a command has been sent, but before the * reply has been received. *

* @param source The source of the event. * @param command The string representation of the command type sent, not * including the arguments (e.g., "STAT" or "GET"). * @param message The entire command string verbatim as sent to the server, * including all arguments. ***/ public ProtocolCommandEvent(Object source, String command, String message) { super(source); __replyCode = 0; __message = message; __isCommand = true; __command = command; } /*** * Creates a ProtocolCommandEvent signalling a reply to a command was * received. ProtocolCommandEvents created with this constructor * should only be sent after a complete command reply has been received * fromt a server. *

* @param source The source of the event. * @param replyCode The integer code indicating the natureof the reply. * This will be the protocol integer value for protocols * that use integer reply codes, or the reply class constant * corresponding to the reply for protocols like POP3 that use * strings like OK rather than integer codes (i.e., POP3Repy.OK). * @param message The entire reply as received from the server. ***/ public ProtocolCommandEvent(Object source, int replyCode, String message) { super(source); __replyCode = replyCode; __message = message; __isCommand = false; __command = null; } /*** * Returns the string representation of the command type sent (e.g., "STAT" * or "GET"). If the ProtocolCommandEvent is a reply event, then null * is returned. *

* @return The string representation of the command type sent, or null * if this is a reply event. ***/ public String getCommand() { return __command; } /*** * Returns the reply code of the received server reply. Undefined if * this is not a reply event. *

* @return The reply code of the received server reply. Undefined if * not a reply event. ***/ public int getReplyCode() { return __replyCode; } /*** * Returns true if the ProtocolCommandEvent was generated as a result * of sending a command. *

* @return true If the ProtocolCommandEvent was generated as a result * of sending a command. False otherwise. ***/ public boolean isCommand() { return __isCommand; } /*** * Returns true if the ProtocolCommandEvent was generated as a result * of receiving a reply. *

* @return true If the ProtocolCommandEvent was generated as a result * of receiving a reply. False otherwise. ***/ public boolean isReply() { return !isCommand(); } /*** * Returns the entire message sent to or received from the server. *

* @return The entire message sent to or received from the server. ***/ public String getMessage() { return __message; } } commons-net-2.2/src/main/java/org/apache/commons/net/bsd/0000755000175000017500000000000011617452467023244 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/bsd/RCommandClient.java0000644000175000017500000004141611445713774026754 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.bsd; import java.io.IOException; import java.io.InputStream; import java.net.BindException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import org.apache.commons.net.io.SocketInputStream; /*** * RCommandClient is very similar to * {@link org.apache.commons.net.bsd.RExecClient}, * from which it is derived, and implements the rcmd() facility that * first appeared in 4.2BSD Unix. rcmd() is the facility used by the rsh * (rshell) and other commands to execute a command on another machine * from a trusted host without issuing a password. The trust relationship * between two machines is established by the contents of a machine's * /etc/hosts.equiv file and a user's .rhosts file. These files specify * from which hosts and accounts on those hosts rcmd() requests will be * accepted. The only additional measure for establishing trust is that * all client connections must originate from a port between 512 and 1023. * Consequently, there is an upper limit to the number of rcmd connections * that can be running simultaneously. The required ports are reserved * ports on Unix systems, and can only be bound by a * process running with root permissions (to accomplish this rsh, rlogin, * and related commands usualy have the suid bit set). Therefore, on a * Unix system, you will only be able to successfully use the RCommandClient * class if the process runs as root. However, there is no such restriction * on Windows95 and some other systems. The security risks are obvious. * However, when carefully used, rcmd() can be very useful when used behind * a firewall. *

* As with virtually all of the client classes in org.apache.commons.net, this * class derives from SocketClient. But it overrides most of its connection * methods so that the local Socket will originate from an acceptable * rshell port. The way to use RCommandClient is to first connect * to the server, call the {@link #rcommand rcommand() } method, * and then * fetch the connection's input, output, and optionally error streams. * Interaction with the remote command is controlled entirely through the * I/O streams. Once you have finished processing the streams, you should * invoke {@link org.apache.commons.net.bsd.RExecClient#disconnect disconnect() } * to clean up properly. *

* By default the standard output and standard error streams of the * remote process are transmitted over the same connection, readable * from the input stream returned by * {@link org.apache.commons.net.bsd.RExecClient#getInputStream getInputStream() } * . However, it is * possible to tell the rshd daemon to return the standard error * stream over a separate connection, readable from the input stream * returned by {@link org.apache.commons.net.bsd.RExecClient#getErrorStream getErrorStream() } * . You * can specify that a separate connection should be created for standard * error by setting the boolean separateErrorStream * parameter of {@link #rcommand rcommand() } to true . * The standard input of the remote process can be written to through * the output stream returned by * {@link org.apache.commons.net.bsd.RExecClient#getOutputStream getOutputStream() } * . *

*

* @author Daniel F. Savarese * @see org.apache.commons.net.SocketClient * @see RExecClient * @see RLoginClient ***/ public class RCommandClient extends RExecClient { /*** * The default rshell port. Set to 514 in BSD Unix. ***/ public static final int DEFAULT_PORT = 514; /*** * The smallest port number an rcmd client may use. By BSD convention * this number is 512. ***/ public static final int MIN_CLIENT_PORT = 512; /*** * The largest port number an rcmd client may use. By BSD convention * this number is 1023. ***/ public static final int MAX_CLIENT_PORT = 1023; // Overrides method in RExecClient in order to implement proper // port number limitations. @Override InputStream _createErrorStream() throws IOException { int localPort; ServerSocket server; Socket socket; localPort = MAX_CLIENT_PORT; server = null; // Keep compiler from barfing for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort) { try { server = _serverSocketFactory_.createServerSocket(localPort, 1, getLocalAddress()); break; // got a socket } catch (SocketException e) { continue; } } if (server == null) { throw new BindException("All ports in use."); } _output_.write(Integer.toString(server.getLocalPort()).getBytes()); _output_.write('\0'); _output_.flush(); socket = server.accept(); server.close(); if (isRemoteVerificationEnabled() && !verifyRemote(socket)) { socket.close(); throw new IOException( "Security violation: unexpected connection attempt by " + socket.getInetAddress().getHostAddress()); } return (new SocketInputStream(socket, socket.getInputStream())); } /*** * The default RCommandClient constructor. Initializes the * default port to DEFAULT_PORT . ***/ public RCommandClient() { setDefaultPort(DEFAULT_PORT); } /*** * Opens a Socket connected to a remote host at the specified port and * originating from the specified local address using a port in a range * acceptable to the BSD rshell daemon. * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param host The remote host. * @param port The port to connect to on the remote host. * @param localAddr The local address to use. * @exception SocketException If the socket timeout could not be set. * @exception BindException If all acceptable rshell ports are in use. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. ***/ public void connect(InetAddress host, int port, InetAddress localAddr) throws SocketException, BindException, IOException { int localPort; localPort = MAX_CLIENT_PORT; for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort) { try { _socket_ = _socketFactory_.createSocket(host, port, localAddr, localPort); } catch (BindException be) { continue; } catch (SocketException e) { continue; } break; } if (localPort < MIN_CLIENT_PORT) throw new BindException("All ports in use or insufficient permssion."); _connectAction_(); } /*** * Opens a Socket connected to a remote host at the specified port and * originating from the current host at a port in a range acceptable * to the BSD rshell daemon. * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param host The remote host. * @param port The port to connect to on the remote host. * @exception SocketException If the socket timeout could not be set. * @exception BindException If all acceptable rshell ports are in use. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. ***/ @Override public void connect(InetAddress host, int port) throws SocketException, IOException { connect(host, port, InetAddress.getLocalHost()); } /*** * Opens a Socket connected to a remote host at the specified port and * originating from the current host at a port in a range acceptable * to the BSD rshell daemon. * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param hostname The name of the remote host. * @param port The port to connect to on the remote host. * @exception SocketException If the socket timeout could not be set. * @exception BindException If all acceptable rshell ports are in use. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. * @exception UnknownHostException If the hostname cannot be resolved. ***/ @Override public void connect(String hostname, int port) throws SocketException, IOException, UnknownHostException { connect(InetAddress.getByName(hostname), port, InetAddress.getLocalHost()); } /*** * Opens a Socket connected to a remote host at the specified port and * originating from the specified local address using a port in a range * acceptable to the BSD rshell daemon. * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param hostname The remote host. * @param port The port to connect to on the remote host. * @param localAddr The local address to use. * @exception SocketException If the socket timeout could not be set. * @exception BindException If all acceptable rshell ports are in use. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. ***/ public void connect(String hostname, int port, InetAddress localAddr) throws SocketException, IOException { connect(InetAddress.getByName(hostname), port, localAddr); } /*** * Opens a Socket connected to a remote host at the specified port and * originating from the specified local address and port. The * local port must lie between MIN_CLIENT_PORT and * MAX_CLIENT_PORT or an IllegalArgumentException will * be thrown. * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param host The remote host. * @param port The port to connect to on the remote host. * @param localAddr The local address to use. * @param localPort The local port to use. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. * @exception IllegalArgumentException If an invalid local port number * is specified. ***/ @Override public void connect(InetAddress host, int port, InetAddress localAddr, int localPort) throws SocketException, IOException, IllegalArgumentException { if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT) throw new IllegalArgumentException("Invalid port number " + localPort); super.connect(host, port, localAddr, localPort); } /*** * Opens a Socket connected to a remote host at the specified port and * originating from the specified local address and port. The * local port must lie between MIN_CLIENT_PORT and * MAX_CLIENT_PORT or an IllegalArgumentException will * be thrown. * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param hostname The name of the remote host. * @param port The port to connect to on the remote host. * @param localAddr The local address to use. * @param localPort The local port to use. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. * @exception UnknownHostException If the hostname cannot be resolved. * @exception IllegalArgumentException If an invalid local port number * is specified. ***/ @Override public void connect(String hostname, int port, InetAddress localAddr, int localPort) throws SocketException, IOException, IllegalArgumentException, UnknownHostException { if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT) throw new IllegalArgumentException("Invalid port number " + localPort); super.connect(hostname, port, localAddr, localPort); } /*** * Remotely executes a command through the rshd daemon on the server * to which the RCommandClient is connected. After calling this method, * you may interact with the remote process through its standard input, * output, and error streams. You will typically be able to detect * the termination of the remote process after reaching end of file * on its standard output (accessible through * {@link #getInputStream getInputStream() }. Disconnecting * from the server or closing the process streams before reaching * end of file will not necessarily terminate the remote process. *

* If a separate error stream is requested, the remote server will * connect to a local socket opened by RCommandClient, providing an * independent stream through which standard error will be transmitted. * The local socket must originate from a secure port (512 - 1023), * and rcommand() ensures that this will be so. * RCommandClient will also do a simple security check when it accepts a * connection for this error stream. If the connection does not originate * from the remote server, an IOException will be thrown. This serves as * a simple protection against possible hijacking of the error stream by * an attacker monitoring the rexec() negotiation. You may disable this * behavior with * {@link org.apache.commons.net.bsd.RExecClient#setRemoteVerificationEnabled setRemoteVerificationEnabled()} * . *

* @param localUsername The user account on the local machine that is * requesting the command execution. * @param remoteUsername The account name on the server through which to * execute the command. * @param command The command, including any arguments, to execute. * @param separateErrorStream True if you would like the standard error * to be transmitted through a different stream than standard output. * False if not. * @exception IOException If the rcommand() attempt fails. The exception * will contain a message indicating the nature of the failure. ***/ public void rcommand(String localUsername, String remoteUsername, String command, boolean separateErrorStream) throws IOException { rexec(localUsername, remoteUsername, command, separateErrorStream); } /*** * Same as * rcommand(localUsername, remoteUsername, command, false); ***/ public void rcommand(String localUsername, String remoteUsername, String command) throws IOException { rcommand(localUsername, remoteUsername, command, false); } } commons-net-2.2/src/main/java/org/apache/commons/net/bsd/RExecClient.java0000644000175000017500000002456411354512541026253 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.bsd; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import org.apache.commons.net.SocketClient; import org.apache.commons.net.io.SocketInputStream; /*** * RExecClient implements the rexec() facility that first appeared in * 4.2BSD Unix. This class will probably only be of use for connecting * to Unix systems and only when the rexecd daemon is configured to run, * which is a rarity these days because of the security risks involved. * However, rexec() can be very useful for performing administrative tasks * on a network behind a firewall. *

* As with virtually all of the client classes in org.apache.commons.net, this * class derives from SocketClient, inheriting its connection methods. * The way to use RExecClient is to first connect * to the server, call the {@link #rexec rexec() } method, and then * fetch the connection's input, output, and optionally error streams. * Interaction with the remote command is controlled entirely through the * I/O streams. Once you have finished processing the streams, you should * invoke {@link #disconnect disconnect() } to clean up properly. *

* By default the standard output and standard error streams of the * remote process are transmitted over the same connection, readable * from the input stream returned by * {@link #getInputStream getInputStream() }. However, it is * possible to tell the rexecd daemon to return the standard error * stream over a separate connection, readable from the input stream * returned by {@link #getErrorStream getErrorStream() }. You * can specify that a separate connection should be created for standard * error by setting the boolean separateErrorStream * parameter of {@link #rexec rexec() } to true . * The standard input of the remote process can be written to through * the output stream returned by * {@link #getOutputStream getOutputSream() }. *

*

* @author Daniel F. Savarese * @see SocketClient * @see RCommandClient * @see RLoginClient ***/ public class RExecClient extends SocketClient { /*** * The default rexec port. Set to 512 in BSD Unix. ***/ public static final int DEFAULT_PORT = 512; private boolean __remoteVerificationEnabled; /*** * If a separate error stream is requested, _errorStream_ * will point to an InputStream from which the standard error of the * remote process can be read (after a call to rexec()). Otherwise, * _errorStream_ will be null. ***/ protected InputStream _errorStream_; // This can be overridden in local package to implement port range // limitations of rcmd and rlogin InputStream _createErrorStream() throws IOException { ServerSocket server; Socket socket; server = _serverSocketFactory_.createServerSocket(0, 1, getLocalAddress()); _output_.write(Integer.toString(server.getLocalPort()).getBytes()); _output_.write('\0'); _output_.flush(); socket = server.accept(); server.close(); if (__remoteVerificationEnabled && !verifyRemote(socket)) { socket.close(); throw new IOException( "Security violation: unexpected connection attempt by " + socket.getInetAddress().getHostAddress()); } return (new SocketInputStream(socket, socket.getInputStream())); } /*** * The default RExecClient constructor. Initializes the * default port to DEFAULT_PORT . ***/ public RExecClient() { _errorStream_ = null; setDefaultPort(DEFAULT_PORT); } /*** * Returns the InputStream from which the standard outputof the remote * process can be read. The input stream will only be set after a * successful rexec() invocation. *

* @return The InputStream from which the standard output of the remote * process can be read. ***/ public InputStream getInputStream() { return _input_; } /*** * Returns the OutputStream through which the standard input of the remote * process can be written. The output stream will only be set after a * successful rexec() invocation. *

* @return The OutputStream through which the standard input of the remote * process can be written. ***/ public OutputStream getOutputStream() { return _output_; } /*** * Returns the InputStream from which the standard error of the remote * process can be read if a separate error stream is requested from * the server. Otherwise, null will be returned. The error stream * will only be set after a successful rexec() invocation. *

* @return The InputStream from which the standard error of the remote * process can be read if a separate error stream is requested from * the server. Otherwise, null will be returned. ***/ public InputStream getErrorStream() { return _errorStream_; } /*** * Remotely executes a command through the rexecd daemon on the server * to which the RExecClient is connected. After calling this method, * you may interact with the remote process through its standard input, * output, and error streams. You will typically be able to detect * the termination of the remote process after reaching end of file * on its standard output (accessible through * {@link #getInputStream getInputStream() }. Disconnecting * from the server or closing the process streams before reaching * end of file will not necessarily terminate the remote process. *

* If a separate error stream is requested, the remote server will * connect to a local socket opened by RExecClient, providing an * independent stream through which standard error will be transmitted. * RExecClient will do a simple security check when it accepts a * connection for this error stream. If the connection does not originate * from the remote server, an IOException will be thrown. This serves as * a simple protection against possible hijacking of the error stream by * an attacker monitoring the rexec() negotiation. You may disable this * behavior with {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()} * . *

* @param username The account name on the server through which to execute * the command. * @param password The plain text password of the user account. * @param command The command, including any arguments, to execute. * @param separateErrorStream True if you would like the standard error * to be transmitted through a different stream than standard output. * False if not. * @exception IOException If the rexec() attempt fails. The exception * will contain a message indicating the nature of the failure. ***/ public void rexec(String username, String password, String command, boolean separateErrorStream) throws IOException { int ch; if (separateErrorStream) { _errorStream_ = _createErrorStream(); } else { _output_.write('\0'); } _output_.write(username.getBytes()); _output_.write('\0'); _output_.write(password.getBytes()); _output_.write('\0'); _output_.write(command.getBytes()); _output_.write('\0'); _output_.flush(); ch = _input_.read(); if (ch > 0) { StringBuilder buffer = new StringBuilder(); while ((ch = _input_.read()) != -1 && ch != '\n') buffer.append((char)ch); throw new IOException(buffer.toString()); } else if (ch < 0) { throw new IOException("Server closed connection."); } } /*** * Same as rexec(username, password, command, false); ***/ public void rexec(String username, String password, String command) throws IOException { rexec(username, password, command, false); } /*** * Disconnects from the server, closing all associated open sockets and * streams. *

* @exception IOException If there an error occurs while disconnecting. ***/ @Override public void disconnect() throws IOException { if (_errorStream_ != null) _errorStream_.close(); _errorStream_ = null; super.disconnect(); } /*** * Enable or disable verification that the remote host connecting to * create a separate error stream is the same as the host to which * the standard out stream is connected. The default is for verification * to be enabled. You may set this value at any time, whether the * client is currently connected or not. *

* @param enable True to enable verification, false to disable verification. ***/ public final void setRemoteVerificationEnabled(boolean enable) { __remoteVerificationEnabled = enable; } /*** * Return whether or not verification of the remote host providing a * separate error stream is enabled. The default behavior is for * verification to be enabled. *

* @return True if verification is enabled, false if not. ***/ public final boolean isRemoteVerificationEnabled() { return __remoteVerificationEnabled; } } commons-net-2.2/src/main/java/org/apache/commons/net/bsd/RLoginClient.java0000644000175000017500000001275010542533103026424 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.bsd; import java.io.IOException; /*** * RLoginClient is very similar to * {@link org.apache.commons.net.bsd.RCommandClient}, * from which it is derived, and uses the rcmd() facility implemented * in RCommandClient to implement the functionality of the rlogin command that * first appeared in 4.2BSD Unix. rlogin is a command used to login to * a remote machine from a trusted host, sometimes without issuing a * password. The trust relationship is the same as described in * the documentation for * {@link org.apache.commons.net.bsd.RCommandClient}. *

* As with virtually all of the client classes in org.apache.commons.net, this * class derives from SocketClient. But it relies on the connection * methods defined in RcommandClient which ensure that the local Socket * will originate from an acceptable rshell port. The way to use * RLoginClient is to first connect * to the server, call the {@link #rlogin rlogin() } method, * and then * fetch the connection's input and output streams. * Interaction with the remote command is controlled entirely through the * I/O streams. Once you have finished processing the streams, you should * invoke {@link org.apache.commons.net.bsd.RExecClient#disconnect disconnect() } * to clean up properly. *

* The standard output and standard error streams of the * remote process are transmitted over the same connection, readable * from the input stream returned by * {@link org.apache.commons.net.bsd.RExecClient#getInputStream getInputStream() } * . Unlike RExecClient and RCommandClient, it is * not possible to tell the rlogind daemon to return the standard error * stream over a separate connection. * {@link org.apache.commons.net.bsd.RExecClient#getErrorStream getErrorStream() } * will always return null. * The standard input of the remote process can be written to through * the output stream returned by * {@link org.apache.commons.net.bsd.RExecClient#getOutputStream getOutputSream() } * . *

*

* @author Daniel F. Savarese * @see org.apache.commons.net.SocketClient * @see RExecClient * @see RCommandClient ***/ public class RLoginClient extends RCommandClient { /*** * The default rlogin port. Set to 513 in BSD Unix and according * to RFC 1282. ***/ public static final int DEFAULT_PORT = 513; /*** * The default RLoginClient constructor. Initializes the * default port to DEFAULT_PORT . ***/ public RLoginClient() { setDefaultPort(DEFAULT_PORT); } /*** * Logins into a remote machine through the rlogind daemon on the server * to which the RLoginClient is connected. After calling this method, * you may interact with the remote login shell through its standard input * and output streams. Standard error is sent over the same stream as * standard output. You will typically be able to detect * the termination of the remote login shell after reaching end of file * on its standard output (accessible through * {@link #getInputStream getInputStream() }. Disconnecting * from the server or closing the process streams before reaching * end of file will terminate the remote login shell in most cases. *

* If user authentication fails, the rlogind daemon will request that * a password be entered interactively. You will be able to read the * prompt from the output stream of the RLoginClient and write the * password to the input stream of the RLoginClient. *

* @param localUsername The user account on the local machine that is * trying to login to the remote host. * @param remoteUsername The account name on the server that is * being logged in to. * @param terminalType The name of the user's terminal (e.g., "vt100", * "network", etc.) * @param terminalSpeed The speed of the user's terminal, expressed * as a baud rate or bps (e.g., 9600 or 38400) * @exception IOException If the rlogin() attempt fails. The exception * will contain a message indicating the nature of the failure. ***/ public void rlogin(String localUsername, String remoteUsername, String terminalType, int terminalSpeed) throws IOException { rexec(localUsername, remoteUsername, terminalType + "/" + terminalSpeed, false); } /*** * Same as the other rlogin method, but no terminal speed is defined. ***/ public void rlogin(String localUsername, String remoteUsername, String terminalType) throws IOException { rexec(localUsername, remoteUsername, terminalType, false); } } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/0000755000175000017500000000000011617452466023452 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/nntp/ArticlePointer.java0000644000175000017500000000303311466122735027233 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /** * This class is a structure used to return article number and unique * id information extracted from an NNTP server reply. You will normally * want this information when issuing a STAT command, implemented by * {@link NNTPClient#selectArticle selectArticle}. * @author Daniel F. Savarese * @see NNTPClient */ public final class ArticlePointer { /** The number of the referenced article. */ public int articleNumber; /** * The unique id of the referenced article, including the enclosing * < and > symbols which are technically not part of the * identifier, but are required by all NNTP commands taking an * article id as an argument. */ public String articleId; } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/Threader.java0000644000175000017500000003711211466231525026050 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /** * This is an implementation of a message threading algorithm, as originally devised by Zamie Zawinski. * See http://www.jwz.org/doc/threading.html for details. * For his Java implementation, see http://lxr.mozilla.org/mozilla/source/grendel/sources/grendel/view/Threader.java * * @author rwinston * */ import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; public class Threader { private ThreadContainer root; private HashMap idTable; private int bogusIdCount = 0; /** * The main threader entry point - The client passes in an array of Threadable objects, and * the Threader constructs a connected 'graph' of messages * @param messages array of messages to thread * @return null if messages == null or root.child == null * @deprecated (2.2) prefer {@link #thread(List)} */ @Deprecated public Threadable thread(Threadable[] messages) { return thread(Arrays.asList(messages)); } /** * The main threader entry point - The client passes in a list of Threadable objects, and * the Threader constructs a connected 'graph' of messages * @param messages list of messages to thread * @return null if messages == null or root.child == null * @since 2.2 */ public Threadable thread(List messages) { if (messages == null) return null; idTable = new HashMap(); // walk through each Threadable element for (Threadable t : messages) { if (!t.isDummy()) buildContainer(t); } root = findRootSet(); idTable.clear(); idTable = null; pruneEmptyContainers(root); root.reverseChildren(); gatherSubjects(); if (root.next != null) throw new RuntimeException("root node has a next:" + root); for (ThreadContainer r = root.child; r != null; r = r.next) { if (r.threadable == null) r.threadable = r.child.threadable.makeDummy(); } Threadable result = (root.child == null ? null : root.child.threadable); root.flush(); root = null; return result; } /** * * @param threadable */ private void buildContainer(Threadable threadable) { String id = threadable.messageThreadId(); ThreadContainer container = idTable.get(id); // A ThreadContainer exists for this id already. This should be a forward reference, but may // be a duplicate id, in which case we will need to generate a bogus placeholder id if (container != null) { if (container.threadable != null) { // oops! duplicate ids... id = ""; container = null; } else { // The container just contained a forward reference to this message, so let's // fill in the threadable field of the container with this message container.threadable = threadable; } } // No container exists for that message Id. Create one and insert it into the hash table. if (container == null) { container = new ThreadContainer(); container.threadable = threadable; idTable.put(id, container); } // Iterate through all of the references and create ThreadContainers for any references that // don't have them. ThreadContainer parentRef = null; { String[] references = threadable.messageThreadReferences(); for (int i = 0; i < references.length; ++i) { String refString = references[i]; ThreadContainer ref = idTable.get(refString); // if this id doesnt have a container, create one if (ref == null) { ref = new ThreadContainer(); idTable.put(refString, ref); } // Link references together in the order they appear in the References: header, // IF they dont have a have a parent already && // IF it will not cause a circular reference if ((parentRef != null) && (ref.parent == null) && (parentRef != ref) && !(parentRef.findChild(ref))) { // Link ref into the parent's child list ref.parent = parentRef; ref.next = parentRef.child; parentRef.child = ref; } parentRef = ref; } } // parentRef is now set to the container of the last element in the references field. make that // be the parent of this container, unless doing so causes a circular reference if (parentRef != null && (parentRef == container || container.findChild(parentRef))) parentRef = null; // if it has a parent already, its because we saw this message in a References: field, and presumed // a parent based on the other entries in that field. Now that we have the actual message, we can // throw away the old parent and use this new one if (container.parent != null) { ThreadContainer rest, prev; for (prev = null, rest = container.parent.child; rest != null; prev = rest, rest = rest.next) { if (rest == container) break; } if (rest == null) { throw new RuntimeException( "Didnt find " + container + " in parent" + container.parent); } // Unlink this container from the parent's child list if (prev == null) container.parent.child = container.next; else prev.next = container.next; container.next = null; container.parent = null; } // If we have a parent, link container into the parents child list if (parentRef != null) { container.parent = parentRef; container.next = parentRef.child; parentRef.child = container; } } /** * Find the root set of all existing ThreadContainers * @return root the ThreadContainer representing the root node */ private ThreadContainer findRootSet() { ThreadContainer root = new ThreadContainer(); Iterator iter = idTable.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); ThreadContainer c = idTable.get(key); if (c.parent == null) { if (c.next != null) throw new RuntimeException( "c.next is " + c.next.toString()); c.next = root.child; root.child = c; } } return root; } /** * Delete any empty or dummy ThreadContainers * @param parent */ private void pruneEmptyContainers(ThreadContainer parent) { ThreadContainer container, prev, next; for (prev = null, container = parent.child, next = container.next; container != null; prev = container, container = next, next = (container == null ? null : container.next)) { // Is it empty and without any children? If so,delete it if (container.threadable == null && container.child == null) { if (prev == null) parent.child = container.next; else prev.next = container.next; // Set container to prev so that prev keeps its same value the next time through the loop container = prev; } // Else if empty, with kids, and (not at root or only one kid) else if ( container.threadable == null && container.child != null && (container.parent != null || container.child.next == null)) { // We have an invalid/expired message with kids. Promote the kids to this level. ThreadContainer tail; ThreadContainer kids = container.child; // Remove this container and replace with 'kids'. if (prev == null) parent.child = kids; else prev.next = kids; // Make each child's parent be this level's parent -> i.e. promote the children. Make the last child's next point to this container's next // i.e. splice kids into the list in place of container for (tail = kids; tail.next != null; tail = tail.next) tail.parent = container.parent; tail.parent = container.parent; tail.next = container.next; // next currently points to the item after the inserted items in the chain - reset that so we process the newly // promoted items next time round next = kids; // Set container to prev so that prev keeps its same value the next time through the loop container = prev; } else if (container.child != null) { // A real message , with kids // Iterate over the children pruneEmptyContainers(container); } } } /** * If any two members of the root set have the same subject, merge them. This is to attempt to accomodate messages without References: headers. */ private void gatherSubjects() { int count = 0; for (ThreadContainer c = root.child; c != null; c = c.next) count++; // TODO verify this will avoid rehashing HashMap subjectTable = new HashMap((int) (count * 1.2), (float) 0.9); count = 0; for (ThreadContainer c = root.child; c != null; c = c.next) { Threadable threadable = c.threadable; // No threadable? If so, it is a dummy node in the root set. // Only root set members may be dummies, and they alway have at least 2 kids // Take the first kid as representative of the subject if (threadable == null) threadable = c.child.threadable; String subj = threadable.simplifiedSubject(); if (subj == null || subj == "") continue; ThreadContainer old = subjectTable.get(subj); // Add this container to the table iff: // - There exists no container with this subject // - or this is a dummy container and the old one is not - the dummy one is // more interesting as a root, so put it in the table instead // - The container in the table has a "Re:" version of this subject, and // this container has a non-"Re:" version of this subject. The non-"Re:" version // is the more interesting of the two. if (old == null || (c.threadable == null && old.threadable != null) || (old.threadable != null && old.threadable.subjectIsReply() && c.threadable != null && !c.threadable.subjectIsReply())) { subjectTable.put(subj, c); count++; } } // If the table is empty, we're done if (count == 0) return; // subjectTable is now populated with one entry for each subject which occurs in the // root set. Iterate over the root set, and gather together the difference. ThreadContainer prev, c, rest; for (prev = null, c = root.child, rest = c.next; c != null; prev = c, c = rest, rest = (rest == null ? null : rest.next)) { Threadable threadable = c.threadable; // is it a dummy node? if (threadable == null) threadable = c.child.threadable; String subj = threadable.simplifiedSubject(); // Dont thread together all subjectless messages if (subj == null || subj == "") continue; ThreadContainer old = subjectTable.get(subj); if (old == c) // That's us continue; // We have now found another container in the root set with the same subject // Remove the "second" message from the root set if (prev == null) root.child = c.next; else prev.next = c.next; c.next = null; if (old.threadable == null && c.threadable == null) { // both dummies - merge them ThreadContainer tail; for (tail = old.child; tail != null && tail.next != null; tail = tail.next); tail.next = c.child; for (tail = c.child; tail != null; tail = tail.next) tail.parent = old; c.child = null; } else if ( old.threadable == null || (c.threadable != null && c.threadable.subjectIsReply() && !old.threadable.subjectIsReply())) { // Else if old is empty, or c has "Re:" and old does not ==> make this message a child of old c.parent = old; c.next = old.child; old.child = c; } else { // else make the old and new messages be children of a new dummy container. // We create a new container object for old.msg and empty the old container ThreadContainer newc = new ThreadContainer(); newc.threadable = old.threadable; newc.child = old.child; for (ThreadContainer tail = newc.child; tail != null; tail = tail.next) tail.parent = newc; old.threadable = null; old.child = null; c.parent = old; newc.parent = old; // Old is now a dummy- give it 2 kids , c and newc old.child = c; c.next = newc; } // We've done a merge, so keep the same prev c = prev; } subjectTable.clear(); subjectTable = null; } } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/ThreadContainer.java0000644000175000017500000000614011275650643027365 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /** * A placeholder utility class, used for constructing a tree of Threadables * Original implementation by Jamie Zawinski. * See the Grendel source for more details here * Threadable objects * @author Rory Winston */ class ThreadContainer { Threadable threadable; ThreadContainer parent; ThreadContainer prev; ThreadContainer next; ThreadContainer child; /** * * @param container * @return true if child is under self's tree. Detects circular references */ boolean findChild(ThreadContainer target) { if (child == null) return false; else if (child == target) return true; else return child.findChild(target); } // Copy the ThreadContainer tree structure down into the underlying Threadable objects // (Make the Threadable tree look like the ThreadContainer tree) // TODO convert this to an iterative function - this can blow the stack // with very large Threadable trees void flush() { if (parent != null && threadable == null) throw new RuntimeException("no threadable in " + this.toString()); parent = null; if (threadable != null) threadable.setChild(child == null ? null : child.threadable); if (child != null) { child.flush(); child = null; } if (threadable != null) threadable.setNext(next == null ? null : next.threadable); if (next != null) { next.flush(); next = null; } threadable = null; } /** * Reverse the entire set of children * */ void reverseChildren() { if (child != null) { ThreadContainer kid, prev, rest; for (prev = null, kid = child, rest = kid.next; kid != null; prev = kid, kid = rest, rest = (rest == null ? null : rest.next)) kid.next = prev; child = prev; // Do it for the kids for (kid = child; kid != null; kid = kid.next) kid.reverseChildren(); } } } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NNTPConnectionClosedException.java0000644000175000017500000000356410542533103032115 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; import java.io.IOException; /*** * NNTPConnectionClosedException is used to indicate the premature or * unexpected closing of an NNTP connection resulting from a * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED } * response (NNTP reply code 400) to a * failed NNTP command. This exception is derived from IOException and * therefore may be caught either as an IOException or specifically as an * NNTPConnectionClosedException. *

*

* @author Daniel F. Savarese * @see NNTP * @see NNTPClient ***/ public final class NNTPConnectionClosedException extends IOException { /*** Constructs a NNTPConnectionClosedException with no message ***/ public NNTPConnectionClosedException() { super(); } /*** * Constructs a NNTPConnectionClosedException with a specified message. *

* @param message The message explaining the reason for the exception. ***/ public NNTPConnectionClosedException(String message) { super(message); } } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java0000644000175000017500000002033311354512541030420 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; import java.util.Calendar; /*** * The NewGroupsOrNewsQuery class. This is used to issue NNTP NEWGROUPS and * NEWNEWS queries, implemented by * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsGroups } * and * {@link org.apache.commons.net.nntp.NNTPClient#listNewNews listNewNews } * respectively. It prevents you from having to format * date, time, distribution, and newgroup arguments. *

* You might use the class as follows: *

 * query = new NewsGroupsOrNewsQuery(new GregorianCalendar(97, 11, 15), false);
 * query.addDistribution("comp");
 * NewsgroupInfo[] newsgroups = client.listNewgroups(query);
 * 
* This will retrieve the list of newsgroups starting with the comp. * distribution prefix created since midnight 11/15/97. *

*

* @author Daniel F. Savarese * @see NNTPClient ***/ public final class NewGroupsOrNewsQuery { private String __date, __time; private StringBuffer __distributions; private StringBuffer __newsgroups; private boolean __isGMT; /*** * Creates a new query using the given time as a reference point. *

* @param date The date since which new groups or news have arrived. * @param gmt True if the date should be considered as GMT, false if not. ***/ public NewGroupsOrNewsQuery(Calendar date, boolean gmt) { int num; String str; StringBuilder buffer; __distributions = null; __newsgroups = null; __isGMT = gmt; buffer = new StringBuilder(); // Get year num = date.get(Calendar.YEAR); str = Integer.toString(num); num = str.length(); if (num >= 2) buffer.append(str.substring(num - 2)); else buffer.append("00"); // Get month num = date.get(Calendar.MONTH) + 1; str = Integer.toString(num); num = str.length(); if (num == 1) { buffer.append('0'); buffer.append(str); } else if (num == 2) buffer.append(str); else buffer.append("01"); // Get day num = date.get(Calendar.DAY_OF_MONTH); str = Integer.toString(num); num = str.length(); if (num == 1) { buffer.append('0'); buffer.append(str); } else if (num == 2) buffer.append(str); else buffer.append("01"); __date = buffer.toString(); buffer.setLength(0); // Get hour num = date.get(Calendar.HOUR_OF_DAY); str = Integer.toString(num); num = str.length(); if (num == 1) { buffer.append('0'); buffer.append(str); } else if (num == 2) buffer.append(str); else buffer.append("00"); // Get minutes num = date.get(Calendar.MINUTE); str = Integer.toString(num); num = str.length(); if (num == 1) { buffer.append('0'); buffer.append(str); } else if (num == 2) buffer.append(str); else buffer.append("00"); // Get seconds num = date.get(Calendar.SECOND); str = Integer.toString(num); num = str.length(); if (num == 1) { buffer.append('0'); buffer.append(str); } else if (num == 2) buffer.append(str); else buffer.append("00"); __time = buffer.toString(); } /*** * Add a newsgroup to the list of newsgroups being queried. Newsgroups * added this way are only meaningful to the NEWNEWS command. Newsgroup * names may include the * wildcard, as in * comp.lang.* or comp.lang.java.* . Adding * at least one newsgroup is mandatory for the NEWNEWS command. *

* @param newsgroup The newsgroup to add to the list of groups to be * checked for new news. ***/ public void addNewsgroup(String newsgroup) { if (__newsgroups != null) __newsgroups.append(','); else __newsgroups = new StringBuffer(); __newsgroups.append(newsgroup); } /*** * Add a newsgroup to the list of newsgroups being queried, but indicate * that group should not be checked for new news. Newsgroups * added this way are only meaningful to the NEWNEWS command. * Newsgroup names may include the * wildcard, as in * comp.lang.* or comp.lang.java.* . *

* The following would create a query that searched for new news in * all comp.lang.java newsgroups except for comp.lang.java.advocacy. *

     * query.addNewsgroup("comp.lang.java.*");
     * query.omitNewsgroup("comp.lang.java.advocacy");
     * 
*

* @param newsgroup The newsgroup to add to the list of groups to be * checked for new news, but which should be omitted from * the search for new news.. ***/ public void omitNewsgroup(String newsgroup) { addNewsgroup("!" + newsgroup); } /*** * Add a distribution group to the query. The distribution part of a * newsgroup is the segment of the name preceding the first dot (e.g., * comp, alt, rec). Only those newsgroups matching one of the * distributions or, in the case of NEWNEWS, an article in a newsgroup * matching one of the distributions, will be reported as a query result. * Adding distributions is purely optional. *

* @param distribution A distribution to add to the query. ***/ public void addDistribution(String distribution) { if (__distributions != null) __distributions.append(','); else __distributions = new StringBuffer(); __distributions.append(distribution); } /*** * Return the NNTP query formatted date (year, month, day in the form * YYMMDD. *

* @return The NNTP query formatted date. ***/ public String getDate() { return __date; } /*** * Return the NNTP query formatted time (hour, minutes, seconds in the form * HHMMSS. *

* @return The NNTP query formatted time. ***/ public String getTime() { return __time; } /*** * Return whether or not the query date should be treated as GMT. *

* @return True if the query date is to be treated as GMT, false if not. ***/ public boolean isGMT() { return __isGMT; } /*** * Return the comma separated list of distributions. This may be null * if there are no distributions. *

* @return The list of distributions, which may be null if no distributions * have been specified. ***/ public String getDistributions() { return (__distributions == null ? null : __distributions.toString()); } /*** * Return the comma separated list of newsgroups. This may be null * if there are no newsgroups *

* @return The list of newsgroups, which may be null if no newsgroups * have been specified. ***/ public String getNewsgroups() { return (__newsgroups == null ? null : __newsgroups.toString()); } } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NNTPClient.java0000644000175000017500000014707411466122735026243 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.util.StringTokenizer; import java.util.Vector; import org.apache.commons.net.MalformedServerReplyException; import org.apache.commons.net.io.DotTerminatedMessageReader; import org.apache.commons.net.io.DotTerminatedMessageWriter; import org.apache.commons.net.io.Util; /*** * NNTPClient encapsulates all the functionality necessary to post and * retrieve articles from an NNTP server. As with all classes derived * from {@link org.apache.commons.net.SocketClient}, * you must first connect to the server with * {@link org.apache.commons.net.SocketClient#connect connect } * before doing anything, and finally * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() } * after you're completely finished interacting with the server. * Remember that the * {@link org.apache.commons.net.nntp.NNTP#isAllowedToPost isAllowedToPost()} * method is defined in * {@link org.apache.commons.net.nntp.NNTP}. *

* You should keep in mind that the NNTP server may choose to prematurely * close a connection if the client has been idle for longer than a * given time period or if the server is being shutdown by the operator or * some other reason. The NNTP class will detect a * premature NNTP server connection closing when it receives a * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED } * response to a command. * When that occurs, the NNTP class method encountering that reply will throw * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} * . * NNTPConectionClosedException * is a subclass of IOException and therefore need not be * caught separately, but if you are going to catch it separately, its * catch block must appear before the more general IOException * catch block. When you encounter an * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} * , you must disconnect the connection with * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() } * to properly clean up the * system resources used by NNTP. Before disconnecting, you may check the * last reply code and text with * {@link org.apache.commons.net.nntp.NNTP#getReplyCode getReplyCode } and * {@link org.apache.commons.net.nntp.NNTP#getReplyString getReplyString }. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @author Rory Winston * @author Ted Wise * @see NNTP * @see NNTPConnectionClosedException * @see org.apache.commons.net.MalformedServerReplyException ***/ public class NNTPClient extends NNTP { private void __parseArticlePointer(String reply, ArticlePointer pointer) throws MalformedServerReplyException { StringTokenizer tokenizer; // Do loop is a kluge to simulate goto do { tokenizer = new StringTokenizer(reply); if (tokenizer.countTokens() < 3) break; // Skip numeric response value tokenizer.nextToken(); // Get article number try { pointer.articleNumber = Integer.parseInt(tokenizer.nextToken()); } catch (NumberFormatException e) { break; } // Get article id pointer.articleId = tokenizer.nextToken(); return ; } while (false); throw new MalformedServerReplyException( "Could not parse article pointer.\nServer reply: " + reply); } private void __parseGroupReply(String reply, NewsgroupInfo info) throws MalformedServerReplyException { String count, first, last; StringTokenizer tokenizer; // Do loop is a kluge to simulate goto do { tokenizer = new StringTokenizer(reply); if (tokenizer.countTokens() < 5) break; // Skip numeric response value tokenizer.nextToken(); // Get estimated article count count = tokenizer.nextToken(); // Get first article number first = tokenizer.nextToken(); // Get last article number last = tokenizer.nextToken(); // Get newsgroup name info._setNewsgroup(tokenizer.nextToken()); try { info._setArticleCount(Integer.parseInt(count)); info._setFirstArticle(Integer.parseInt(first)); info._setLastArticle(Integer.parseInt(last)); } catch (NumberFormatException e) { break; } info._setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION); return ; } while (false); throw new MalformedServerReplyException( "Could not parse newsgroup info.\nServer reply: " + reply); } private NewsgroupInfo __parseNewsgroupListEntry(String entry) { NewsgroupInfo result; StringTokenizer tokenizer; int lastNum, firstNum; String last, first, permission; result = new NewsgroupInfo(); tokenizer = new StringTokenizer(entry); if (tokenizer.countTokens() < 4) return null; result._setNewsgroup(tokenizer.nextToken()); last = tokenizer.nextToken(); first = tokenizer.nextToken(); permission = tokenizer.nextToken(); try { lastNum = Integer.parseInt(last); firstNum = Integer.parseInt(first); result._setFirstArticle(firstNum); result._setLastArticle(lastNum); if((firstNum == 0) && (lastNum == 0)) result._setArticleCount(0); else result._setArticleCount(lastNum - firstNum + 1); } catch (NumberFormatException e) { return null; } switch (permission.charAt(0)) { case 'y': case 'Y': result._setPostingPermission( NewsgroupInfo.PERMITTED_POSTING_PERMISSION); break; case 'n': case 'N': result._setPostingPermission( NewsgroupInfo.PROHIBITED_POSTING_PERMISSION); break; case 'm': case 'M': result._setPostingPermission( NewsgroupInfo.MODERATED_POSTING_PERMISSION); break; default: result._setPostingPermission( NewsgroupInfo.UNKNOWN_POSTING_PERMISSION); break; } return result; } private NewsgroupInfo[] __readNewsgroupListing() throws IOException { int size; String line; Vector list; BufferedReader reader; NewsgroupInfo tmp, info[]; reader = new BufferedReader(new DotTerminatedMessageReader(_reader_)); // Start of with a big vector because we may be reading a very large // amount of groups. list = new Vector(2048); while ((line = reader.readLine()) != null) { tmp = __parseNewsgroupListEntry(line); if (tmp != null) list.addElement(tmp); else throw new MalformedServerReplyException(line); } if ((size = list.size()) < 1) return new NewsgroupInfo[0]; info = new NewsgroupInfo[size]; list.copyInto(info); return info; } private Reader __retrieve(int command, String articleId, ArticlePointer pointer) throws IOException { Reader reader; if (articleId != null) { if (!NNTPReply.isPositiveCompletion(sendCommand(command, articleId))) return null; } else { if (!NNTPReply.isPositiveCompletion(sendCommand(command))) return null; } if (pointer != null) __parseArticlePointer(getReplyString(), pointer); reader = new DotTerminatedMessageReader(_reader_); return reader; } private Reader __retrieve(int command, int articleNumber, ArticlePointer pointer) throws IOException { Reader reader; if (!NNTPReply.isPositiveCompletion(sendCommand(command, Integer.toString(articleNumber)))) return null; if (pointer != null) __parseArticlePointer(getReplyString(), pointer); reader = new DotTerminatedMessageReader(_reader_); return reader; } /*** * Retrieves an article from the NNTP server. The article is referenced * by its unique article identifier (including the enclosing < and >). * The article number and identifier contained in the server reply * are returned through an ArticlePointer. The articleId * field of the ArticlePointer cannot always be trusted because some * NNTP servers do not correctly follow the RFC 977 reply format. *

* A DotTerminatedMessageReader is returned from which the article can * be read. If the article does not exist, null is returned. *

* You must not issue any commands to the NNTP server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The NNTP protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the NNTP connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param articleId The unique article identifier of the article to * retrieve. If this parameter is null, the currently selected * article is retrieved. * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return A DotTerminatedMessageReader instance from which the article * be read. null if the article does not exist. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Reader retrieveArticle(String articleId, ArticlePointer pointer) throws IOException { return __retrieve(NNTPCommand.ARTICLE, articleId, pointer); } /*** Same as retrieveArticle(articleId, null) ***/ public Reader retrieveArticle(String articleId) throws IOException { return retrieveArticle(articleId, null); } /*** Same as retrieveArticle(null) ***/ public Reader retrieveArticle() throws IOException { return retrieveArticle(null); } /*** * Retrieves an article from the currently selected newsgroup. The * article is referenced by its article number. * The article number and identifier contained in the server reply * are returned through an ArticlePointer. The articleId * field of the ArticlePointer cannot always be trusted because some * NNTP servers do not correctly follow the RFC 977 reply format. *

* A DotTerminatedMessageReader is returned from which the article can * be read. If the article does not exist, null is returned. *

* You must not issue any commands to the NNTP server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The NNTP protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the NNTP connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param articleNumber The number of the the article to * retrieve. * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return A DotTerminatedMessageReader instance from which the article * be read. null if the article does not exist. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Reader retrieveArticle(int articleNumber, ArticlePointer pointer) throws IOException { return __retrieve(NNTPCommand.ARTICLE, articleNumber, pointer); } /*** Same as retrieveArticle(articleNumber, null) ***/ public Reader retrieveArticle(int articleNumber) throws IOException { return retrieveArticle(articleNumber, null); } /*** * Retrieves an article header from the NNTP server. The article is * referenced * by its unique article identifier (including the enclosing < and >). * The article number and identifier contained in the server reply * are returned through an ArticlePointer. The articleId * field of the ArticlePointer cannot always be trusted because some * NNTP servers do not correctly follow the RFC 977 reply format. *

* A DotTerminatedMessageReader is returned from which the article can * be read. If the article does not exist, null is returned. *

* You must not issue any commands to the NNTP server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The NNTP protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the NNTP connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param articleId The unique article identifier of the article whose * header is being retrieved. If this parameter is null, the * header of the currently selected article is retrieved. * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return A DotTerminatedMessageReader instance from which the article * header can be read. null if the article does not exist. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Reader retrieveArticleHeader(String articleId, ArticlePointer pointer) throws IOException { return __retrieve(NNTPCommand.HEAD, articleId, pointer); } /*** Same as retrieveArticleHeader(articleId, null) ***/ public Reader retrieveArticleHeader(String articleId) throws IOException { return retrieveArticleHeader(articleId, null); } /*** Same as retrieveArticleHeader(null) ***/ public Reader retrieveArticleHeader() throws IOException { return retrieveArticleHeader(null); } /*** * Retrieves an article header from the currently selected newsgroup. The * article is referenced by its article number. * The article number and identifier contained in the server reply * are returned through an ArticlePointer. The articleId * field of the ArticlePointer cannot always be trusted because some * NNTP servers do not correctly follow the RFC 977 reply format. *

* A DotTerminatedMessageReader is returned from which the article can * be read. If the article does not exist, null is returned. *

* You must not issue any commands to the NNTP server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The NNTP protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the NNTP connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param articleNumber The number of the the article whose header is * being retrieved. * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return A DotTerminatedMessageReader instance from which the article * header can be read. null if the article does not exist. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Reader retrieveArticleHeader(int articleNumber, ArticlePointer pointer) throws IOException { return __retrieve(NNTPCommand.HEAD, articleNumber, pointer); } /*** Same as retrieveArticleHeader(articleNumber, null) ***/ public Reader retrieveArticleHeader(int articleNumber) throws IOException { return retrieveArticleHeader(articleNumber, null); } /*** * Retrieves an article body from the NNTP server. The article is * referenced * by its unique article identifier (including the enclosing < and >). * The article number and identifier contained in the server reply * are returned through an ArticlePointer. The articleId * field of the ArticlePointer cannot always be trusted because some * NNTP servers do not correctly follow the RFC 977 reply format. *

* A DotTerminatedMessageReader is returned from which the article can * be read. If the article does not exist, null is returned. *

* You must not issue any commands to the NNTP server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The NNTP protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the NNTP connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param articleId The unique article identifier of the article whose * body is being retrieved. If this parameter is null, the * body of the currently selected article is retrieved. * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return A DotTerminatedMessageReader instance from which the article * body can be read. null if the article does not exist. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Reader retrieveArticleBody(String articleId, ArticlePointer pointer) throws IOException { return __retrieve(NNTPCommand.BODY, articleId, pointer); } /*** Same as retrieveArticleBody(articleId, null) ***/ public Reader retrieveArticleBody(String articleId) throws IOException { return retrieveArticleBody(articleId, null); } /*** Same as retrieveArticleBody(null) ***/ public Reader retrieveArticleBody() throws IOException { return retrieveArticleBody(null); } /*** * Retrieves an article body from the currently selected newsgroup. The * article is referenced by its article number. * The article number and identifier contained in the server reply * are returned through an ArticlePointer. The articleId * field of the ArticlePointer cannot always be trusted because some * NNTP servers do not correctly follow the RFC 977 reply format. *

* A DotTerminatedMessageReader is returned from which the article can * be read. If the article does not exist, null is returned. *

* You must not issue any commands to the NNTP server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The NNTP protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the NNTP connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param articleNumber The number of the the article whose body is * being retrieved. * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return A DotTerminatedMessageReader instance from which the article * body can be read. null if the article does not exist. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Reader retrieveArticleBody(int articleNumber, ArticlePointer pointer) throws IOException { return __retrieve(NNTPCommand.BODY, articleNumber, pointer); } /*** Same as retrieveArticleBody(articleNumber, null) ***/ public Reader retrieveArticleBody(int articleNumber) throws IOException { return retrieveArticleBody(articleNumber, null); } /*** * Select the specified newsgroup to be the target of for future article * retrieval and posting operations. Also return the newsgroup * information contained in the server reply through the info parameter. *

* @param newsgroup The newsgroup to select. * @param info A parameter through which the newsgroup information of * the selected newsgroup contained in the server reply is returned. * Set this to null if you do not desire this information. * @return True if the newsgroup exists and was selected, false otherwise. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean selectNewsgroup(String newsgroup, NewsgroupInfo info) throws IOException { if (!NNTPReply.isPositiveCompletion(group(newsgroup))) return false; if (info != null) __parseGroupReply(getReplyString(), info); return true; } /*** Same as selectNewsgroup(newsgroup, null) ***/ public boolean selectNewsgroup(String newsgroup) throws IOException { return selectNewsgroup(newsgroup, null); } /*** * List the command help from the server. *

* @return The sever help information. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String listHelp() throws IOException { StringWriter help; Reader reader; if (!NNTPReply.isInformational(help())) return null; help = new StringWriter(); reader = new DotTerminatedMessageReader(_reader_); Util.copyReader(reader, help); reader.close(); help.close(); return help.toString(); } /*** * Select an article by its unique identifier (including enclosing * < and >) and return its article number and id through the * pointer parameter. This is achieved through the STAT command. * According to RFC 977, this will NOT set the current article pointer * on the server. To do that, you must reference the article by its * number. *

* @param articleId The unique article identifier of the article that * is being selectedd. If this parameter is null, the * body of the current article is selected * @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return True if successful, false if not. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean selectArticle(String articleId, ArticlePointer pointer) throws IOException { if (articleId != null) { if (!NNTPReply.isPositiveCompletion(stat(articleId))) return false; } else { if (!NNTPReply.isPositiveCompletion(stat())) return false; } if (pointer != null) __parseArticlePointer(getReplyString(), pointer); return true; } /**** Same as selectArticle(articleId, null) ***/ public boolean selectArticle(String articleId) throws IOException { return selectArticle(articleId, null); } /**** * Same as selectArticle(null, articleId) . Useful * for retrieving the current article number. ***/ public boolean selectArticle(ArticlePointer pointer) throws IOException { return selectArticle(null, pointer); } /*** * Select an article in the currently selected newsgroup by its number. * and return its article number and id through the * pointer parameter. This is achieved through the STAT command. * According to RFC 977, this WILL set the current article pointer * on the server. Use this command to select an article before retrieving * it, or to obtain an article's unique identifier given its number. *

* @param articleNumber The number of the article to select from the * currently selected newsgroup. * @param pointer A parameter through which to return the article's * number and unique id. Although the articleId field cannot always * be trusted because of server deviations from RFC 977 reply formats, * we haven't found a server that misformats this information in response * to this particular command. You may set this parameter to null if * you do not desire to retrieve the returned article information. * @return True if successful, false if not. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean selectArticle(int articleNumber, ArticlePointer pointer) throws IOException { if (!NNTPReply.isPositiveCompletion(stat(articleNumber))) return false; if (pointer != null) __parseArticlePointer(getReplyString(), pointer); return true; } /*** Same as selectArticle(articleNumber, null) ***/ public boolean selectArticle(int articleNumber) throws IOException { return selectArticle(articleNumber, null); } /*** * Select the article preceeding the currently selected article in the * currently selected newsgroup and return its number and unique id * through the pointer parameter. Because of deviating server * implementations, the articleId information cannot be trusted. To * obtain the article identifier, issue a * selectArticle(pointer.articleNumber, pointer) immediately * afterward. *

* @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return True if successful, false if not (e.g., there is no previous * article). * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean selectPreviousArticle(ArticlePointer pointer) throws IOException { if (!NNTPReply.isPositiveCompletion(last())) return false; if (pointer != null) __parseArticlePointer(getReplyString(), pointer); return true; } /*** Same as selectPreviousArticle(null) ***/ public boolean selectPreviousArticle() throws IOException { return selectPreviousArticle(null); } /*** * Select the article following the currently selected article in the * currently selected newsgroup and return its number and unique id * through the pointer parameter. Because of deviating server * implementations, the articleId information cannot be trusted. To * obtain the article identifier, issue a * selectArticle(pointer.articleNumber, pointer) immediately * afterward. *

* @param pointer A parameter through which to return the article's * number and unique id. The articleId field cannot always be trusted * because of server deviations from RFC 977 reply formats. You may * set this parameter to null if you do not desire to retrieve the * returned article information. * @return True if successful, false if not (e.g., there is no following * article). * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean selectNextArticle(ArticlePointer pointer) throws IOException { if (!NNTPReply.isPositiveCompletion(next())) return false; if (pointer != null) __parseArticlePointer(getReplyString(), pointer); return true; } /*** Same as selectNextArticle(null) ***/ public boolean selectNextArticle() throws IOException { return selectNextArticle(null); } /*** * List all newsgroups served by the NNTP server. If no newsgroups * are served, a zero length array will be returned. If the command * fails, null will be returned. *

* @return An array of NewsgroupInfo instances containing the information * for each newsgroup served by the NNTP server. If no newsgroups * are served, a zero length array will be returned. If the command * fails, null will be returned. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public NewsgroupInfo[] listNewsgroups() throws IOException { if (!NNTPReply.isPositiveCompletion(list())) return null; return __readNewsgroupListing(); } /** * An overloaded listNewsgroups() command that allows us to * specify with a pattern what groups we want to list. Wraps the * LIST ACTIVE command. *

* @param wildmat a pseudo-regex pattern (cf. RFC 2980) * @return An array of NewsgroupInfo instances containing the information * for each newsgroup served by the NNTP server corresponding to the * supplied pattern. If no such newsgroups are served, a zero length * array will be returned. If the command fails, null will be returned. * @throws IOException */ public NewsgroupInfo[] listNewsgroups(String wildmat) throws IOException { if(!NNTPReply.isPositiveCompletion(listActive(wildmat))) return null; return __readNewsgroupListing(); } /*** * List all new newsgroups added to the NNTP server since a particular * date subject to the conditions of the specified query. If no new * newsgroups were added, a zero length array will be returned. If the * command fails, null will be returned. *

* @param query The query restricting how to search for new newsgroups. * @return An array of NewsgroupInfo instances containing the information * for each new newsgroup added to the NNTP server. If no newsgroups * were added, a zero length array will be returned. If the command * fails, null will be returned. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public NewsgroupInfo[] listNewNewsgroups(NewGroupsOrNewsQuery query) throws IOException { if (!NNTPReply.isPositiveCompletion(newgroups( query.getDate(), query.getTime(), query.isGMT(), query.getDistributions()))) return null; return __readNewsgroupListing(); } /*** * List all new articles added to the NNTP server since a particular * date subject to the conditions of the specified query. If no new * new news is found, a zero length array will be returned. If the * command fails, null will be returned. You must add at least one * newsgroup to the query, else the command will fail. Each String * in the returned array is a unique message identifier including the * enclosing < and >. *

* @param query The query restricting how to search for new news. You * must add at least one newsgroup to the query. * @return An array of String instances containing the unique message * identifiers for each new article added to the NNTP server. If no * new news is found, a zero length array will be returned. If the * command fails, null will be returned. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String[] listNewNews(NewGroupsOrNewsQuery query) throws IOException { int size; String line; Vector list; String[] result; BufferedReader reader; if (!NNTPReply.isPositiveCompletion(newnews( query.getNewsgroups(), query.getDate(), query.getTime(), query.isGMT(), query.getDistributions()))) return null; list = new Vector(); reader = new BufferedReader(new DotTerminatedMessageReader(_reader_)); while ((line = reader.readLine()) != null) list.addElement(line); size = list.size(); if (size < 1) return new String[0]; result = new String[size]; list.copyInto(result); return result; } /*** * There are a few NNTPClient methods that do not complete the * entire sequence of NNTP commands to complete a transaction. These * commands require some action by the programmer after the reception * of a positive preliminary command. After the programmer's code * completes its actions, it must call this method to receive * the completion reply from the server and verify the success of the * entire transaction. *

* For example *

     * writer = client.postArticle();
     * if(writer == null) // failure
     *   return false;
     * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
     * header.addNewsgroup("alt.test");
     * writer.write(header.toString());
     * writer.write("This is just a test");
     * writer.close();
     * if(!client.completePendingCommand()) // failure
     *   return false;
     * 
*

* @return True if successfully completed, false if not. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean completePendingCommand() throws IOException { return NNTPReply.isPositiveCompletion(getReply()); } /*** * Post an article to the NNTP server. This method returns a * DotTerminatedMessageWriter instance to which the article can be * written. Null is returned if the posting attempt fails. You * should check {@link NNTP#isAllowedToPost isAllowedToPost() } * before trying to post. However, a posting * attempt can fail due to malformed headers. *

* You must not issue any commands to the NNTP server (i.e., call any * (other methods) until you finish writing to the returned Writer * instance and close it. The NNTP protocol uses the same stream for * issuing commands as it does for returning results. Therefore the * returned Writer actually writes directly to the NNTP connection. * After you close the writer, you can execute new commands. If you * do not follow these requirements your program will not work properly. *

* Different NNTP servers will require different header formats, but * you can use the provided * {@link org.apache.commons.net.nntp.SimpleNNTPHeader} * class to construct the bare minimum acceptable header for most * news readers. To construct more complicated headers you should * refer to RFC 822. When the Java Mail API is finalized, you will be * able to use it to compose fully compliant Internet text messages. * The DotTerminatedMessageWriter takes care of doubling line-leading * dots and ending the message with a single dot upon closing, so all * you have to worry about is writing the header and the message. *

* Upon closing the returned Writer, you need to call * {@link #completePendingCommand completePendingCommand() } * to finalize the posting and verify its success or failure from * the server reply. *

* @return A DotTerminatedMessageWriter to which the article (including * header) can be written. Returns null if the command fails. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Writer postArticle() throws IOException { if (!NNTPReply.isPositiveIntermediate(post())) return null; return new DotTerminatedMessageWriter(_writer_); } public Writer forwardArticle(String articleId) throws IOException { if (!NNTPReply.isPositiveIntermediate(ihave(articleId))) return null; return new DotTerminatedMessageWriter(_writer_); } /*** * Logs out of the news server gracefully by sending the QUIT command. * However, you must still disconnect from the server before you can open * a new connection. *

* @return True if successfully completed, false if not. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean logout() throws IOException { return NNTPReply.isPositiveCompletion(quit()); } /** * Log into a news server by sending the AUTHINFO USER/AUTHINFO * PASS command sequence. This is usually sent in response to a * 480 reply code from the NNTP server. *

* @param username a valid username * @param password the corresponding password * @return True for successful login, false for a failure * @throws IOException */ public boolean authenticate(String username, String password) throws IOException { int replyCode = authinfoUser(username); if (replyCode == NNTPReply.MORE_AUTH_INFO_REQUIRED) { replyCode = authinfoPass(password); if (replyCode == NNTPReply.AUTHENTICATION_ACCEPTED) { _isAllowedToPost = true; return true; } } return false; } /*** * Private implementation of XOVER functionality. * * See {@link NNTP#xover} * for legal agument formats. Alternatively, read RFC 2980 :-) *

* @param articleRange * @return Returns a DotTerminatedMessageReader if successful, null * otherwise * @exception IOException */ private Reader __retrieveArticleInfo(String articleRange) throws IOException { if (!NNTPReply.isPositiveCompletion(xover(articleRange))) return null; return new DotTerminatedMessageReader(_reader_); } /** * Return article headers for a specified post. *

* @param articleNumber the article to retrieve headers for * @return a DotTerminatedReader if successful, null otherwise * @throws IOException */ public Reader retrieveArticleInfo(int articleNumber) throws IOException { return __retrieveArticleInfo(Integer.toString(articleNumber)); } /** * Return article headers for all articles between lowArticleNumber * and highArticleNumber, inclusively. *

* @param lowArticleNumber * @param highArticleNumber * @return a DotTerminatedReader if successful, null otherwise * @throws IOException */ public Reader retrieveArticleInfo(int lowArticleNumber, int highArticleNumber) throws IOException { return __retrieveArticleInfo(lowArticleNumber + "-" + highArticleNumber); } /*** * Private implementation of XHDR functionality. * * See {@link NNTP#xhdr} * for legal agument formats. Alternatively, read RFC 1036. *

* @param header * @param articleRange * @return Returns a DotTerminatedMessageReader if successful, null * otherwise * @exception IOException */ private Reader __retrieveHeader(String header, String articleRange) throws IOException { if (!NNTPReply.isPositiveCompletion(xhdr(header, articleRange))) return null; return new DotTerminatedMessageReader(_reader_); } /** * Return an article header for a specified post. *

* @param header the header to retrieve * @param articleNumber the article to retrieve the header for * @return a DotTerminatedReader if successful, null otherwise * @throws IOException */ public Reader retrieveHeader(String header, int articleNumber) throws IOException { return __retrieveHeader(header, Integer.toString(articleNumber)); } /** * Return an article header for all articles between lowArticleNumber * and highArticleNumber, inclusively. *

* @param header * @param lowArticleNumber * @param highArticleNumber * @return a DotTerminatedReader if successful, null otherwise * @throws IOException */ public Reader retrieveHeader(String header, int lowArticleNumber, int highArticleNumber) throws IOException { return __retrieveHeader(header,lowArticleNumber + "-" + highArticleNumber); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NNTP.java0000644000175000017500000012433311354512541025067 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import org.apache.commons.net.MalformedServerReplyException; import org.apache.commons.net.ProtocolCommandListener; import org.apache.commons.net.ProtocolCommandSupport; import org.apache.commons.net.SocketClient; /*** * The NNTP class is not meant to be used by itself and is provided * only so that you may easily implement your own NNTP client if * you so desire. If you have no need to perform your own implementation, * you should use {@link org.apache.commons.net.nntp.NNTPClient}. * The NNTP class is made public to provide access to various NNTP constants * and to make it easier for adventurous programmers (or those with special * needs) to interact with the NNTP protocol and implement their own clients. * A set of methods with names corresponding to the NNTP command names are * provided to facilitate this interaction. *

* You should keep in mind that the NNTP server may choose to prematurely * close a connection if the client has been idle for longer than a * given time period or if the server is being shutdown by the operator or * some other reason. The NNTP class will detect a * premature NNTP server connection closing when it receives a * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED } * response to a command. * When that occurs, the NNTP class method encountering that reply will throw * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} * . * NNTPConectionClosedException * is a subclass of IOException and therefore need not be * caught separately, but if you are going to catch it separately, its * catch block must appear before the more general IOException * catch block. When you encounter an * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} * , you must disconnect the connection with * {@link #disconnect disconnect() } to properly clean up the * system resources used by NNTP. Before disconnecting, you may check the * last reply code and text with * {@link #getReplyCode getReplyCode } and * {@link #getReplyString getReplyString }. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @author Rory Winston * @author Ted Wise * @see NNTPClient * @see NNTPConnectionClosedException * @see org.apache.commons.net.MalformedServerReplyException ***/ public class NNTP extends SocketClient { /*** The default NNTP port. Its value is 119 according to RFC 977. ***/ public static final int DEFAULT_PORT = 119; // We have to ensure that the protocol communication is in ASCII // but we use ISO-8859-1 just in case 8-bit characters cross // the wire. private static final String __DEFAULT_ENCODING = "ISO-8859-1"; private StringBuffer __commandBuffer; boolean _isAllowedToPost; int _replyCode; String _replyString; /** * Wraps {@link SocketClient#_input_} * to communicate with server. Initialized by {@link #_connectAction_}. * All server reads should be done through this variable. */ protected BufferedReader _reader_; /** * Wraps {@link SocketClient#_output_} * to communicate with server. Initialized by {@link #_connectAction_}. * All server reads should be done through this variable. */ protected BufferedWriter _writer_; /*** * A ProtocolCommandSupport object used to manage the registering of * ProtocolCommandListeners and te firing of ProtocolCommandEvents. ***/ protected ProtocolCommandSupport _commandSupport_; /*** * The default NNTP constructor. Sets the default port to * DEFAULT_PORT and initializes internal data structures * for saving NNTP reply information. ***/ public NNTP() { setDefaultPort(DEFAULT_PORT); __commandBuffer = new StringBuffer(); _replyString = null; _reader_ = null; _writer_ = null; _isAllowedToPost = false; _commandSupport_ = new ProtocolCommandSupport(this); } private void __getReply() throws IOException { _replyString = _reader_.readLine(); if (_replyString == null) throw new NNTPConnectionClosedException( "Connection closed without indication."); // In case we run into an anomaly we don't want fatal index exceptions // to be thrown. if (_replyString.length() < 3) throw new MalformedServerReplyException( "Truncated server reply: " + _replyString); try { _replyCode = Integer.parseInt(_replyString.substring(0, 3)); } catch (NumberFormatException e) { throw new MalformedServerReplyException( "Could not parse response code.\nServer Reply: " + _replyString); } if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireReplyReceived(_replyCode, _replyString + SocketClient.NETASCII_EOL); if (_replyCode == NNTPReply.SERVICE_DISCONTINUED) throw new NNTPConnectionClosedException( "NNTP response 400 received. Server closed connection."); } /*** * Initiates control connections and gets initial reply, determining * if the client is allowed to post to the server. Initializes * {@link #_reader_} and {@link #_writer_} to wrap * {@link SocketClient#_input_} and {@link SocketClient#_output_}. ***/ @Override protected void _connectAction_() throws IOException { super._connectAction_(); _reader_ = new BufferedReader(new InputStreamReader(_input_, __DEFAULT_ENCODING)); _writer_ = new BufferedWriter(new OutputStreamWriter(_output_, __DEFAULT_ENCODING)); __getReply(); _isAllowedToPost = (_replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED); } /*** * Adds a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to add. ***/ public void addProtocolCommandListener(ProtocolCommandListener listener) { _commandSupport_.addProtocolCommandListener(listener); } /*** * Removes a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to remove. ***/ public void removeProtocolCommandListener(ProtocolCommandListener listener) { _commandSupport_.removeProtocolCommandListener(listener); } /*** * Closes the connection to the NNTP server and sets to null * some internal data so that the memory may be reclaimed by the * garbage collector. The reply text and code information from the * last command is voided so that the memory it used may be reclaimed. *

* @exception IOException If an error occurs while disconnecting. ***/ @Override public void disconnect() throws IOException { super.disconnect(); _reader_ = null; _writer_ = null; _replyString = null; _isAllowedToPost = false; } /*** * Indicates whether or not the client is allowed to post articles to * the server it is currently connected to. *

* @return True if the client can post articles to the server, false * otherwise. ***/ public boolean isAllowedToPost() { return _isAllowedToPost; } /*** * Sends an NNTP command to the server, waits for a reply and returns the * numerical response code. After invocation, for more detailed * information, the actual reply text can be accessed by calling * {@link #getReplyString getReplyString }. *

* @param command The text representation of the NNTP command to send. * @param args The arguments to the NNTP command. If this parameter is * set to null, then the command is sent with no argument. * @return The integer value of the NNTP reply code returned by the server * in response to the command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(String command, String args) throws IOException { String message; __commandBuffer.setLength(0); __commandBuffer.append(command); if (args != null) { __commandBuffer.append(' '); __commandBuffer.append(args); } __commandBuffer.append(SocketClient.NETASCII_EOL); _writer_.write(message = __commandBuffer.toString()); _writer_.flush(); if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireCommandSent(command, message); __getReply(); return _replyCode; } /*** * Sends an NNTP command to the server, waits for a reply and returns the * numerical response code. After invocation, for more detailed * information, the actual reply text can be accessed by calling * {@link #getReplyString getReplyString }. *

* @param command The NNTPCommand constant corresponding to the NNTP command * to send. * @param args The arguments to the NNTP command. If this parameter is * set to null, then the command is sent with no argument. * @return The integer value of the NNTP reply code returned by the server * in response to the command. * in response to the command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(int command, String args) throws IOException { return sendCommand(NNTPCommand._commands[command], args); } /*** * Sends an NNTP command with no arguments to the server, waits for a * reply and returns the numerical response code. After invocation, for * more detailed information, the actual reply text can be accessed by * calling {@link #getReplyString getReplyString }. *

* @param command The text representation of the NNTP command to send. * @return The integer value of the NNTP reply code returned by the server * in response to the command. * in response to the command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(String command) throws IOException { return sendCommand(command, null); } /*** * Sends an NNTP command with no arguments to the server, waits for a * reply and returns the numerical response code. After invocation, for * more detailed information, the actual reply text can be accessed by * calling {@link #getReplyString getReplyString }. *

* @param command The NNTPCommand constant corresponding to the NNTP command * to send. * @return The integer value of the NNTP reply code returned by the server * in response to the command. * in response to the command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(int command) throws IOException { return sendCommand(command, null); } /*** * Returns the integer value of the reply code of the last NNTP reply. * You will usually only use this method after you connect to the * NNTP server to check that the connection was successful since * connect is of type void. *

* @return The integer value of the reply code of the last NNTP reply. ***/ public int getReplyCode() { return _replyCode; } /*** * Fetches a reply from the NNTP server and returns the integer reply * code. After calling this method, the actual reply text can be accessed * from {@link #getReplyString getReplyString }. Only use this * method if you are implementing your own NNTP client or if you need to * fetch a secondary response from the NNTP server. *

* @return The integer value of the reply code of the fetched NNTP reply. * in response to the command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while * receiving the server reply. ***/ public int getReply() throws IOException { __getReply(); return _replyCode; } /*** * Returns the entire text of the last NNTP server response exactly * as it was received, not including the end of line marker. *

* @return The entire text from the last NNTP response as a String. ***/ public String getReplyString() { return _replyString; } /*** * A convenience method to send the NNTP ARTICLE command to the server, * receive the initial reply, and return the reply code. *

* @param messageId The message identifier of the requested article, * including the encapsulating < and > characters. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int article(String messageId) throws IOException { return sendCommand(NNTPCommand.ARTICLE, messageId); } /*** * A convenience method to send the NNTP ARTICLE command to the server, * receive the initial reply, and return the reply code. *

* @param articleNumber The number of the article to request from the * currently selected newsgroup. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int article(int articleNumber) throws IOException { return sendCommand(NNTPCommand.ARTICLE, Integer.toString(articleNumber)); } /*** * A convenience method to send the NNTP ARTICLE command to the server, * receive the initial reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int article() throws IOException { return sendCommand(NNTPCommand.ARTICLE); } /*** * A convenience method to send the NNTP BODY command to the server, * receive the initial reply, and return the reply code. *

* @param messageId The message identifier of the requested article, * including the encapsulating < and > characters. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int body(String messageId) throws IOException { return sendCommand(NNTPCommand.BODY, messageId); } /*** * A convenience method to send the NNTP BODY command to the server, * receive the initial reply, and return the reply code. *

* @param articleNumber The number of the article to request from the * currently selected newsgroup. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int body(int articleNumber) throws IOException { return sendCommand(NNTPCommand.BODY, Integer.toString(articleNumber)); } /*** * A convenience method to send the NNTP BODY command to the server, * receive the initial reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int body() throws IOException { return sendCommand(NNTPCommand.BODY); } /*** * A convenience method to send the NNTP HEAD command to the server, * receive the initial reply, and return the reply code. *

* @param messageId The message identifier of the requested article, * including the encapsulating < and > characters. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int head(String messageId) throws IOException { return sendCommand(NNTPCommand.HEAD, messageId); } /*** * A convenience method to send the NNTP HEAD command to the server, * receive the initial reply, and return the reply code. *

* @param articleNumber The number of the article to request from the * currently selected newsgroup. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int head(int articleNumber) throws IOException { return sendCommand(NNTPCommand.HEAD, Integer.toString(articleNumber)); } /*** * A convenience method to send the NNTP HEAD command to the server, * receive the initial reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int head() throws IOException { return sendCommand(NNTPCommand.HEAD); } /*** * A convenience method to send the NNTP STAT command to the server, * receive the initial reply, and return the reply code. *

* @param messageId The message identifier of the requested article, * including the encapsulating < and > characters. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stat(String messageId) throws IOException { return sendCommand(NNTPCommand.STAT, messageId); } /*** * A convenience method to send the NNTP STAT command to the server, * receive the initial reply, and return the reply code. *

* @param articleNumber The number of the article to request from the * currently selected newsgroup. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stat(int articleNumber) throws IOException { return sendCommand(NNTPCommand.STAT, Integer.toString(articleNumber)); } /*** * A convenience method to send the NNTP STAT command to the server, * receive the initial reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stat() throws IOException { return sendCommand(NNTPCommand.STAT); } /*** * A convenience method to send the NNTP GROUP command to the server, * receive the reply, and return the reply code. *

* @param newsgroup The name of the newsgroup to select. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int group(String newsgroup) throws IOException { return sendCommand(NNTPCommand.GROUP, newsgroup); } /*** * A convenience method to send the NNTP HELP command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int help() throws IOException { return sendCommand(NNTPCommand.HELP); } /*** * A convenience method to send the NNTP IHAVE command to the server, * receive the reply, and return the reply code. *

* @param messageId The article identifier, * including the encapsulating < and > characters. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int ihave(String messageId) throws IOException { return sendCommand(NNTPCommand.IHAVE, messageId); } /*** * A convenience method to send the NNTP LAST command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int last() throws IOException { return sendCommand(NNTPCommand.LAST); } /*** * A convenience method to send the NNTP LIST command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int list() throws IOException { return sendCommand(NNTPCommand.LIST); } /*** * A convenience method to send the NNTP NEXT command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int next() throws IOException { return sendCommand(NNTPCommand.NEXT); } /*** * A convenience method to send the NNTP NEWGROUPS command to the server, * receive the reply, and return the reply code. *

* @param date The date after which to check for new groups. * Date format is YYMMDD * @param time The time after which to check for new groups. * Time format is HHMMSS using a 24-hour clock. * @param GMT True if the time is in GMT, false if local server time. * @param distributions Comma-separated distribution list to check for * new groups. Set to null if no distributions. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int newgroups(String date, String time, boolean GMT, String distributions) throws IOException { StringBuilder buffer = new StringBuilder(); buffer.append(date); buffer.append(' '); buffer.append(time); if (GMT) { buffer.append(' '); buffer.append("GMT"); } if (distributions != null) { buffer.append(" <"); buffer.append(distributions); buffer.append('>'); } return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString()); } /*** * A convenience method to send the NNTP NEWGROUPS command to the server, * receive the reply, and return the reply code. *

* @param newsgroups A comma-separated list of newsgroups to check for new * news. * @param date The date after which to check for new news. * Date format is YYMMDD * @param time The time after which to check for new news. * Time format is HHMMSS using a 24-hour clock. * @param GMT True if the time is in GMT, false if local server time. * @param distributions Comma-separated distribution list to check for * new news. Set to null if no distributions. * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int newnews(String newsgroups, String date, String time, boolean GMT, String distributions) throws IOException { StringBuilder buffer = new StringBuilder(); buffer.append(newsgroups); buffer.append(' '); buffer.append(date); buffer.append(' '); buffer.append(time); if (GMT) { buffer.append(' '); buffer.append("GMT"); } if (distributions != null) { buffer.append(" <"); buffer.append(distributions); buffer.append('>'); } return sendCommand(NNTPCommand.NEWNEWS, buffer.toString()); } /*** * A convenience method to send the NNTP POST command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int post() throws IOException { return sendCommand(NNTPCommand.POST); } /*** * A convenience method to send the NNTP QUIT command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int quit() throws IOException { return sendCommand(NNTPCommand.QUIT); } /*** * A convenience method to send the AUTHINFO USER command to the server, * receive the reply, and return the reply code. (See RFC 2980) *

* @param username A valid username. * @return The reply code received from the server. The server should * return a 381 or 281 for this command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int authinfoUser(String username) throws IOException { String userParameter = "USER " + username; return sendCommand(NNTPCommand.AUTHINFO, userParameter); } /*** * A convenience method to send the AUTHINFO PASS command to the server, * receive the reply, and return the reply code. If this step is * required, it should immediately follow the AUTHINFO USER command * (See RFC 2980) *

* @param password a valid password. * @return The reply code received from the server. The server should * return a 281 or 502 for this command. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int authinfoPass(String password) throws IOException { String passParameter = "PASS " + password; return sendCommand(NNTPCommand.AUTHINFO, passParameter); } /*** * A convenience method to send the NNTP XOVER command to the server, * receive the reply, and return the reply code. *

* @param selectedArticles a String representation of the range of * article headers required. This may be an article number, or a * range of article numbers in the form "XXXX-YYYY", where XXXX * and YYYY are valid article numbers in the current group. It * also may be of the form "XXX-", meaning "return XXX and all * following articles" In this revision, the last format is not * possible (yet). * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int xover(String selectedArticles) throws IOException { return sendCommand(NNTPCommand.XOVER, selectedArticles); } /*** * A convenience method to send the NNTP XHDR command to the server, * receive the reply, and return the reply code. *

* @param header a String naming a header line (e.g., "subject"). See * RFC-1036 for a list of valid header lines. * @param selectedArticles a String representation of the range of * article headers required. This may be an article number, or a * range of article numbers in the form "XXXX-YYYY", where XXXX * and YYYY are valid article numbers in the current group. It * also may be of the form "XXX-", meaning "return XXX and all * following articles" In this revision, the last format is not * possible (yet). * @return The reply code received from the server. * @exception NNTPConnectionClosedException * If the NNTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send NNTP reply code 400. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int xhdr(String header, String selectedArticles) throws IOException { StringBuilder command = new StringBuilder(header); command.append(" "); command.append(selectedArticles); return sendCommand(NNTPCommand.XHDR, command.toString()); } /** * A convenience wrapper for the extended LIST command that takes * an argument, allowing us to selectively list multiple groups. *

* @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for * details. * @return the reply code received from the server. * @throws IOException */ public int listActive(String wildmat) throws IOException { StringBuilder command = new StringBuilder("ACTIVE "); command.append(wildmat); return sendCommand(NNTPCommand.LIST, command.toString()); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NNTPCommand.java0000644000175000017500000000530110542533103026352 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /*** * NNTPCommand stores a set of constants for NNTP command codes. To interpret * the meaning of the codes, familiarity with RFC 977 is assumed. *

* @author Daniel F. Savarese * @author Rory Winston * @author Ted Wise ***/ public final class NNTPCommand { public static final int ARTICLE = 0; public static final int BODY = 1; public static final int GROUP = 2; public static final int HEAD = 3; public static final int HELP = 4; public static final int IHAVE = 5; public static final int LAST = 6; public static final int LIST = 7; public static final int NEWGROUPS = 8; public static final int NEWNEWS = 9; public static final int NEXT = 10; public static final int POST = 11; public static final int QUIT = 12; public static final int SLAVE = 13; public static final int STAT = 14; public static final int AUTHINFO = 15; public static final int XOVER = 16; public static final int XHDR = 17; // Cannot be instantiated private NNTPCommand() {} static final String[] _commands = { "ARTICLE", "BODY", "GROUP", "HEAD", "HELP", "IHAVE", "LAST", "LIST", "NEWGROUPS", "NEWNEWS", "NEXT", "POST", "QUIT", "SLAVE", "STAT", "AUTHINFO", "XOVER", "XHDR" }; /*** * Retrieve the NNTP protocol command string corresponding to a specified * command code. *

* @param command The command code. * @return The NNTP protcol command string corresponding to a specified * command code. ***/ public static final String getCommand(int command) { return _commands[command]; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/nntp/SimpleNNTPHeader.java0000644000175000017500000001232511354512541027347 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /*** * This class is used to construct the bare minimum * acceptable header for most news readers. To construct more * complicated headers you should refer to RFC 822. When the * Java Mail API is finalized, you will be * able to use it to compose fully compliant Internet text messages. *

* The main purpose of the class is to faciliatate the article posting * process, by relieving the programmer from having to explicitly format * an article header. For example: *

 * writer = client.postArticle();
 * if(writer == null) // failure
 *   return false;
 * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
 * header.addNewsgroup("alt.test");
 * header.addHeaderField("Organization", "Foobar, Inc.");
 * writer.write(header.toString());
 * writer.write("This is just a test");
 * writer.close();
 * if(!client.completePendingCommand()) // failure
 *   return false;
 * 
*

*

* @author Daniel F. Savarese * @see NNTPClient ***/ public class SimpleNNTPHeader { private String __subject, __from; private StringBuilder __newsgroups; private StringBuilder __headerFields; private int __newsgroupCount; /*** * Creates a new SimpleNNTPHeader instance initialized with the given * from and subject header field values. *

* @param from The value of the From: header field. This * should be the article poster's email address. * @param subject The value of the Subject: header field. * This should be the subject of the article. ***/ public SimpleNNTPHeader(String from, String subject) { __from = from; __subject = subject; __newsgroups = new StringBuilder(); __headerFields = new StringBuilder(); __newsgroupCount = 0; } /*** * Adds a newsgroup to the article Newsgroups: field. *

* @param newsgroup The newsgroup to add to the article's newsgroup * distribution list. ***/ public void addNewsgroup(String newsgroup) { if (__newsgroupCount++ > 0) __newsgroups.append(','); __newsgroups.append(newsgroup); } /*** * Adds an arbitrary header field with the given value to the article * header. These headers will be written after the From, Newsgroups, * and Subject fields when the SimpleNNTPHeader is convertered to a string. * An example use would be: *

     * header.addHeaderField("Organization", "Foobar, Inc.");
     * 
*

* @param headerField The header field to add, not including the colon. * @param value The value of the added header field. ***/ public void addHeaderField(String headerField, String value) { __headerFields.append(headerField); __headerFields.append(": "); __headerFields.append(value); __headerFields.append('\n'); } /*** * Returns the address used in the From: header field. *

* @return The from address. ***/ public String getFromAddress() { return __from; } /*** * Returns the subject used in the Subject: header field. *

* @return The subject. ***/ public String getSubject() { return __subject; } /*** * Returns the contents of the Newsgroups: header field. *

* @return The comma-separated list of newsgroups to which the article * is being posted. ***/ public String getNewsgroups() { return __newsgroups.toString(); } /*** * Converts the SimpleNNTPHeader to a properly formatted header in * the form of a String, including the blank line used to separate * the header from the article body. *

* @return The article header in the form of a String. ***/ @Override public String toString() { StringBuilder header = new StringBuilder(); header.append("From: "); header.append(__from); header.append("\nNewsgroups: "); header.append(__newsgroups.toString()); header.append("\nSubject: "); header.append(__subject); header.append('\n'); if (__headerFields.length() > 0) header.append(__headerFields.toString()); header.append('\n'); return header.toString(); } } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NewsgroupInfo.java0000644000175000017500000001064311466122735027121 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /*** * NewsgroupInfo stores information pertaining to a newsgroup returned by * the NNTP GROUP, LIST, and NEWGROUPS commands, implemented by * {@link org.apache.commons.net.nntp.NNTPClient#selectNewsgroup selectNewsgroup } * , * {@link org.apache.commons.net.nntp.NNTPClient#listNewsgroups listNewsgroups } * , and * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsgroups } * respectively. *

*

* @author Daniel F. Savarese * @see NNTPClient ***/ public final class NewsgroupInfo { /*** * A constant indicating that the posting permission of a newsgroup is * unknown. For example, the NNTP GROUP command does not return posting * information, so NewsgroupInfo instances obtained from that command * willhave an UNKNOWN_POSTING_PERMISSION. ***/ public static final int UNKNOWN_POSTING_PERMISSION = 0; /*** A constant indicating that a newsgroup is moderated. ***/ public static final int MODERATED_POSTING_PERMISSION = 1; /*** A constant indicating that a newsgroup is public and unmoderated. ***/ public static final int PERMITTED_POSTING_PERMISSION = 2; /*** * A constant indicating that a newsgroup is closed for general posting. ***/ public static final int PROHIBITED_POSTING_PERMISSION = 3; private String __newsgroup; private int __estimatedArticleCount; private int __firstArticle, __lastArticle; private int __postingPermission; void _setNewsgroup(String newsgroup) { __newsgroup = newsgroup; } void _setArticleCount(int count) { __estimatedArticleCount = count; } void _setFirstArticle(int first) { __firstArticle = first; } void _setLastArticle(int last) { __lastArticle = last; } void _setPostingPermission(int permission) { __postingPermission = permission; } /*** * Get the newsgroup name. *

* @return The name of the newsgroup. ***/ public String getNewsgroup() { return __newsgroup; } /*** * Get the estimated number of articles in the newsgroup. The * accuracy of this value will depend on the server implementation. *

* @return The estimated number of articles in the newsgroup. ***/ public int getArticleCount() { return __estimatedArticleCount; } /*** * Get the number of the first article in the newsgroup. *

* @return The number of the first article in the newsgroup. ***/ public int getFirstArticle() { return __firstArticle; } /*** * Get the number of the last article in the newsgroup. *

* @return The number of the last article in the newsgroup. ***/ public int getLastArticle() { return __lastArticle; } /*** * Get the posting permission of the newsgroup. This will be one of * the POSTING_PERMISSION constants. *

* @return The posting permission status of the newsgroup. ***/ public int getPostingPermission() { return __postingPermission; } /* public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(__newsgroup); buffer.append(' '); buffer.append(__lastArticle); buffer.append(' '); buffer.append(__firstArticle); buffer.append(' '); switch(__postingPermission) { case 1: buffer.append('m'); break; case 2: buffer.append('y'); break; case 3: buffer.append('n'); break; } return buffer.toString(); } */ } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/Threadable.java0000644000175000017500000000243111014672436026340 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /** * A placeholder interface for threadable message objects * Author: Rory Winston * */ public interface Threadable { public boolean isDummy(); public String messageThreadId(); public String[] messageThreadReferences(); public String simplifiedSubject(); public boolean subjectIsReply(); public void setChild(Threadable child); public void setNext(Threadable next); public Threadable makeDummy(); } commons-net-2.2/src/main/java/org/apache/commons/net/nntp/NNTPReply.java0000644000175000017500000002246311466231525026110 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; /*** * NNTPReply stores a set of constants for NNTP reply codes. To interpret * the meaning of the codes, familiarity with RFC 977 is assumed. * The mnemonic constant names are transcriptions from the code descriptions * of RFC 977. For those who think in terms of the actual reply code values, * a set of CODE_NUM constants are provided where NUM is the numerical value * of the code. *

*

* @author Daniel F. Savarese ***/ public final class NNTPReply { // TODO - drop all these numeric constants? public static final int CODE_100 = 100; public static final int CODE_199 = 199; public static final int CODE_200 = 200; public static final int CODE_201 = 201; public static final int CODE_202 = 202; public static final int CODE_205 = 205; public static final int CODE_211 = 211; public static final int CODE_215 = 215; public static final int CODE_220 = 220; public static final int CODE_221 = 221; public static final int CODE_222 = 222; public static final int CODE_223 = 223; public static final int CODE_230 = 230; public static final int CODE_231 = 231; public static final int CODE_235 = 235; public static final int CODE_240 = 240; public static final int CODE_281 = 281; public static final int CODE_335 = 335; public static final int CODE_340 = 340; public static final int CODE_381 = 381; public static final int CODE_400 = 400; public static final int CODE_408 = 408; // Not actually needed; kept for API compatibility public static final int CODE_411 = 411; public static final int CODE_412 = 412; public static final int CODE_420 = 420; public static final int CODE_421 = 421; public static final int CODE_422 = 422; public static final int CODE_423 = 423; public static final int CODE_430 = 430; public static final int CODE_435 = 435; public static final int CODE_436 = 436; public static final int CODE_437 = 437; public static final int CODE_440 = 440; public static final int CODE_441 = 441; /** @since 2.2 */ public static final int CODE_480 = 480; public static final int CODE_482 = 482; public static final int CODE_500 = 500; public static final int CODE_501 = 501; public static final int CODE_502 = 502; public static final int CODE_503 = 503; public static final int HELP_TEXT_FOLLOWS = CODE_100; public static final int DEBUG_OUTPUT = CODE_199; public static final int SERVER_READY_POSTING_ALLOWED = CODE_200; public static final int SERVER_READY_POSTING_NOT_ALLOWED = CODE_201; public static final int SLAVE_STATUS_NOTED = CODE_202; public static final int CLOSING_CONNECTION = CODE_205; public static final int GROUP_SELECTED = CODE_211; public static final int ARTICLE_RETRIEVED_HEAD_AND_BODY_FOLLOW = CODE_220; public static final int ARTICLE_RETRIEVED_HEAD_FOLLOWS = CODE_221; public static final int ARTICLE_RETRIEVED_BODY_FOLLOWS = CODE_222; public static final int ARTICLE_RETRIEVED_REQUEST_TEXT_SEPARATELY = CODE_223; public static final int ARTICLE_LIST_BY_MESSAGE_ID_FOLLOWS = CODE_230; public static final int NEW_NEWSGROUP_LIST_FOLLOWS = CODE_231; public static final int ARTICLE_TRANSFERRED_OK = CODE_235; public static final int ARTICLE_POSTED_OK = CODE_240; public static final int AUTHENTICATION_ACCEPTED = CODE_281; public static final int SEND_ARTICLE_TO_TRANSFER = CODE_335; public static final int SEND_ARTICLE_TO_POST = CODE_340; public static final int MORE_AUTH_INFO_REQUIRED = CODE_381; public static final int SERVICE_DISCONTINUED = CODE_400; public static final int NO_SUCH_NEWSGROUP = CODE_411; public static final int NO_NEWSGROUP_SELECTED = CODE_412; public static final int NO_CURRENT_ARTICLE_SELECTED = CODE_420; public static final int NO_NEXT_ARTICLE = CODE_421; public static final int NO_PREVIOUS_ARTICLE = CODE_422; public static final int NO_SUCH_ARTICLE_NUMBER = CODE_423; public static final int NO_SUCH_ARTICLE_FOUND = CODE_430; public static final int ARTICLE_NOT_WANTED = CODE_435; public static final int TRANSFER_FAILED = CODE_436; public static final int ARTICLE_REJECTED = CODE_437; public static final int POSTING_NOT_ALLOWED = CODE_440; public static final int POSTING_FAILED = CODE_441; /** @since 2.2 - corrected value to 480 */ public static final int AUTHENTICATION_REQUIRED = CODE_480; public static final int AUTHENTICATION_REJECTED = CODE_482; public static final int COMMAND_NOT_RECOGNIZED = CODE_500; public static final int COMMAND_SYNTAX_ERROR = CODE_501; public static final int PERMISSION_DENIED = CODE_502; public static final int PROGRAM_FAULT = CODE_503; // Cannot be instantiated private NNTPReply() {} /*** * Determine if a reply code is an informational response. All * codes beginning with a 1 are positive informational responses. * Informational responses are used to provide human readable * information such as help text. *

* @param reply The reply code to test. * @return True if a reply code is an informational response, false * if not. ***/ public static boolean isInformational(int reply) { return (reply >= 100 && reply < 200); } /*** * Determine if a reply code is a positive completion response. All * codes beginning with a 2 are positive completion responses. * The NNTP server will send a positive completion response on the final * successful completion of a command. *

* @param reply The reply code to test. * @return True if a reply code is a postive completion response, false * if not. ***/ public static boolean isPositiveCompletion(int reply) { return (reply >= 200 && reply < 300); } /*** * Determine if a reply code is a positive intermediate response. All * codes beginning with a 3 are positive intermediate responses. * The NNTP server will send a positive intermediate response on the * successful completion of one part of a multi-part command or * sequence of commands. For example, after a successful POST command, * a positive intermediate response will be sent to indicate that the * server is ready to receive the article to be posted. *

* @param reply The reply code to test. * @return True if a reply code is a postive intermediate response, false * if not. ***/ public static boolean isPositiveIntermediate(int reply) { return (reply >= 300 && reply < 400); } /*** * Determine if a reply code is a negative transient response. All * codes beginning with a 4 are negative transient responses. * The NNTP server will send a negative transient response on the * failure of a correctly formatted command that could not be performed * for some reason. For example, retrieving an article that does not * exist will result in a negative transient response. *

* @param reply The reply code to test. * @return True if a reply code is a negative transient response, false * if not. ***/ public static boolean isNegativeTransient(int reply) { return (reply >= 400 && reply < 500); } /*** * Determine if a reply code is a negative permanent response. All * codes beginning with a 5 are negative permanent responses. * The NNTP server will send a negative permanent response when * it does not implement a command, a command is incorrectly formatted, * or a serious program error occurs. *

* @param reply The reply code to test. * @return True if a reply code is a negative permanent response, false * if not. ***/ public static boolean isNegativePermanent(int reply) { return (reply >= 500 && reply < 600); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/nntp/Article.java0000644000175000017500000001627111466233505025700 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.nntp; import java.util.ArrayList; import java.util.StringTokenizer; /** * This is a class that contains the basic state needed for message retrieval and threading. * With thanks to Jamie Zawinski * @author rwinston * */ public class Article implements Threadable { private int articleNumber; private String subject; private String date; private String articleId; private String simplifiedSubject; private String from; private StringBuffer header; private StringBuffer references; private boolean isReply = false; public Article kid, next; public Article() { header = new StringBuffer(); } /** * Adds an arbitrary header key and value to this message's header. * @param name the header name * @param val the header value */ public void addHeaderField(String name, String val) { header.append(name); header.append(": "); header.append(val); header.append('\n'); } /** * Adds a message-id to the list of messages that this message references (i.e. replies to) * @param msgId */ public void addReference(String msgId) { if (references == null) { references = new StringBuffer(); references.append("References: "); } references.append(msgId); references.append("\t"); } /** * Returns the MessageId references as an array of Strings * @return an array of message-ids */ public String[] getReferences() { if (references == null) return new String[0]; ArrayList list = new ArrayList(); int terminator = references.toString().indexOf(':'); StringTokenizer st = new StringTokenizer(references.substring(terminator), "\t"); while (st.hasMoreTokens()) { list.add(st.nextToken()); } return list.toArray(new String[list.size()]); } /** * Attempts to parse the subject line for some typical reply signatures, and strip them out * */ private void simplifySubject() { int start = 0; String subject = getSubject(); int len = subject.length(); boolean done = false; while (!done) { done = true; // skip whitespace // "Re: " breaks this while (start < len && subject.charAt(start) == ' ') { start++; } if (start < (len - 2) && (subject.charAt(start) == 'r' || subject.charAt(start) == 'R') && (subject.charAt(start + 1) == 'e' || subject.charAt(start + 1) == 'E')) { if (subject.charAt(start + 2) == ':') { start += 3; // Skip "Re:" isReply = true; done = false; } else if ( start < (len - 2) && (subject.charAt(start + 2) == '[' || subject.charAt(start + 2) == '(')) { int i = start + 3; while (i < len && subject.charAt(i) >= '0' && subject.charAt(i) <= '9') i++; if (i < (len - 1) && (subject.charAt(i) == ']' || subject.charAt(i) == ')') && subject.charAt(i + 1) == ':') { start = i + 2; isReply = true; done = false; } } } if ("(no subject)".equals(simplifiedSubject)) simplifiedSubject = ""; int end = len; while (end > start && subject.charAt(end - 1) < ' ') end--; if (start == 0 && end == len) simplifiedSubject = subject; else simplifiedSubject = subject.substring(start, end); } } /** * Recursive method that traverses a pre-threaded graph (or tree) * of connected Article objects and prints them out. * @param article the root of the article 'tree' * @param depth the current tree depth */ public static void printThread(Article article, int depth) { for (int i = 0; i < depth; ++i) System.out.print("==>"); System.out.println(article.getSubject() + "\t" + article.getFrom()); if (article.kid != null) printThread(article.kid, depth + 1); if (article.next != null) printThread(article.next, depth); } public String getArticleId() { return articleId; } public int getArticleNumber() { return articleNumber; } public String getDate() { return date; } public String getFrom() { return from; } public String getSubject() { return subject; } public void setArticleId(String string) { articleId = string; } public void setArticleNumber(int i) { articleNumber = i; } public void setDate(String string) { date = string; } public void setFrom(String string) { from = string; } public void setSubject(String string) { subject = string; } public boolean isDummy() { return (getSubject() == null); } public String messageThreadId() { return articleId; } public String[] messageThreadReferences() { return getReferences(); } public String simplifiedSubject() { if(simplifiedSubject == null) simplifySubject(); return simplifiedSubject; } public boolean subjectIsReply() { if(simplifiedSubject == null) simplifySubject(); return isReply; } public void setChild(Threadable child) { this.kid = (Article) child; flushSubjectCache(); } private void flushSubjectCache() { simplifiedSubject = null; } public void setNext(Threadable next) { this.next = (Article)next; flushSubjectCache(); } public Threadable makeDummy() { return new Article(); } } commons-net-2.2/src/main/java/org/apache/commons/net/whois/0000755000175000017500000000000011617452466023624 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/whois/WhoisClient.java0000644000175000017500000000716210761044665026722 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.whois; import java.io.IOException; import java.io.InputStream; import org.apache.commons.net.finger.FingerClient; /*** * The WhoisClient class implements the client side of the Internet Whois * Protocol defined in RFC 954. To query a host you create a * WhoisClient instance, connect to the host, query the host, and finally * disconnect from the host. If the whois service you want to query is on * a non-standard port, connect to the host at that port. * Here's a sample use: *

 *    WhoisClient whois;
 *
 *    whois = new WhoisClient();
 *
 *    try {
 *      whois.connect(WhoisClient.DEFAULT_HOST);
 *      System.out.println(whois.query("foobar"));
 *      whois.disconnect();
 *    } catch(IOException e) {
 *      System.err.println("Error I/O exception: " + e.getMessage());
 *      return;
 *    }
 * 
* *

*

* @author Daniel F. Savarese ***/ public final class WhoisClient extends FingerClient { /*** * The default whois host to query. It is set to whois.internic.net. ***/ public static final String DEFAULT_HOST = "whois.internic.net"; /*** * The default whois port. It is set to 43 according to RFC 954. ***/ public static final int DEFAULT_PORT = 43; /*** * The default whois constructor. Initializes the * default port to DEFAULT_PORT . ***/ public WhoisClient() { setDefaultPort(DEFAULT_PORT); } /*** * Queries the connected whois server for information regarding * the given handle. It is up to the programmer to be familiar with the * handle syntax of the whois server. You must first connect to a whois * server before calling this method, and you should disconnect afterward. *

* @param handle The handle to lookup. * @return The result of the whois query. * @exception IOException If an I/O error occurs during the operation. ***/ public String query(String handle) throws IOException { return query(false, handle); } /*** * Queries the connected whois server for information regarding * the given handle and returns the InputStream of the network connection. * It is up to the programmer to be familiar with the handle syntax * of the whois server. You must first connect to a finger server before * calling this method, and you should disconnect after finishing reading * the stream. *

* @param handle The handle to lookup. * @return The InputStream of the network connection of the whois query. * Can be read to obtain whois results. * @exception IOException If an I/O error occurs during the operation. ***/ public InputStream getInputStream(String handle) throws IOException { return getInputStream(false, handle); } } commons-net-2.2/src/main/java/org/apache/commons/net/DatagramSocketClient.java0000644000175000017500000002217310542533103027353 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /*** * The DatagramSocketClient provides the basic operations that are required * of client objects accessing datagram sockets. It is meant to be * subclassed to avoid having to rewrite the same code over and over again * to open a socket, close a socket, set timeouts, etc. Of special note * is the {@link #setDatagramSocketFactory setDatagramSocketFactory } * method, which allows you to control the type of DatagramSocket the * DatagramSocketClient creates for network communications. This is * especially useful for adding things like proxy support as well as better * support for applets. For * example, you could create a * {@link org.apache.commons.net.DatagramSocketFactory} * that * requests browser security capabilities before creating a socket. * All classes derived from DatagramSocketClient should use the * {@link #_socketFactory_ _socketFactory_ } member variable to * create DatagramSocket instances rather than instantiating * them by directly invoking a constructor. By honoring this contract * you guarantee that a user will always be able to provide his own * Socket implementations by substituting his own SocketFactory. *

*

* @author Daniel F. Savarese * @see DatagramSocketFactory ***/ public abstract class DatagramSocketClient { /*** * The default DatagramSocketFactory shared by all DatagramSocketClient * instances. ***/ private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY = new DefaultDatagramSocketFactory(); /*** The timeout to use after opening a socket. ***/ protected int _timeout_; /*** The datagram socket used for the connection. ***/ protected DatagramSocket _socket_; /*** * A status variable indicating if the client's socket is currently open. ***/ protected boolean _isOpen_; /*** The datagram socket's DatagramSocketFactory. ***/ protected DatagramSocketFactory _socketFactory_; /*** * Default constructor for DatagramSocketClient. Initializes * _socket_ to null, _timeout_ to 0, and _isOpen_ to false. ***/ public DatagramSocketClient() { _socket_ = null; _timeout_ = 0; _isOpen_ = false; _socketFactory_ = __DEFAULT_SOCKET_FACTORY; } /*** * Opens a DatagramSocket on the local host at the first available port. * Also sets the timeout on the socket to the default timeout set * by {@link #setDefaultTimeout setDefaultTimeout() }. *

* _isOpen_ is set to true after calling this method and _socket_ * is set to the newly opened socket. *

* @exception SocketException If the socket could not be opened or the * timeout could not be set. ***/ public void open() throws SocketException { _socket_ = _socketFactory_.createDatagramSocket(); _socket_.setSoTimeout(_timeout_); _isOpen_ = true; } /*** * Opens a DatagramSocket on the local host at a specified port. * Also sets the timeout on the socket to the default timeout set * by {@link #setDefaultTimeout setDefaultTimeout() }. *

* _isOpen_ is set to true after calling this method and _socket_ * is set to the newly opened socket. *

* @param port The port to use for the socket. * @exception SocketException If the socket could not be opened or the * timeout could not be set. ***/ public void open(int port) throws SocketException { _socket_ = _socketFactory_.createDatagramSocket(port); _socket_.setSoTimeout(_timeout_); _isOpen_ = true; } /*** * Opens a DatagramSocket at the specified address on the local host * at a specified port. * Also sets the timeout on the socket to the default timeout set * by {@link #setDefaultTimeout setDefaultTimeout() }. *

* _isOpen_ is set to true after calling this method and _socket_ * is set to the newly opened socket. *

* @param port The port to use for the socket. * @param laddr The local address to use. * @exception SocketException If the socket could not be opened or the * timeout could not be set. ***/ public void open(int port, InetAddress laddr) throws SocketException { _socket_ = _socketFactory_.createDatagramSocket(port, laddr); _socket_.setSoTimeout(_timeout_); _isOpen_ = true; } /*** * Closes the DatagramSocket used for the connection. * You should call this method after you've finished using the class * instance and also before you call {@link #open open() } * again. _isOpen_ is set to false and _socket_ is set to null. * If you call this method when the client socket is not open, * a NullPointerException is thrown. ***/ public void close() { _socket_.close(); _socket_ = null; _isOpen_ = false; } /*** * Returns true if the client has a currently open socket. *

* @return True if the client has a curerntly open socket, false otherwise. ***/ public boolean isOpen() { return _isOpen_; } /*** * Set the default timeout in milliseconds to use when opening a socket. * After a call to open, the timeout for the socket is set using this value. * This method should be used prior to a call to {@link #open open()} * and should not be confused with {@link #setSoTimeout setSoTimeout()} * which operates on the currently open socket. _timeout_ contains * the new timeout value. *

* @param timeout The timeout in milliseconds to use for the datagram socket * connection. ***/ public void setDefaultTimeout(int timeout) { _timeout_ = timeout; } /*** * Returns the default timeout in milliseconds that is used when * opening a socket. *

* @return The default timeout in milliseconds that is used when * opening a socket. ***/ public int getDefaultTimeout() { return _timeout_; } /*** * Set the timeout in milliseconds of a currently open connection. * Only call this method after a connection has been opened * by {@link #open open()}. *

* @param timeout The timeout in milliseconds to use for the currently * open datagram socket connection. ***/ public void setSoTimeout(int timeout) throws SocketException { _socket_.setSoTimeout(timeout); } /*** * Returns the timeout in milliseconds of the currently opened socket. * If you call this method when the client socket is not open, * a NullPointerException is thrown. *

* @return The timeout in milliseconds of the currently opened socket. ***/ public int getSoTimeout() throws SocketException { return _socket_.getSoTimeout(); } /*** * Returns the port number of the open socket on the local host used * for the connection. If you call this method when the client socket * is not open, a NullPointerException is thrown. *

* @return The port number of the open socket on the local host used * for the connection. ***/ public int getLocalPort() { return _socket_.getLocalPort(); } /*** * Returns the local address to which the client's socket is bound. * If you call this method when the client socket is not open, a * NullPointerException is thrown. *

* @return The local address to which the client's socket is bound. ***/ public InetAddress getLocalAddress() { return _socket_.getLocalAddress(); } /*** * Sets the DatagramSocketFactory used by the DatagramSocketClient * to open DatagramSockets. If the factory value is null, then a default * factory is used (only do this to reset the factory after having * previously altered it). *

* @param factory The new DatagramSocketFactory the DatagramSocketClient * should use. ***/ public void setDatagramSocketFactory(DatagramSocketFactory factory) { if (factory == null) _socketFactory_ = __DEFAULT_SOCKET_FACTORY; else _socketFactory_ = factory; } } commons-net-2.2/src/main/java/org/apache/commons/net/io/0000755000175000017500000000000011617452467023103 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/io/Util.java0000644000175000017500000003353010542533103024646 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; /*** * The Util class cannot be instantiated and stores short static convenience * methods that are often quite useful. *

*

* @see CopyStreamException * @see CopyStreamListener * @see CopyStreamAdapter * @author Daniel F. Savarese ***/ public final class Util { /*** * The default buffer size used by {@link #copyStream copyStream } * and {@link #copyReader copyReader }. It's value is 1024. ***/ public static final int DEFAULT_COPY_BUFFER_SIZE = 1024; // Cannot be instantiated private Util() { } /*** * Copies the contents of an InputStream to an OutputStream using a * copy buffer of a given size and notifies the provided * CopyStreamListener of the progress of the copy operation by calling * its bytesTransferred(long, int) method after each write to the * destination. If you wish to notify more than one listener you should * use a CopyStreamAdapter as the listener and register the additional * listeners with the CopyStreamAdapter. *

* The contents of the InputStream are * read until the end of the stream is reached, but neither the * source nor the destination are closed. You must do this yourself * outside of the method call. The number of bytes read/written is * returned. *

* @param source The source InputStream. * @param dest The destination OutputStream. * @param bufferSize The number of bytes to buffer during the copy. * @param streamSize The number of bytes in the stream being copied. * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. * @param listener The CopyStreamListener to notify of progress. If * this parameter is null, notification is not attempted. * @param flush Whether to flush the output stream after every * write. This is necessary for interactive sessions that rely on * buffered streams. If you don't flush, the data will stay in * the stream buffer. * @exception CopyStreamException If an error occurs while reading from the * source or writing to the destination. The CopyStreamException * will contain the number of bytes confirmed to have been * transferred before an * IOException occurred, and it will also contain the IOException * that caused the error. These values can be retrieved with * the CopyStreamException getTotalBytesTransferred() and * getIOException() methods. ***/ public static final long copyStream(InputStream source, OutputStream dest, int bufferSize, long streamSize, CopyStreamListener listener, boolean flush) throws CopyStreamException { int bytes; long total; byte[] buffer; buffer = new byte[bufferSize]; total = 0; try { while ((bytes = source.read(buffer)) != -1) { // Technically, some read(byte[]) methods may return 0 and we cannot // accept that as an indication of EOF. if (bytes == 0) { bytes = source.read(); if (bytes < 0) break; dest.write(bytes); if(flush) dest.flush(); ++total; if (listener != null) listener.bytesTransferred(total, 1, streamSize); continue; } dest.write(buffer, 0, bytes); if(flush) dest.flush(); total += bytes; if (listener != null) listener.bytesTransferred(total, bytes, streamSize); } } catch (IOException e) { throw new CopyStreamException("IOException caught while copying.", total, e); } return total; } /*** * Copies the contents of an InputStream to an OutputStream using a * copy buffer of a given size and notifies the provided * CopyStreamListener of the progress of the copy operation by calling * its bytesTransferred(long, int) method after each write to the * destination. If you wish to notify more than one listener you should * use a CopyStreamAdapter as the listener and register the additional * listeners with the CopyStreamAdapter. *

* The contents of the InputStream are * read until the end of the stream is reached, but neither the * source nor the destination are closed. You must do this yourself * outside of the method call. The number of bytes read/written is * returned. *

* @param source The source InputStream. * @param dest The destination OutputStream. * @param bufferSize The number of bytes to buffer during the copy. * @param streamSize The number of bytes in the stream being copied. * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. * @param listener The CopyStreamListener to notify of progress. If * this parameter is null, notification is not attempted. * @exception CopyStreamException If an error occurs while reading from the * source or writing to the destination. The CopyStreamException * will contain the number of bytes confirmed to have been * transferred before an * IOException occurred, and it will also contain the IOException * that caused the error. These values can be retrieved with * the CopyStreamException getTotalBytesTransferred() and * getIOException() methods. ***/ public static final long copyStream(InputStream source, OutputStream dest, int bufferSize, long streamSize, CopyStreamListener listener) throws CopyStreamException { return copyStream(source, dest, bufferSize, streamSize, listener, true); } /*** * Copies the contents of an InputStream to an OutputStream using a * copy buffer of a given size. The contents of the InputStream are * read until the end of the stream is reached, but neither the * source nor the destination are closed. You must do this yourself * outside of the method call. The number of bytes read/written is * returned. *

* @param source The source InputStream. * @param dest The destination OutputStream. * @return The number of bytes read/written in the copy operation. * @exception CopyStreamException If an error occurs while reading from the * source or writing to the destination. The CopyStreamException * will contain the number of bytes confirmed to have been * transferred before an * IOException occurred, and it will also contain the IOException * that caused the error. These values can be retrieved with * the CopyStreamException getTotalBytesTransferred() and * getIOException() methods. ***/ public static final long copyStream(InputStream source, OutputStream dest, int bufferSize) throws CopyStreamException { return copyStream(source, dest, bufferSize, CopyStreamEvent.UNKNOWN_STREAM_SIZE, null); } /*** * Same as copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); ***/ public static final long copyStream(InputStream source, OutputStream dest) throws CopyStreamException { return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); } /*** * Copies the contents of a Reader to a Writer using a * copy buffer of a given size and notifies the provided * CopyStreamListener of the progress of the copy operation by calling * its bytesTransferred(long, int) method after each write to the * destination. If you wish to notify more than one listener you should * use a CopyStreamAdapter as the listener and register the additional * listeners with the CopyStreamAdapter. *

* The contents of the Reader are * read until its end is reached, but neither the source nor the * destination are closed. You must do this yourself outside of the * method call. The number of characters read/written is returned. *

* @param source The source Reader. * @param dest The destination writer. * @param bufferSize The number of characters to buffer during the copy. * @param streamSize The number of characters in the stream being copied. * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. * @param listener The CopyStreamListener to notify of progress. If * this parameter is null, notification is not attempted. * @return The number of characters read/written in the copy operation. * @exception CopyStreamException If an error occurs while reading from the * source or writing to the destination. The CopyStreamException * will contain the number of bytes confirmed to have been * transferred before an * IOException occurred, and it will also contain the IOException * that caused the error. These values can be retrieved with * the CopyStreamException getTotalBytesTransferred() and * getIOException() methods. ***/ public static final long copyReader(Reader source, Writer dest, int bufferSize, long streamSize, CopyStreamListener listener) throws CopyStreamException { int chars; long total; char[] buffer; buffer = new char[bufferSize]; total = 0; try { while ((chars = source.read(buffer)) != -1) { // Technically, some read(char[]) methods may return 0 and we cannot // accept that as an indication of EOF. if (chars == 0) { chars = source.read(); if (chars < 0) break; dest.write(chars); dest.flush(); ++total; if (listener != null) listener.bytesTransferred(total, chars, streamSize); continue; } dest.write(buffer, 0, chars); dest.flush(); total += chars; if (listener != null) listener.bytesTransferred(total, chars, streamSize); } } catch (IOException e) { throw new CopyStreamException("IOException caught while copying.", total, e); } return total; } /*** * Copies the contents of a Reader to a Writer using a * copy buffer of a given size. The contents of the Reader are * read until its end is reached, but neither the source nor the * destination are closed. You must do this yourself outside of the * method call. The number of characters read/written is returned. *

* @param source The source Reader. * @param dest The destination writer. * @param bufferSize The number of characters to buffer during the copy. * @return The number of characters read/written in the copy operation. * @exception CopyStreamException If an error occurs while reading from the * source or writing to the destination. The CopyStreamException * will contain the number of bytes confirmed to have been * transferred before an * IOException occurred, and it will also contain the IOException * that caused the error. These values can be retrieved with * the CopyStreamException getTotalBytesTransferred() and * getIOException() methods. ***/ public static final long copyReader(Reader source, Writer dest, int bufferSize) throws CopyStreamException { return copyReader(source, dest, bufferSize, CopyStreamEvent.UNKNOWN_STREAM_SIZE, null); } /*** * Same as copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); ***/ public static final long copyReader(Reader source, Writer dest) throws CopyStreamException { return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); } } commons-net-2.2/src/main/java/org/apache/commons/net/io/CopyStreamAdapter.java0000644000175000017500000001134011354710167027324 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.util.EventListener; import org.apache.commons.net.util.ListenerList; /** * The CopyStreamAdapter will relay CopyStreamEvents to a list of listeners * when either of its bytesTransferred() methods are called. Its purpose * is to facilitate the notification of the progress of a copy operation * performed by one of the static copyStream() methods in * org.apache.commons.io.Util to multiple listeners. The static * copyStream() methods invoke the * bytesTransfered(long, int) of a CopyStreamListener for performance * reasons and also because multiple listeners cannot be registered given * that the methods are static. *

*

* @see CopyStreamEvent * @see CopyStreamListener * @see Util * @author Daniel F. Savarese * @version $Id: CopyStreamAdapter.java 929649 2010-03-31 18:12:07Z sebb $ */ public class CopyStreamAdapter implements CopyStreamListener { private final ListenerList internalListeners; /** * Creates a new copyStreamAdapter. */ public CopyStreamAdapter() { internalListeners = new ListenerList(); } /** * This method is invoked by a CopyStreamEvent source after copying * a block of bytes from a stream. The CopyStreamEvent will contain * the total number of bytes transferred so far and the number of bytes * transferred in the last write. The CopyStreamAdapater will relay * the event to all of its registered listeners, listing itself as the * source of the event. * @param event The CopyStreamEvent fired by the copying of a block of * bytes. */ public void bytesTransferred(CopyStreamEvent event) { bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize()); } /** * This method is not part of the JavaBeans model and is used by the * static methods in the org.apache.commons.io.Util class for efficiency. * It is invoked after a block of bytes to inform the listener of the * transfer. The CopyStreamAdapater will create a CopyStreamEvent * from the arguments and relay the event to all of its registered * listeners, listing itself as the source of the event. * @param totalBytesTransferred The total number of bytes transferred * so far by the copy operation. * @param bytesTransferred The number of bytes copied by the most recent * write. * @param streamSize The number of bytes in the stream being copied. * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if * the size is unknown. */ public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) { CopyStreamEvent event; event = new CopyStreamEvent(this, totalBytesTransferred, bytesTransferred, streamSize); for (EventListener listener : internalListeners) { ((CopyStreamListener) (listener)).bytesTransferred(event); } } /** * Registers a CopyStreamListener to receive CopyStreamEvents. * Although this method is not declared to be synchronized, it is * implemented in a thread safe manner. * @param listener The CopyStreamlistener to register. */ public void addCopyStreamListener(CopyStreamListener listener) { internalListeners.addListener(listener); } /** * Unregisters a CopyStreamListener. Although this method is not * synchronized, it is implemented in a thread safe manner. * @param listener The CopyStreamlistener to unregister. */ public void removeCopyStreamListener(CopyStreamListener listener) { internalListeners.removeListener(listener); } } commons-net-2.2/src/main/java/org/apache/commons/net/io/CopyStreamEvent.java0000644000175000017500000000647511354710167027042 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.util.EventObject; /** * A CopyStreamEvent is triggered after every write performed by a * stream copying operation. The event stores the number of bytes * transferred by the write triggering the event as well as the total * number of bytes transferred so far by the copy operation. *

*

* @see CopyStreamListener * @see CopyStreamAdapter * @see Util * @author Daniel F. Savarese * @version $Id: CopyStreamEvent.java 929649 2010-03-31 18:12:07Z sebb $ */ public class CopyStreamEvent extends EventObject { /** * Constant used to indicate the stream size is unknown. */ public static final long UNKNOWN_STREAM_SIZE = -1; private final int bytesTransferred; private final long totalBytesTransferred; private final long streamSize; /** * Creates a new CopyStreamEvent instance. * @param source The source of the event. * @param totalBytesTransferred The total number of bytes transferred so * far during a copy operation. * @param bytesTransferred The number of bytes transferred during the * write that triggered the CopyStreamEvent. * @param streamSize The number of bytes in the stream being copied. * This may be set to UNKNOWN_STREAM_SIZE if the * size is unknown. */ public CopyStreamEvent(Object source, long totalBytesTransferred, int bytesTransferred, long streamSize) { super(source); this.bytesTransferred = bytesTransferred; this.totalBytesTransferred = totalBytesTransferred; this.streamSize = streamSize; } /** * Returns the number of bytes transferred by the write that triggered * the event. * @return The number of bytes transferred by the write that triggered * the vent. */ public int getBytesTransferred() { return bytesTransferred; } /** * Returns the total number of bytes transferred so far by the copy * operation. * @return The total number of bytes transferred so far by the copy * operation. */ public long getTotalBytesTransferred() { return totalBytesTransferred; } /** * Returns the size of the stream being copied. * This may be set to UNKNOWN_STREAM_SIZE if the * size is unknown. * @return The size of the stream being copied. */ public long getStreamSize() { return streamSize; } } commons-net-2.2/src/main/java/org/apache/commons/net/io/DotTerminatedMessageWriter.java0000644000175000017500000001505111330134214031170 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.IOException; import java.io.Writer; /*** * DotTerminatedMessageWriter is a class used to write messages to a * server that are terminated by a single dot followed by a * <CR><LF> * sequence and with double dots appearing at the begining of lines which * do not signal end of message yet start with a dot. Various Internet * protocols such as NNTP and POP3 produce messages of this type. *

* This class handles the doubling of line-starting periods, * converts single linefeeds to NETASCII newlines, and on closing * will send the final message terminator dot and NETASCII newline * sequence. *

*

* @author Daniel F. Savarese ***/ public final class DotTerminatedMessageWriter extends Writer { private static final int __NOTHING_SPECIAL_STATE = 0; private static final int __LAST_WAS_CR_STATE = 1; private static final int __LAST_WAS_NL_STATE = 2; private int __state; private Writer __output; /*** * Creates a DotTerminatedMessageWriter that wraps an existing Writer * output destination. *

* @param output The Writer output destination to write the message. ***/ public DotTerminatedMessageWriter(Writer output) { super(output); __output = output; __state = __NOTHING_SPECIAL_STATE; } /*** * Writes a character to the output. Note that a call to this method * may result in multiple writes to the underling Writer in order to * convert naked linefeeds to NETASCII line separators and to double * line-leading periods. This is transparent to the programmer and * is only mentioned for completeness. *

* @param ch The character to write. * @exception IOException If an error occurs while writing to the * underlying output. ***/ @Override public void write(int ch) throws IOException { synchronized (lock) { switch (ch) { case '\r': __state = __LAST_WAS_CR_STATE; __output.write('\r'); return ; case '\n': if (__state != __LAST_WAS_CR_STATE) __output.write('\r'); __output.write('\n'); __state = __LAST_WAS_NL_STATE; return ; case '.': // Double the dot at the beginning of a line if (__state == __LAST_WAS_NL_STATE) __output.write('.'); //$FALL-THROUGH$ default: __state = __NOTHING_SPECIAL_STATE; __output.write(ch); return ; } } } /*** * Writes a number of characters from a character array to the output * starting from a given offset. *

* @param buffer The character array to write. * @param offset The offset into the array at which to start copying data. * @param length The number of characters to write. * @exception IOException If an error occurs while writing to the underlying * output. ***/ @Override public void write(char[] buffer, int offset, int length) throws IOException { synchronized (lock) { while (length-- > 0) write(buffer[offset++]); } } /*** * Writes a character array to the output. *

* @param buffer The character array to write. * @exception IOException If an error occurs while writing to the underlying * output. ***/ @Override public void write(char[] buffer) throws IOException { write(buffer, 0, buffer.length); } /*** * Writes a String to the output. *

* @param string The String to write. * @exception IOException If an error occurs while writing to the underlying * output. ***/ @Override public void write(String string) throws IOException { write(string.toCharArray()); } /*** * Writes part of a String to the output starting from a given offset. *

* @param string The String to write. * @param offset The offset into the String at which to start copying data. * @param length The number of characters to write. * @exception IOException If an error occurs while writing to the underlying * output. ***/ @Override public void write(String string, int offset, int length) throws IOException { write(string.toCharArray(), offset, length); } /*** * Flushes the underlying output, writing all buffered output. *

* @exception IOException If an error occurs while writing to the underlying * output. ***/ @Override public void flush() throws IOException { synchronized (lock) { __output.flush(); } } /*** * Flushes the underlying output, writing all buffered output, but doesn't * actually close the underlying stream. The underlying stream may still * be used for communicating with the server and therefore is not closed. *

* @exception IOException If an error occurs while writing to the underlying * output or closing the Writer. ***/ @Override public void close() throws IOException { synchronized (lock) { if (__output == null) return ; if (__state == __LAST_WAS_CR_STATE) __output.write('\n'); else if (__state != __LAST_WAS_NL_STATE) __output.write("\r\n"); __output.write(".\r\n"); __output.flush(); __output = null; } } } commons-net-2.2/src/main/java/org/apache/commons/net/io/ToNetASCIIOutputStream.java0000644000175000017500000000704111330134214030122 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; /*** * This class wraps an output stream, replacing all singly occurring * <LF> (linefeed) characters with <CR><LF> (carriage return * followed by linefeed), which is the NETASCII standard for representing * a newline. * You would use this class to implement ASCII file transfers requiring * conversion to NETASCII. *

*

* @author Daniel F. Savarese ***/ public final class ToNetASCIIOutputStream extends FilterOutputStream { private boolean __lastWasCR; /*** * Creates a ToNetASCIIOutputStream instance that wraps an existing * OutputStream. *

* @param output The OutputStream to wrap. ***/ public ToNetASCIIOutputStream(OutputStream output) { super(output); __lastWasCR = false; } /*** * Writes a byte to the stream. Note that a call to this method * may result in multiple writes to the underlying input stream in order * to convert naked newlines to NETASCII line separators. * This is transparent to the programmer and is only mentioned for * completeness. *

* @param ch The byte to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public synchronized void write(int ch) throws IOException { switch (ch) { case '\r': __lastWasCR = true; out.write('\r'); return ; case '\n': if (!__lastWasCR) out.write('\r'); //$FALL-THROUGH$ default: __lastWasCR = false; out.write(ch); return ; } } /*** * Writes a byte array to the stream. *

* @param buffer The byte array to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public synchronized void write(byte buffer[]) throws IOException { write(buffer, 0, buffer.length); } /*** * Writes a number of bytes from a byte array to the stream starting from * a given offset. *

* @param buffer The byte array to write. * @param offset The offset into the array at which to start copying data. * @param length The number of bytes to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public synchronized void write(byte buffer[], int offset, int length) throws IOException { while (length-- > 0) write(buffer[offset++]); } } commons-net-2.2/src/main/java/org/apache/commons/net/io/CopyStreamListener.java0000644000175000017500000000625510542533103027531 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.util.EventListener; /** * The CopyStreamListener class can accept CopyStreamEvents to keep track * of the progress of a stream copying operation. However, it is currently * not used that way within NetComponents for performance reasons. Rather * the bytesTransferred(long, int) method is called directly rather than * passing an event to bytesTransferred(CopyStreamEvent), saving the creation * of a CopyStreamEvent instance. Also, the only place where * CopyStreamListener is currently used within NetComponents is in the * static methods of the uninstantiable org.apache.commons.io.Util class, which * would preclude the use of addCopyStreamListener and * removeCopyStreamListener methods. However, future additions may use the * JavaBean event model, which is why the hooks have been included from the * beginning. *

*

* @see CopyStreamEvent * @see CopyStreamAdapter * @see Util * @author Daniel F. Savarese * @version $Id: CopyStreamListener.java 489397 2006-12-21 16:28:51Z rwinston $ */ public interface CopyStreamListener extends EventListener { /** * This method is invoked by a CopyStreamEvent source after copying * a block of bytes from a stream. The CopyStreamEvent will contain * the total number of bytes transferred so far and the number of bytes * transferred in the last write. * @param event The CopyStreamEvent fired by the copying of a block of * bytes. */ public void bytesTransferred(CopyStreamEvent event); /** * This method is not part of the JavaBeans model and is used by the * static methods in the org.apache.commons.io.Util class for efficiency. * It is invoked after a block of bytes to inform the listener of the * transfer. * @param totalBytesTransferred The total number of bytes transferred * so far by the copy operation. * @param bytesTransferred The number of bytes copied by the most recent * write. * @param streamSize The number of bytes in the stream being copied. * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if * the size is unknown. */ public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize); } commons-net-2.2/src/main/java/org/apache/commons/net/io/SocketInputStream.java0000644000175000017500000000437411354710167027372 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; /*** * This class wraps an input stream, storing a reference to its originating * socket. When the stream is closed, it will also close the socket * immediately afterward. This class is useful for situations where you * are dealing with a stream originating from a socket, but do not have * a reference to the socket, and want to make sure it closes when the * stream closes. *

*

* @author Daniel F. Savarese * @see SocketOutputStream ***/ public class SocketInputStream extends FilterInputStream { private final Socket __socket; /*** * Creates a SocketInputStream instance wrapping an input stream and * storing a reference to a socket that should be closed on closing * the stream. *

* @param socket The socket to close on closing the stream. * @param stream The input stream to wrap. ***/ public SocketInputStream(Socket socket, InputStream stream) { super(stream); __socket = socket; } /*** * Closes the stream and immediately afterward closes the referenced * socket. *

* @exception IOException If there is an error in closing the stream * or socket. ***/ @Override public void close() throws IOException { super.close(); __socket.close(); } } commons-net-2.2/src/main/java/org/apache/commons/net/io/FromNetASCIIOutputStream.java0000644000175000017500000001205310766271714030465 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; /*** * This class wraps an output stream, replacing all occurrences * of <CR><LF> (carriage return followed by a linefeed), * which is the NETASCII standard for representing a newline, with the * local line separator representation. You would use this class to * implement ASCII file transfers requiring conversion from NETASCII. *

* Because of the translation process, a call to flush() will * not flush the last byte written if that byte was a carriage * return. A call to {@link #close close() }, however, will * flush the carriage return. *

*

* @author Daniel F. Savarese ***/ public final class FromNetASCIIOutputStream extends FilterOutputStream { private boolean __lastWasCR; /*** * Creates a FromNetASCIIOutputStream instance that wraps an existing * OutputStream. *

* @param output The OutputStream to wrap. ***/ public FromNetASCIIOutputStream(OutputStream output) { super(output); __lastWasCR = false; } private void __write(int ch) throws IOException { switch (ch) { case '\r': __lastWasCR = true; // Don't write anything. We need to see if next one is linefeed break; case '\n': if (__lastWasCR) { out.write(FromNetASCIIInputStream._lineSeparatorBytes); __lastWasCR = false; break; } __lastWasCR = false; out.write('\n'); break; default: if (__lastWasCR) { out.write('\r'); __lastWasCR = false; } out.write(ch); break; } } /*** * Writes a byte to the stream. Note that a call to this method * might not actually write a byte to the underlying stream until a * subsequent character is written, from which it can be determined if * a NETASCII line separator was encountered. * This is transparent to the programmer and is only mentioned for * completeness. *

* @param ch The byte to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public synchronized void write(int ch) throws IOException { if (FromNetASCIIInputStream._noConversionRequired) { out.write(ch); return ; } __write(ch); } /*** * Writes a byte array to the stream. *

* @param buffer The byte array to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public synchronized void write(byte buffer[]) throws IOException { write(buffer, 0, buffer.length); } /*** * Writes a number of bytes from a byte array to the stream starting from * a given offset. *

* @param buffer The byte array to write. * @param offset The offset into the array at which to start copying data. * @param length The number of bytes to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public synchronized void write(byte buffer[], int offset, int length) throws IOException { if (FromNetASCIIInputStream._noConversionRequired) { // FilterOutputStream method is very slow. //super.write(buffer, offset, length); out.write(buffer, offset, length); return ; } while (length-- > 0) __write(buffer[offset++]); } /*** * Closes the stream, writing all pending data. *

* @exception IOException If an error occurs while closing the stream. ***/ @Override public synchronized void close() throws IOException { if (FromNetASCIIInputStream._noConversionRequired) { super.close(); return ; } if (__lastWasCR) out.write('\r'); super.close(); } } commons-net-2.2/src/main/java/org/apache/commons/net/io/ToNetASCIIInputStream.java0000644000175000017500000001214311330134214027720 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /*** * This class wraps an input stream, replacing all singly occurring * <LF> (linefeed) characters with <CR><LF> (carriage return * followed by linefeed), which is the NETASCII standard for representing * a newline. * You would use this class to implement ASCII file transfers requiring * conversion to NETASCII. *

*

* @author Daniel F. Savarese ***/ public final class ToNetASCIIInputStream extends FilterInputStream { private static final int __NOTHING_SPECIAL = 0; private static final int __LAST_WAS_CR = 1; private static final int __LAST_WAS_NL = 2; private int __status; /*** * Creates a ToNetASCIIInputStream instance that wraps an existing * InputStream. *

* @param input The InputStream to . ***/ public ToNetASCIIInputStream(InputStream input) { super(input); __status = __NOTHING_SPECIAL; } /*** * Reads and returns the next byte in the stream. If the end of the * message has been reached, returns -1. *

* @return The next character in the stream. Returns -1 if the end of the * stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read() throws IOException { int ch; if (__status == __LAST_WAS_NL) { __status = __NOTHING_SPECIAL; return '\n'; } ch = in.read(); switch (ch) { case '\r': __status = __LAST_WAS_CR; return '\r'; case '\n': if (__status != __LAST_WAS_CR) { __status = __LAST_WAS_NL; return '\r'; } //$FALL-THROUGH$ default: __status = __NOTHING_SPECIAL; return ch; } // statement not reached //return ch; } /*** * Reads the next number of bytes from the stream into an array and * returns the number of bytes read. Returns -1 if the end of the * stream has been reached. *

* @param buffer The byte array in which to store the data. * @return The number of bytes read. Returns -1 if the * end of the message has been reached. * @exception IOException If an error occurs in reading the underlying * stream. ***/ @Override public int read(byte buffer[]) throws IOException { return read(buffer, 0, buffer.length); } /*** * Reads the next number of bytes from the stream into an array and returns * the number of bytes read. Returns -1 if the end of the * message has been reached. The characters are stored in the array * starting from the given offset and up to the length specified. *

* @param buffer The byte array in which to store the data. * @param offset The offset into the array at which to start storing data. * @param length The number of bytes to read. * @return The number of bytes read. Returns -1 if the * end of the stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read(byte buffer[], int offset, int length) throws IOException { int ch, off; if (length < 1) return 0; ch = available(); if (length > ch) length = ch; // If nothing is available, block to read only one character if (length < 1) length = 1; if ((ch = read()) == -1) return -1; off = offset; do { buffer[offset++] = (byte)ch; } while (--length > 0 && (ch = read()) != -1); return (offset - off); } /*** Returns false. Mark is not supported. ***/ @Override public boolean markSupported() { return false; } @Override public int available() throws IOException { int result; result = in.available(); if (__status == __LAST_WAS_NL) return (result + 1); return result; } } commons-net-2.2/src/main/java/org/apache/commons/net/io/CopyStreamException.java0000644000175000017500000000513111354710167027703 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.IOException; /** * The CopyStreamException class is thrown by the org.apache.commons.io.Util * copyStream() methods. It stores the number of bytes confirmed to * have been transferred before an I/O error as well as the IOException * responsible for the failure of a copy operation. * @see Util * @author Daniel F. Savarese * @version $Id: CopyStreamException.java 929649 2010-03-31 18:12:07Z sebb $ */ public class CopyStreamException extends IOException { private final long totalBytesTransferred; private final IOException ioException; /** * Creates a new CopyStreamException instance. * @param message A message describing the error. * @param bytesTransferred The total number of bytes transferred before * an exception was thrown in a copy operation. * @param exception The IOException thrown during a copy operation. */ public CopyStreamException(String message, long bytesTransferred, IOException exception) { super(message); totalBytesTransferred = bytesTransferred; ioException = exception; } /** * Returns the total number of bytes confirmed to have * been transferred by a failed copy operation. * @return The total number of bytes confirmed to have * been transferred by a failed copy operation. */ public long getTotalBytesTransferred() { return totalBytesTransferred; } /** * Returns the IOException responsible for the failure of a copy operation. * @return The IOException responsible for the failure of a copy operation. */ public IOException getIOException() { return ioException; } } commons-net-2.2/src/main/java/org/apache/commons/net/io/DotTerminatedMessageReader.java0000644000175000017500000002201011347053246031124 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.IOException; import java.io.PushbackReader; import java.io.Reader; /** * DotTerminatedMessageReader is a class used to read messages from a * server that are terminated by a single dot followed by a * <CR><LF> * sequence and with double dots appearing at the begining of lines which * do not signal end of message yet start with a dot. Various Internet * protocols such as NNTP and POP3 produce messages of this type. *

* This class handles stripping of the duplicate period at the beginning * of lines starting with a period, converts NETASCII newlines to the * local line separator format, truncates the end of message indicator, * and ensures you cannot read past the end of the message. * @author Daniel F. Savarese * @version $Id: DotTerminatedMessageReader.java 922748 2010-03-14 03:23:18Z sebb $ */ public final class DotTerminatedMessageReader extends Reader { private static final String LS = System.getProperty("line.separator"); char[] LS_CHARS; private boolean atBeginning; private boolean eof; private int pos; private char[] internalBuffer; private PushbackReader internalReader; /** * Creates a DotTerminatedMessageReader that wraps an existing Reader * input source. * @param reader The Reader input source containing the message. */ public DotTerminatedMessageReader(Reader reader) { super(reader); LS_CHARS = LS.toCharArray(); internalBuffer = new char[LS_CHARS.length + 3]; pos = internalBuffer.length; // Assumes input is at start of message atBeginning = true; eof = false; internalReader = new PushbackReader(reader); } /** * Reads and returns the next character in the message. If the end of the * message has been reached, returns -1. Note that a call to this method * may result in multiple reads from the underlying input stream to decode * the message properly (removing doubled dots and so on). All of * this is transparent to the programmer and is only mentioned for * completeness. * @return The next character in the message. Returns -1 if the end of the * message has been reached. * @exception IOException If an error occurs while reading the underlying * stream. */ @Override public int read() throws IOException { int ch; synchronized (lock) { if (pos < internalBuffer.length) { return internalBuffer[pos++]; } if (eof) { return -1; } if ((ch = internalReader.read()) == -1) { eof = true; return -1; } if (atBeginning) { atBeginning = false; if (ch == '.') { ch = internalReader.read(); if (ch != '.') { // read newline eof = true; internalReader.read(); return -1; } else { return '.'; } } } if (ch == '\r') { ch = internalReader.read(); if (ch == '\n') { ch = internalReader.read(); if (ch == '.') { ch = internalReader.read(); if (ch != '.') { // read newline and indicate end of file internalReader.read(); eof = true; } else { internalBuffer[--pos] = (char) ch; } } else { internalReader.unread(ch); } pos -= LS_CHARS.length; System.arraycopy(LS_CHARS, 0, internalBuffer, pos, LS_CHARS.length); ch = internalBuffer[pos++]; } else if (ch == '\r') { internalReader.unread(ch); } else { internalBuffer[--pos] = (char) ch; return '\r'; } } return ch; } } /** * Reads the next characters from the message into an array and * returns the number of characters read. Returns -1 if the end of the * message has been reached. * @param buffer The character array in which to store the characters. * @return The number of characters read. Returns -1 if the * end of the message has been reached. * @exception IOException If an error occurs in reading the underlying * stream. */ @Override public int read(char[] buffer) throws IOException { return read(buffer, 0, buffer.length); } /** * Reads the next characters from the message into an array and * returns the number of characters read. Returns -1 if the end of the * message has been reached. The characters are stored in the array * starting from the given offset and up to the length specified. * @param buffer The character array in which to store the characters. * @param offset The offset into the array at which to start storing * characters. * @param length The number of characters to read. * @return The number of characters read. Returns -1 if the * end of the message has been reached. * @exception IOException If an error occurs in reading the underlying * stream. */ @Override public int read(char[] buffer, int offset, int length) throws IOException { int ch, off; synchronized (lock) { if (length < 1) { return 0; } if ((ch = read()) == -1) { return -1; } off = offset; do { buffer[offset++] = (char) ch; } while (--length > 0 && (ch = read()) != -1); return (offset - off); } } /** * Determines if the message is ready to be read. * @return True if the message is ready to be read, false if not. * @exception IOException If an error occurs while checking the underlying * stream. */ @Override public boolean ready() throws IOException { synchronized (lock) { return (pos < internalBuffer.length || internalReader.ready()); } } /** * Closes the message for reading. This doesn't actually close the * underlying stream. The underlying stream may still be used for * communicating with the server and therefore is not closed. *

* If the end of the message has not yet been reached, this method * will read the remainder of the message until it reaches the end, * so that the underlying stream may continue to be used properly * for communicating with the server. If you do not fully read * a message, you MUST close it, otherwise your program will likely * hang or behave improperly. * @exception IOException If an error occurs while reading the * underlying stream. */ @Override public void close() throws IOException { synchronized (lock) { if (internalReader == null) { return; } if (!eof) { while (read() != -1) { // read to EOF } } eof = true; atBeginning = false; pos = internalBuffer.length; internalReader = null; } } } commons-net-2.2/src/main/java/org/apache/commons/net/io/SocketOutputStream.java0000644000175000017500000000572011354710167027567 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /*** * This class wraps an output stream, storing a reference to its originating * socket. When the stream is closed, it will also close the socket * immediately afterward. This class is useful for situations where you * are dealing with a stream originating from a socket, but do not have * a reference to the socket, and want to make sure it closes when the * stream closes. *

*

* @author Daniel F. Savarese * @see SocketInputStream ***/ public class SocketOutputStream extends FilterOutputStream { private final Socket __socket; /*** * Creates a SocketOutputStream instance wrapping an output stream and * storing a reference to a socket that should be closed on closing * the stream. *

* @param socket The socket to close on closing the stream. * @param stream The input stream to wrap. ***/ public SocketOutputStream(Socket socket, OutputStream stream) { super(stream); __socket = socket; } /*** * Writes a number of bytes from a byte array to the stream starting from * a given offset. This method bypasses the equivalent method in * FilterOutputStream because the FilterOutputStream implementation is * very inefficient. *

* @param buffer The byte array to write. * @param offset The offset into the array at which to start copying data. * @param length The number of bytes to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public void write(byte buffer[], int offset, int length) throws IOException { out.write(buffer, offset, length); } /*** * Closes the stream and immediately afterward closes the referenced * socket. *

* @exception IOException If there is an error in closing the stream * or socket. ***/ @Override public void close() throws IOException { super.close(); __socket.close(); } } commons-net-2.2/src/main/java/org/apache/commons/net/io/FromNetASCIIInputStream.java0000644000175000017500000001474111456046441030264 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; /*** * This class wraps an input stream, replacing all occurrences * of <CR><LF> (carriage return followed by a linefeed), * which is the NETASCII standard for representing a newline, with the * local line separator representation. You would use this class to * implement ASCII file transfers requiring conversion from NETASCII. *

*

* @author Daniel F. Savarese ***/ public final class FromNetASCIIInputStream extends PushbackInputStream { static final boolean _noConversionRequired; static final String _lineSeparator; static final byte[] _lineSeparatorBytes; static { _lineSeparator = System.getProperty("line.separator"); _noConversionRequired = _lineSeparator.equals("\r\n"); _lineSeparatorBytes = _lineSeparator.getBytes(); } private int __length = 0; /*** * Returns true if the NetASCII line separator differs from the system * line separator, false if they are the same. This method is useful * to determine whether or not you need to instantiate a * FromNetASCIIInputStream object. *

* @return True if the NETASCII line separator differs from the local * system line separator, false if they are the same. ***/ public static final boolean isConversionRequired() { return !_noConversionRequired; } /*** * Creates a FromNetASCIIInputStream instance that wraps an existing * InputStream. ***/ public FromNetASCIIInputStream(InputStream input) { super(input, _lineSeparatorBytes.length + 1); } private int __read() throws IOException { int ch; ch = super.read(); if (ch == '\r') { ch = super.read(); if (ch == '\n') { unread(_lineSeparatorBytes); ch = super.read(); // This is a kluge for read(byte[], ...) to read the right amount --__length; } else { if (ch != -1) unread(ch); return '\r'; } } return ch; } /*** * Reads and returns the next byte in the stream. If the end of the * message has been reached, returns -1. Note that a call to this method * may result in multiple reads from the underlying input stream in order * to convert NETASCII line separators to the local line separator format. * This is transparent to the programmer and is only mentioned for * completeness. *

* @return The next character in the stream. Returns -1 if the end of the * stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read() throws IOException { if (_noConversionRequired) return super.read(); return __read(); } /*** * Reads the next number of bytes from the stream into an array and * returns the number of bytes read. Returns -1 if the end of the * stream has been reached. *

* @param buffer The byte array in which to store the data. * @return The number of bytes read. Returns -1 if the * end of the message has been reached. * @exception IOException If an error occurs in reading the underlying * stream. ***/ @Override public int read(byte buffer[]) throws IOException { return read(buffer, 0, buffer.length); } /*** * Reads the next number of bytes from the stream into an array and returns * the number of bytes read. Returns -1 if the end of the * message has been reached. The characters are stored in the array * starting from the given offset and up to the length specified. *

* @param buffer The byte array in which to store the data. * @param offset The offset into the array at which to start storing data. * @param length The number of bytes to read. * @return The number of bytes read. Returns -1 if the * end of the stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read(byte buffer[], int offset, int length) throws IOException { if (_noConversionRequired) return super.read(buffer, offset, length); if (length < 1) return 0; int ch, off; ch = available(); __length = (length > ch ? ch : length); // If nothing is available, block to read only one character if (__length < 1) __length = 1; if ((ch = __read()) == -1) return -1; off = offset; do { buffer[offset++] = (byte)ch; } while (--__length > 0 && (ch = __read()) != -1); return (offset - off); } // PushbackInputStream in JDK 1.1.3 returns the wrong thing // TODO - can we delete this override now? /*** * Returns the number of bytes that can be read without blocking EXCEPT * when newline conversions have to be made somewhere within the * available block of bytes. In other words, you really should not * rely on the value returned by this method if you are trying to avoid * blocking. ***/ @Override public int available() throws IOException { if (in == null) { throw new IOException("Stream closed"); } return (buf.length - pos) + in.available(); } } commons-net-2.2/src/main/java/org/apache/commons/net/ProtocolCommandListener.java0000644000175000017500000000425710542533103030134 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.util.EventListener; /*** * There exists a large class of IETF protocols that work by sending an * ASCII text command and arguments to a server, and then receiving an * ASCII text reply. For debugging and other purposes, it is extremely * useful to log or keep track of the contents of the protocol messages. * The ProtocolCommandListener interface coupled with the * {@link ProtocolCommandEvent} class facilitate this process. *

* To receive ProtocolCommandEvents, you merely implement the * ProtocolCommandListener interface and register the class as a listener * with a ProtocolCommandEvent source such as * {@link org.apache.commons.net.ftp.FTPClient}. *

*

* @see ProtocolCommandEvent * @see ProtocolCommandSupport * @author Daniel F. Savarese ***/ public interface ProtocolCommandListener extends EventListener { /*** * This method is invoked by a ProtocolCommandEvent source after * sending a protocol command to a server. *

* @param event The ProtocolCommandEvent fired. ***/ public void protocolCommandSent(ProtocolCommandEvent event); /*** * This method is invoked by a ProtocolCommandEvent source after * receiving a reply from a server. *

* @param event The ProtocolCommandEvent fired. ***/ public void protocolReplyReceived(ProtocolCommandEvent event); } commons-net-2.2/src/main/java/org/apache/commons/net/finger/0000755000175000017500000000000011617452467023746 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/finger/FingerClient.java0000644000175000017500000001602711416066007027154 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.finger; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import org.apache.commons.net.SocketClient; /*** * The FingerClient class implements the client side of the Internet Finger * Protocol defined in RFC 1288. To finger a host you create a * FingerClient instance, connect to the host, query the host, and finally * disconnect from the host. If the finger service you want to query is on * a non-standard port, connect to the host at that port. * Here's a sample use: *

 *    FingerClient finger;
 *
 *    finger = new FingerClient();
 *
 *    try {
 *      finger.connect("foo.bar.com");
 *      System.out.println(finger.query("foobar", false));
 *      finger.disconnect();
 *    } catch(IOException e) {
 *      System.err.println("Error I/O exception: " + e.getMessage());
 *      return;
 *    }
 * 
*

*

* @author Daniel F. Savarese ***/ public class FingerClient extends SocketClient { /*** * The default FINGER port. Set to 79 according to RFC 1288. ***/ public static final int DEFAULT_PORT = 79; private static final String __LONG_FLAG = "/W "; private transient char[] __buffer = new char[1024]; /*** * The default FingerClient constructor. Initializes the * default port to DEFAULT_PORT . ***/ public FingerClient() { setDefaultPort(DEFAULT_PORT); } /*** * Fingers a user at the connected host and returns the output * as a String. You must first connect to a finger server before * calling this method, and you should disconnect afterward. *

* @param longOutput Set to true if long output is requested, false if not. * @param username The name of the user to finger. * @return The result of the finger query. * @exception IOException If an I/O error occurs while reading the socket. ***/ public String query(boolean longOutput, String username) throws IOException { int read; StringBuilder result = new StringBuilder(__buffer.length); BufferedReader input; input = new BufferedReader(new InputStreamReader(getInputStream(longOutput, username))); try { while (true) { read = input.read(__buffer, 0, __buffer.length); if (read <= 0) break; result.append(__buffer, 0, read); } } finally { input.close(); } return result.toString(); } /*** * Fingers the connected host and returns the output * as a String. You must first connect to a finger server before * calling this method, and you should disconnect afterward. * This is equivalent to calling query(longOutput, "") . *

* @param longOutput Set to true if long output is requested, false if not. * @return The result of the finger query. * @exception IOException If an I/O error occurs while reading the socket. ***/ public String query(boolean longOutput) throws IOException { return query(longOutput, ""); } /*** * Fingers a user and returns the input stream from the network connection * of the finger query. You must first connect to a finger server before * calling this method, and you should disconnect after finishing reading * the stream. *

* @param longOutput Set to true if long output is requested, false if not. * @param username The name of the user to finger. * @return The InputStream of the network connection of the finger query. * Can be read to obtain finger results. * @exception IOException If an I/O error during the operation. ***/ public InputStream getInputStream(boolean longOutput, String username) throws IOException { return getInputStream(longOutput, username, null); } /*** * Fingers a user and returns the input stream from the network connection * of the finger query. You must first connect to a finger server before * calling this method, and you should disconnect after finishing reading * the stream. *

* @param longOutput Set to true if long output is requested, false if not. * @param username The name of the user to finger. * @param encoding the character encoding that should be used for the query, * null for the platform's default encoding * @return The InputStream of the network connection of the finger query. * Can be read to obtain finger results. * @exception IOException If an I/O error during the operation. ***/ public InputStream getInputStream(boolean longOutput, String username, String encoding) throws IOException { DataOutputStream output; StringBuilder buffer = new StringBuilder(64); if (longOutput) buffer.append(__LONG_FLAG); buffer.append(username); buffer.append(SocketClient.NETASCII_EOL); byte[] encodedQuery = (encoding == null ? buffer.toString().getBytes() : buffer.toString().getBytes(encoding)); output = new DataOutputStream(new BufferedOutputStream(_output_, 1024)); output.write(encodedQuery, 0, encodedQuery.length); output.flush(); return _input_; } /*** * Fingers the connected host and returns the input stream from * the network connection of the finger query. This is equivalent to * calling getInputStream(longOutput, ""). You must first connect to a * finger server before calling this method, and you should disconnect * after finishing reading the stream. *

* @param longOutput Set to true if long output is requested, false if not. * @return The InputStream of the network connection of the finger query. * Can be read to obtain finger results. * @exception IOException If an I/O error during the operation. ***/ public InputStream getInputStream(boolean longOutput) throws IOException { return getInputStream(longOutput, ""); } } commons-net-2.2/src/main/java/org/apache/commons/net/chargen/0000755000175000017500000000000011617452467024103 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/chargen/CharGenTCPClient.java0000644000175000017500000000627710761044665027773 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.chargen; import java.io.InputStream; import org.apache.commons.net.SocketClient; /*** * The CharGenTCPClient class is a TCP implementation of a client for the * character generator protocol described in RFC 864. It can also be * used for Systat (RFC 866), Quote of the Day (RFC 865), and netstat * (port 15). All of these protocols involve connecting to the appropriate * port, and reading data from an input stream. The chargen protocol * actually sends data until the receiving end closes the connection. All * of the others send only a fixed amount of data and then close the * connection. *

* To use the CharGenTCPClient class, just establish a * connection with * {@link org.apache.commons.net.SocketClient#connect connect } * and call {@link #getInputStream getInputStream() } to access * the data. Don't close the input stream when you're done with it. Rather, * call {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to clean up properly. *

*

* @author Daniel F. Savarese * @see CharGenUDPClient ***/ public final class CharGenTCPClient extends SocketClient { /*** The systat port value of 11 according to RFC 866. ***/ public static final int SYSTAT_PORT = 11; /*** The netstat port value of 19. ***/ public static final int NETSTAT_PORT = 15; /*** The quote of the day port value of 17 according to RFC 865. ***/ public static final int QUOTE_OF_DAY_PORT = 17; /*** The character generator port value of 19 according to RFC 864. ***/ public static final int CHARGEN_PORT = 19; /*** The default chargen port. It is set to 19 according to RFC 864. ***/ public static final int DEFAULT_PORT = 19; /*** * The default constructor for CharGenTCPClient. It merely sets the * default port to DEFAULT_PORT . ***/ public CharGenTCPClient () { setDefaultPort(DEFAULT_PORT); } /*** * Returns an InputStream from which the server generated data can be * read. You should NOT close the InputStream when you're finished * reading from it. Rather, you should call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to clean up properly. *

* @return An InputStream from which the server generated data can be read. ***/ public InputStream getInputStream() { return _input_; } } commons-net-2.2/src/main/java/org/apache/commons/net/chargen/CharGenUDPClient.java0000644000175000017500000001173711354710167027766 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.chargen; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import org.apache.commons.net.DatagramSocketClient; /*** * The CharGenUDPClient class is a UDP implementation of a client for the * character generator protocol described in RFC 864. It can also be * used for Systat (RFC 866), Quote of the Day (RFC 865), and netstat * (port 15). All of these protocols involve sending a datagram to the * appropriate port, and reading data contained in one or more reply * datagrams. The chargen and quote of the day protocols only send * one reply datagram containing 512 bytes or less of data. The other * protocols may reply with more than one datagram, in which case you * must wait for a timeout to determine that all reply datagrams have * been sent. *

* To use the CharGenUDPClient class, just open a local UDP port * with {@link org.apache.commons.net.DatagramSocketClient#open open } * and call {@link #send send } to send the datagram that will * initiate the data reply. For chargen or quote of the day, just * call {@link #receive receive }, and you're done. For netstat and * systat, call receive in a while loop, and catch a SocketException and * InterruptedIOException to detect a timeout (don't forget to set the * timeout duration beforehand). Don't forget to call * {@link org.apache.commons.net.DatagramSocketClient#close close() } * to clean up properly. *

*

* @author Daniel F. Savarese * @see CharGenTCPClient ***/ public final class CharGenUDPClient extends DatagramSocketClient { /*** The systat port value of 11 according to RFC 866. ***/ public static final int SYSTAT_PORT = 11; /*** The netstat port value of 19. ***/ public static final int NETSTAT_PORT = 15; /*** The quote of the day port value of 17 according to RFC 865. ***/ public static final int QUOTE_OF_DAY_PORT = 17; /*** The character generator port value of 19 according to RFC 864. ***/ public static final int CHARGEN_PORT = 19; /*** The default chargen port. It is set to 19 according to RFC 864. ***/ public static final int DEFAULT_PORT = 19; private final byte[] __receiveData; private final DatagramPacket __receivePacket; private final DatagramPacket __sendPacket; /*** * The default CharGenUDPClient constructor. It initializes some internal * data structures for sending and receiving the necessary datagrams for * the chargen and related protocols. ***/ public CharGenUDPClient() { // CharGen return packets have a maximum length of 512 __receiveData = new byte[512]; __receivePacket = new DatagramPacket(__receiveData, __receiveData.length); __sendPacket = new DatagramPacket(new byte[0], 0); } /*** * Sends the data initiation datagram. This data in the packet is ignored * by the server, and merely serves to signal that the server should send * its reply. *

* @param host The address of the server. * @param port The port of the service. * @exception IOException If an error occurs while sending the datagram. ***/ public void send(InetAddress host, int port) throws IOException { __sendPacket.setAddress(host); __sendPacket.setPort(port); _socket_.send(__sendPacket); } /*** Same as send(host, CharGenUDPClient.DEFAULT_PORT); ***/ public void send(InetAddress host) throws IOException { send(host, DEFAULT_PORT); } /*** * Receive the reply data from the server. This will always be 512 bytes * or less. Chargen and quote of the day only return one packet. Netstat * and systat require multiple calls to receive() with timeout detection. *

* @return The reply data from the server. * @exception IOException If an error occurs while receiving the datagram. ***/ public byte[] receive() throws IOException { int length; byte[] result; _socket_.receive(__receivePacket); result = new byte[length = __receivePacket.getLength()]; System.arraycopy(__receiveData, 0, result, 0, length); return result; } } commons-net-2.2/src/main/java/org/apache/commons/net/smtp/0000755000175000017500000000000011617452466023456 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/smtp/SMTPClient.java0000644000175000017500000006225711014673543026247 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; import java.io.IOException; import java.io.Writer; import java.net.InetAddress; import org.apache.commons.net.io.DotTerminatedMessageWriter; /*** * SMTPClient encapsulates all the functionality necessary to send files * through an SMTP server. This class takes care of all * low level details of interacting with an SMTP server and provides * a convenient higher level interface. As with all classes derived * from {@link org.apache.commons.net.SocketClient}, * you must first connect to the server with * {@link org.apache.commons.net.SocketClient#connect connect } * before doing anything, and finally * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * after you're completely finished interacting with the server. * Then you need to check the SMTP reply code to see if the connection * was successful. For example: *

 *    try {
 *      int reply;
 *      client.connect("mail.foobar.com");
 *      System.out.print(client.getReplyString());
 *
 *      // After connection attempt, you should check the reply code to verify
 *      // success.
 *      reply = client.getReplyCode();
 *
 *      if(!SMTPReply.isPositiveCompletion(reply)) {
 *        client.disconnect();
 *        System.err.println("SMTP server refused connection.");
 *        System.exit(1);
 *      }
 *
 *      // Do useful stuff here.
 *      ...
 *    } catch(IOException e) {
 *      if(client.isConnected()) {
 *        try {
 *          client.disconnect();
 *        } catch(IOException f) {
 *          // do nothing
 *        }
 *      }
 *      System.err.println("Could not connect to server.");
 *      e.printStackTrace();
 *      System.exit(1);
 *    }
 * 
*

* Immediately after connecting is the only real time you need to check the * reply code (because connect is of type void). The convention for all the * SMTP command methods in SMTPClient is such that they either return a * boolean value or some other value. * The boolean methods return true on a successful completion reply from * the SMTP server and false on a reply resulting in an error condition or * failure. The methods returning a value other than boolean return a value * containing the higher level data produced by the SMTP command, or null if a * reply resulted in an error condition or failure. If you want to access * the exact SMTP reply code causing a success or failure, you must call * {@link org.apache.commons.net.smtp.SMTP#getReplyCode getReplyCode } after * a success or failure. *

* You should keep in mind that the SMTP server may choose to prematurely * close a connection for various reasons. The SMTPClient class will detect a * premature SMTP server connection closing when it receives a * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE } * response to a command. * When that occurs, the method encountering that reply will throw * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException} * . * SMTPConectionClosedException * is a subclass of IOException and therefore need not be * caught separately, but if you are going to catch it separately, its * catch block must appear before the more general IOException * catch block. When you encounter an * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException} * , you must disconnect the connection with * {@link #disconnect disconnect() } to properly clean up the * system resources used by SMTPClient. Before disconnecting, you may check * the last reply code and text with * {@link org.apache.commons.net.smtp.SMTP#getReplyCode getReplyCode }, * {@link org.apache.commons.net.smtp.SMTP#getReplyString getReplyString }, * and * {@link org.apache.commons.net.smtp.SMTP#getReplyStrings getReplyStrings}. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @see SMTP * @see SimpleSMTPHeader * @see RelayPath * @see SMTPConnectionClosedException * @see org.apache.commons.net.MalformedServerReplyException ***/ public class SMTPClient extends SMTP { /** * Default SMTPClient constructor. Creates a new SMTPClient instance. */ public SMTPClient() { } /** * Overloaded constructor that takes an encoding specification * @param encoding The encoding to use * @since 2.0 */ public SMTPClient(String encoding) { super(encoding); } /*** * At least one SMTPClient method ({@link #sendMessageData sendMessageData }) * does not complete the entire sequence of SMTP commands to complete a * transaction. These types of commands require some action by the * programmer after the reception of a positive intermediate command. * After the programmer's code completes its actions, it must call this * method to receive the completion reply from the server and verify the * success of the entire transaction. *

* For example, *

     * writer = client.sendMessage();
     * if(writer == null) // failure
     *   return false;
     * header =
     *  new SimpleSMTPHeader("foobar@foo.com", "foo@foobar.com", "Re: Foo");
     * writer.write(header.toString());
     * writer.write("This is just a test");
     * writer.close();
     * if(!client.completePendingCommand()) // failure
     *   return false;
     * 
*

* @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean completePendingCommand() throws IOException { return SMTPReply.isPositiveCompletion(getReply()); } /*** * Login to the SMTP server by sending the HELO command with the * given hostname as an argument. Before performing any mail commands, * you must first login. *

* @param hostname The hostname with which to greet the SMTP server. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean login(String hostname) throws IOException { return SMTPReply.isPositiveCompletion(helo(hostname)); } /*** * Login to the SMTP server by sending the HELO command with the * client hostname as an argument. Before performing any mail commands, * you must first login. *

* @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean login() throws IOException { String name; InetAddress host; host = getLocalAddress(); name = host.getHostName(); if (name == null) return false; return SMTPReply.isPositiveCompletion(helo(name)); } /*** * Set the sender of a message using the SMTP MAIL command, specifying * a reverse relay path. The sender must be set first before any * recipients may be specified, otherwise the mail server will reject * your commands. *

* @param path The reverse relay path pointing back to the sender. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean setSender(RelayPath path) throws IOException { return SMTPReply.isPositiveCompletion(mail(path.toString())); } /*** * Set the sender of a message using the SMTP MAIL command, specifying * the sender's email address. The sender must be set first before any * recipients may be specified, otherwise the mail server will reject * your commands. *

* @param address The sender's email address. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean setSender(String address) throws IOException { return SMTPReply.isPositiveCompletion(mail("<" + address + ">")); } /*** * Add a recipient for a message using the SMTP RCPT command, specifying * a forward relay path. The sender must be set first before any * recipients may be specified, otherwise the mail server will reject * your commands. *

* @param path The forward relay path pointing to the recipient. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean addRecipient(RelayPath path) throws IOException { return SMTPReply.isPositiveCompletion(rcpt(path.toString())); } /*** * Add a recipient for a message using the SMTP RCPT command, the * recipient's email address. The sender must be set first before any * recipients may be specified, otherwise the mail server will reject * your commands. *

* @param address The recipient's email address. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean addRecipient(String address) throws IOException { return SMTPReply.isPositiveCompletion(rcpt("<" + address + ">")); } /*** * Send the SMTP DATA command in preparation to send an email message. * This method returns a DotTerminatedMessageWriter instance to which * the message can be written. Null is returned if the DATA command * fails. *

* You must not issue any commands to the SMTP server (i.e., call any * (other methods) until you finish writing to the returned Writer * instance and close it. The SMTP protocol uses the same stream for * issuing commands as it does for returning results. Therefore the * returned Writer actually writes directly to the SMTP connection. * After you close the writer, you can execute new commands. If you * do not follow these requirements your program will not work properly. *

* You can use the provided * {@link org.apache.commons.net.smtp.SimpleSMTPHeader} * class to construct a bare minimum header. * To construct more complicated headers you should * refer to RFC 822. When the Java Mail API is finalized, you will be * able to use it to compose fully compliant Internet text messages. * The DotTerminatedMessageWriter takes care of doubling line-leading * dots and ending the message with a single dot upon closing, so all * you have to worry about is writing the header and the message. *

* Upon closing the returned Writer, you need to call * {@link #completePendingCommand completePendingCommand() } * to finalize the transaction and verify its success or failure from * the server reply. *

* @return A DotTerminatedMessageWriter to which the message (including * header) can be written. Returns null if the command fails. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public Writer sendMessageData() throws IOException { if (!SMTPReply.isPositiveIntermediate(data())) return null; return new DotTerminatedMessageWriter(_writer); } /*** * A convenience method for sending short messages. This method fetches * the Writer returned by {@link #sendMessageData sendMessageData() } * and writes the specified String to it. After writing the message, * this method calls {@link #completePendingCommand completePendingCommand() } * to finalize the transaction and returns * its success or failure. *

* @param message The short email message to send. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean sendShortMessageData(String message) throws IOException { Writer writer; writer = sendMessageData(); if (writer == null) return false; writer.write(message); writer.close(); return completePendingCommand(); } /*** * A convenience method for a sending short email without having to * explicitly set the sender and recipient(s). This method * sets the sender and recipient using * {@link #setSender setSender } and * {@link #addRecipient addRecipient }, and then sends the * message using {@link #sendShortMessageData sendShortMessageData }. *

* @param sender The email address of the sender. * @param recipient The email address of the recipient. * @param message The short email message to send. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean sendSimpleMessage(String sender, String recipient, String message) throws IOException { if (!setSender(sender)) return false; if (!addRecipient(recipient)) return false; return sendShortMessageData(message); } /*** * A convenience method for a sending short email without having to * explicitly set the sender and recipient(s). This method * sets the sender and recipients using * {@link #setSender setSender } and * {@link #addRecipient addRecipient }, and then sends the * message using {@link #sendShortMessageData sendShortMessageData }. *

* @param sender The email address of the sender. * @param recipients An array of recipient email addresses. * @param message The short email message to send. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean sendSimpleMessage(String sender, String[] recipients, String message) throws IOException { boolean oneSuccess = false; int count; if (!setSender(sender)) return false; for (count = 0; count < recipients.length; count++) { if (addRecipient(recipients[count])) oneSuccess = true; } if (!oneSuccess) return false; return sendShortMessageData(message); } /*** * Logout of the SMTP server by sending the QUIT command. *

* @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean logout() throws IOException { return SMTPReply.isPositiveCompletion(quit()); } /*** * Aborts the current mail transaction, resetting all server stored * sender, recipient, and mail data, cleaing all buffers and tables. *

* @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean reset() throws IOException { return SMTPReply.isPositiveCompletion(rset()); } /*** * Verify that a username or email address is valid, i.e., that mail * can be delivered to that mailbox on the server. *

* @param username The username or email address to validate. * @return True if the username is valid, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean verify(String username) throws IOException { int result; result = vrfy(username); return (result == SMTPReply.ACTION_OK || result == SMTPReply.USER_NOT_LOCAL_WILL_FORWARD); } /*** * Fetches the system help information from the server and returns the * full string. *

* @return The system help string obtained from the server. null if the * information could not be obtained. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String listHelp() throws IOException { if (SMTPReply.isPositiveCompletion(help())) return getReplyString(); return null; } /*** * Fetches the help information for a given command from the server and * returns the full string. *

* @param command The command on which to ask for help. * @return The command help string obtained from the server. null if the * information could not be obtained. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String listHelp(String command) throws IOException { if (SMTPReply.isPositiveCompletion(help(command))) return getReplyString(); return null; } /*** * Sends a NOOP command to the SMTP server. This is useful for preventing * server timeouts. *

* @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean sendNoOp() throws IOException { return SMTPReply.isPositiveCompletion(noop()); } } commons-net-2.2/src/main/java/org/apache/commons/net/smtp/SMTPConnectionClosedException.java0000644000175000017500000000356610542533103032127 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; import java.io.IOException; /*** * SMTPConnectionClosedException is used to indicate the premature or * unexpected closing of an SMTP connection resulting from a * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE } * response (SMTP reply code 421) to a * failed SMTP command. This exception is derived from IOException and * therefore may be caught either as an IOException or specifically as an * SMTPConnectionClosedException. *

*

* @author Daniel F. Savarese * @see SMTP * @see SMTPClient ***/ public final class SMTPConnectionClosedException extends IOException { /*** Constructs a SMTPConnectionClosedException with no message ***/ public SMTPConnectionClosedException() { super(); } /*** * Constructs a SMTPConnectionClosedException with a specified message. *

* @param message The message explaining the reason for the exception. ***/ public SMTPConnectionClosedException(String message) { super(message); } } commons-net-2.2/src/main/java/org/apache/commons/net/smtp/RelayPath.java0000644000175000017500000000566511354512541026213 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; import java.util.Enumeration; import java.util.Vector; /*** * A class used to represent forward and reverse relay paths. The * SMTP MAIL command requires a reverse relay path while the SMTP RCPT * command requires a forward relay path. See RFC 821 for more details. * In general, you will not have to deal with relay paths. *

*

* @author Daniel F. Savarese * @see SMTPClient ***/ public final class RelayPath { Vector _path; String _emailAddress; /*** * Create a relay path with the specified email address as the ultimate * destination. *

* @param emailAddress The destination email address. ***/ public RelayPath(String emailAddress) { _path = new Vector(); _emailAddress = emailAddress; } /*** * Add a mail relay host to the relay path. Hosts are added left to * right. For example, the following will create the path * < @bar.com,@foo.com:foobar@foo.com > *

     * path = new RelayPath("foobar@foo.com");
     * path.addRelay("bar.com");
     * path.addRelay("foo.com");
     * 
*

* @param hostname The host to add to the relay path. ***/ public void addRelay(String hostname) { _path.addElement(hostname); } /*** * Return the properly formatted string representation of the relay path. *

* @return The properly formatted string representation of the relay path. ***/ @Override public String toString() { StringBuilder buffer = new StringBuilder(); Enumeration hosts; buffer.append('<'); hosts = _path.elements(); if (hosts.hasMoreElements()) { buffer.append('@'); buffer.append(hosts.nextElement()); while (hosts.hasMoreElements()) { buffer.append(",@"); buffer.append(hosts.nextElement()); } buffer.append(':'); } buffer.append(_emailAddress); buffer.append('>'); return buffer.toString(); } } commons-net-2.2/src/main/java/org/apache/commons/net/smtp/SimpleSMTPHeader.java0000644000175000017500000001144311354512541027357 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; /*** * This class is used to construct a bare minimum * acceptable header for an email message. To construct more * complicated headers you should refer to RFC 822. When the * Java Mail API is finalized, you will be * able to use it to compose fully compliant Internet text messages. *

* The main purpose of the class is to faciliatate the mail sending * process, by relieving the programmer from having to explicitly format * a simple message header. For example: *

 * writer = client.sendMessageData();
 * if(writer == null) // failure
 *   return false;
 * header =
 *    new SimpleSMTPHeader("foobar@foo.com", "foo@bar.com" "Just testing");
 * header.addCC("bar@foo.com");
 * header.addHeaderField("Organization", "Foobar, Inc.");
 * writer.write(header.toString());
 * writer.write("This is just a test");
 * writer.close();
 * if(!client.completePendingCommand()) // failure
 *   return false;
 * 
*

*

* @author Daniel F. Savarese * @see SMTPClient ***/ public class SimpleSMTPHeader { private String __subject, __from, __to; private StringBuffer __headerFields, __cc; /*** * Creates a new SimpleSMTPHeader instance initialized with the given * from, to, and subject header field values. *

* @param from The value of the From: header field. This * should be the sender's email address. * @param to The value of the To: header field. This * should be the recipient's email address. * @param subject The value of the Subject: header field. * This should be the subject of the message. ***/ public SimpleSMTPHeader(String from, String to, String subject) { __to = to; __from = from; __subject = subject; __headerFields = new StringBuffer(); __cc = null; } /*** * Adds an arbitrary header field with the given value to the article * header. These headers will be written before the From, To, Subject, and * Cc fields when the SimpleSMTPHeader is convertered to a string. * An example use would be: *

     * header.addHeaderField("Organization", "Foobar, Inc.");
     * 
*

* @param headerField The header field to add, not including the colon. * @param value The value of the added header field. ***/ public void addHeaderField(String headerField, String value) { __headerFields.append(headerField); __headerFields.append(": "); __headerFields.append(value); __headerFields.append('\n'); } /*** * Add an email address to the CC (carbon copy or courtesy copy) list. *

* @param address The email address to add to the CC list. ***/ public void addCC(String address) { if (__cc == null) __cc = new StringBuffer(); else __cc.append(", "); __cc.append(address); } /*** * Converts the SimpleSMTPHeader to a properly formatted header in * the form of a String, including the blank line used to separate * the header from the article body. The header fields CC and Subject * are only included when they are non-null. *

* @return The message header in the form of a String. ***/ @Override public String toString() { StringBuilder header = new StringBuilder(); if (__headerFields.length() > 0) header.append(__headerFields.toString()); header.append("From: "); header.append(__from); header.append("\nTo: "); header.append(__to); if (__cc != null) { header.append("\nCc: "); header.append(__cc.toString()); } if (__subject != null) { header.append("\nSubject: "); header.append(__subject); } header.append('\n'); header.append('\n'); return header.toString(); } } commons-net-2.2/src/main/java/org/apache/commons/net/smtp/SMTP.java0000644000175000017500000007375311347053246025114 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import org.apache.commons.net.MalformedServerReplyException; import org.apache.commons.net.ProtocolCommandListener; import org.apache.commons.net.ProtocolCommandSupport; import org.apache.commons.net.SocketClient; /*** * SMTP provides the basic the functionality necessary to implement your * own SMTP client. To derive the full benefits of the SMTP class requires * some knowledge of the FTP protocol defined in RFC 821. However, there * is no reason why you should have to use the SMTP class. The * {@link org.apache.commons.net.smtp.SMTPClient} class, * derived from SMTP, * implements all the functionality required of an SMTP client. The * SMTP class is made public to provide access to various SMTP constants * and to make it easier for adventurous programmers (or those with * special needs) to interact with the SMTP protocol and implement their * own clients. A set of methods with names corresponding to the SMTP * command names are provided to facilitate this interaction. *

* You should keep in mind that the SMTP server may choose to prematurely * close a connection for various reasons. The SMTP class will detect a * premature SMTP server connection closing when it receives a * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE } * response to a command. * When that occurs, the SMTP class method encountering that reply will throw * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException} * . * SMTPConectionClosedException * is a subclass of IOException and therefore need not be * caught separately, but if you are going to catch it separately, its * catch block must appear before the more general IOException * catch block. When you encounter an * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException} * , you must disconnect the connection with * {@link org.apache.commons.net.SocketClient#disconnect disconnect() } * to properly clean up the system resources used by SMTP. Before * disconnecting, you may check the * last reply code and text with * {@link #getReplyCode getReplyCode }, * {@link #getReplyString getReplyString }, * and {@link #getReplyStrings getReplyStrings}. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @see SMTPClient * @see SMTPConnectionClosedException * @see org.apache.commons.net.MalformedServerReplyException ***/ public class SMTP extends SocketClient { /*** The default SMTP port (25). ***/ public static final int DEFAULT_PORT = 25; // We have to ensure that the protocol communication is in ASCII // but we use ISO-8859-1 just in case 8-bit characters cross // the wire. private static final String __DEFAULT_ENCODING = "ISO-8859-1"; /** The encoding to use (user-settable) */ private String encoding = __DEFAULT_ENCODING; private StringBuffer __commandBuffer; BufferedReader _reader; BufferedWriter _writer; int _replyCode; ArrayList _replyLines; boolean _newReplyString; String _replyString; /*** * A ProtocolCommandSupport object used to manage the registering of * ProtocolCommandListeners and te firing of ProtocolCommandEvents. ***/ protected ProtocolCommandSupport _commandSupport_; /*** * The default SMTP constructor. Sets the default port to * DEFAULT_PORT and initializes internal data structures * for saving SMTP reply information. ***/ public SMTP() { setDefaultPort(DEFAULT_PORT); __commandBuffer = new StringBuffer(); _replyLines = new ArrayList(); _newReplyString = false; _replyString = null; _commandSupport_ = new ProtocolCommandSupport(this); } /** * Overloaded constructor where the user may specify a default encoding. * @param encoding * @since 2.0 */ public SMTP(String encoding) { this(); this.encoding = encoding; } private int __sendCommand(String command, String args, boolean includeSpace) throws IOException { String message; __commandBuffer.setLength(0); __commandBuffer.append(command); if (args != null) { if (includeSpace) __commandBuffer.append(' '); __commandBuffer.append(args); } __commandBuffer.append(SocketClient.NETASCII_EOL); _writer.write(message = __commandBuffer.toString()); _writer.flush(); if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireCommandSent(command, message); __getReply(); return _replyCode; } private int __sendCommand(int command, String args, boolean includeSpace) throws IOException { return __sendCommand(SMTPCommand._commands[command], args, includeSpace); } private void __getReply() throws IOException { int length; _newReplyString = true; _replyLines.clear(); String line = _reader.readLine(); if (line == null) throw new SMTPConnectionClosedException( "Connection closed without indication."); // In case we run into an anomaly we don't want fatal index exceptions // to be thrown. length = line.length(); if (length < 3) throw new MalformedServerReplyException( "Truncated server reply: " + line); try { String code = line.substring(0, 3); _replyCode = Integer.parseInt(code); } catch (NumberFormatException e) { throw new MalformedServerReplyException( "Could not parse response code.\nServer Reply: " + line); } _replyLines.add(line); // Get extra lines if message continues. if (length > 3 && line.charAt(3) == '-') { do { line = _reader.readLine(); if (line == null) throw new SMTPConnectionClosedException( "Connection closed without indication."); _replyLines.add(line); // The length() check handles problems that could arise from readLine() // returning too soon after encountering a naked CR or some other // anomaly. } while (!(line.length() >= 4 && line.charAt(3) != '-' && Character.isDigit(line.charAt(0)))); // This is too strong a condition because a non-conforming server // could screw things up like ftp.funet.fi does for FTP // line.startsWith(code))); } if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireReplyReceived(_replyCode, getReplyString()); if (_replyCode == SMTPReply.SERVICE_NOT_AVAILABLE) throw new SMTPConnectionClosedException( "SMTP response 421 received. Server closed connection."); } /*** Initiates control connections and gets initial reply. ***/ @Override protected void _connectAction_() throws IOException { super._connectAction_(); _reader = new BufferedReader(new InputStreamReader(_input_, encoding)); _writer = new BufferedWriter(new OutputStreamWriter(_output_, encoding)); __getReply(); } /*** * Adds a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to add. ***/ public void addProtocolCommandListener(ProtocolCommandListener listener) { _commandSupport_.addProtocolCommandListener(listener); } /*** * Removes a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to remove. ***/ public void removeProtocolCommandistener(ProtocolCommandListener listener) { _commandSupport_.removeProtocolCommandListener(listener); } /*** * Closes the connection to the SMTP server and sets to null * some internal data so that the memory may be reclaimed by the * garbage collector. The reply text and code information from the * last command is voided so that the memory it used may be reclaimed. *

* @exception IOException If an error occurs while disconnecting. ***/ @Override public void disconnect() throws IOException { super.disconnect(); _reader = null; _writer = null; _replyString = null; _replyLines.clear(); _newReplyString = false; } /*** * Sends an SMTP command to the server, waits for a reply and returns the * numerical response code. After invocation, for more detailed * information, the actual reply text can be accessed by calling * {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The text representation of the SMTP command to send. * @param args The arguments to the SMTP command. If this parameter is * set to null, then the command is sent with no argument. * @return The integer value of the SMTP reply code returned by the server * in response to the command. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(String command, String args) throws IOException { return __sendCommand(command, args, true); } /*** * Sends an SMTP command to the server, waits for a reply and returns the * numerical response code. After invocation, for more detailed * information, the actual reply text can be accessed by calling * {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The SMTPCommand constant corresponding to the SMTP command * to send. * @param args The arguments to the SMTP command. If this parameter is * set to null, then the command is sent with no argument. * @return The integer value of the SMTP reply code returned by the server * in response to the command. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(int command, String args) throws IOException { return sendCommand(SMTPCommand._commands[command], args); } /*** * Sends an SMTP command with no arguments to the server, waits for a * reply and returns the numerical response code. After invocation, for * more detailed information, the actual reply text can be accessed by * calling {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The text representation of the SMTP command to send. * @return The integer value of the SMTP reply code returned by the server * in response to the command. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(String command) throws IOException { return sendCommand(command, null); } /*** * Sends an SMTP command with no arguments to the server, waits for a * reply and returns the numerical response code. After invocation, for * more detailed information, the actual reply text can be accessed by * calling {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The SMTPCommand constant corresponding to the SMTP command * to send. * @return The integer value of the SMTP reply code returned by the server * in response to the command. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(int command) throws IOException { return sendCommand(command, null); } /*** * Returns the integer value of the reply code of the last SMTP reply. * You will usually only use this method after you connect to the * SMTP server to check that the connection was successful since * connect is of type void. *

* @return The integer value of the reply code of the last SMTP reply. ***/ public int getReplyCode() { return _replyCode; } /*** * Fetches a reply from the SMTP server and returns the integer reply * code. After calling this method, the actual reply text can be accessed * from either calling {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. Only use this * method if you are implementing your own SMTP client or if you need to * fetch a secondary response from the SMTP server. *

* @return The integer value of the reply code of the fetched SMTP reply. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while receiving the * server reply. ***/ public int getReply() throws IOException { __getReply(); return _replyCode; } /*** * Returns the lines of text from the last SMTP server response as an array * of strings, one entry per line. The end of line markers of each are * stripped from each line. *

* @return The lines of text from the last SMTP response as an array. ***/ public String[] getReplyStrings() { return _replyLines.toArray(new String[_replyLines.size()]); } /*** * Returns the entire text of the last SMTP server response exactly * as it was received, including all end of line markers in NETASCII * format. *

* @return The entire text from the last SMTP response as a String. ***/ public String getReplyString() { StringBuilder buffer; if (!_newReplyString) return _replyString; buffer = new StringBuilder(); for (String line : _replyLines) { buffer.append(line); buffer.append(SocketClient.NETASCII_EOL); } _newReplyString = false; return (_replyString = buffer.toString()); } /*** * A convenience method to send the SMTP HELO command to the server, * receive the reply, and return the reply code. *

* @param hostname The hostname of the sender. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int helo(String hostname) throws IOException { return sendCommand(SMTPCommand.HELO, hostname); } /*** * A convenience method to send the SMTP MAIL command to the server, * receive the reply, and return the reply code. *

* @param reversePath The reverese path. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int mail(String reversePath) throws IOException { return __sendCommand(SMTPCommand.MAIL, reversePath, false); } /*** * A convenience method to send the SMTP RCPT command to the server, * receive the reply, and return the reply code. *

* @param forwardPath The forward path. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rcpt(String forwardPath) throws IOException { return __sendCommand(SMTPCommand.RCPT, forwardPath, false); } /*** * A convenience method to send the SMTP DATA command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int data() throws IOException { return sendCommand(SMTPCommand.DATA); } /*** * A convenience method to send the SMTP SEND command to the server, * receive the reply, and return the reply code. *

* @param reversePath The reverese path. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int send(String reversePath) throws IOException { return sendCommand(SMTPCommand.SEND, reversePath); } /*** * A convenience method to send the SMTP SOML command to the server, * receive the reply, and return the reply code. *

* @param reversePath The reverese path. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int soml(String reversePath) throws IOException { return sendCommand(SMTPCommand.SOML, reversePath); } /*** * A convenience method to send the SMTP SAML command to the server, * receive the reply, and return the reply code. *

* @param reversePath The reverese path. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int saml(String reversePath) throws IOException { return sendCommand(SMTPCommand.SAML, reversePath); } /*** * A convenience method to send the SMTP RSET command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rset() throws IOException { return sendCommand(SMTPCommand.RSET); } /*** * A convenience method to send the SMTP VRFY command to the server, * receive the reply, and return the reply code. *

* @param user The user address to verify. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int vrfy(String user) throws IOException { return sendCommand(SMTPCommand.VRFY, user); } /*** * A convenience method to send the SMTP VRFY command to the server, * receive the reply, and return the reply code. *

* @param name The name to expand. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int expn(String name) throws IOException { return sendCommand(SMTPCommand.EXPN, name); } /*** * A convenience method to send the SMTP HELP command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int help() throws IOException { return sendCommand(SMTPCommand.HELP); } /*** * A convenience method to send the SMTP HELP command to the server, * receive the reply, and return the reply code. *

* @param command The command name on which to request help. * @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int help(String command) throws IOException { return sendCommand(SMTPCommand.HELP, command); } /*** * A convenience method to send the SMTP NOOP command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int noop() throws IOException { return sendCommand(SMTPCommand.NOOP); } /*** * A convenience method to send the SMTP TURN command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int turn() throws IOException { return sendCommand(SMTPCommand.TURN); } /*** * A convenience method to send the SMTP QUIT command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception SMTPConnectionClosedException * If the SMTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int quit() throws IOException { return sendCommand(SMTPCommand.QUIT); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/smtp/SMTPReply.java0000644000175000017500000001535010542533103026104 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; /*** * SMTPReply stores a set of constants for SMTP reply codes. To interpret * the meaning of the codes, familiarity with RFC 821 is assumed. * The mnemonic constant names are transcriptions from the code descriptions * of RFC 821. For those who think in terms of the actual reply code values, * a set of CODE_NUM constants are provided where NUM is the numerical value * of the code. *

*

* @author Daniel F. Savarese ***/ public final class SMTPReply { public static final int CODE_211 = 211; public static final int CODE_214 = 214; public static final int CODE_215 = 215; public static final int CODE_220 = 220; public static final int CODE_221 = 221; public static final int CODE_250 = 250; public static final int CODE_251 = 251; public static final int CODE_354 = 354; public static final int CODE_421 = 421; public static final int CODE_450 = 450; public static final int CODE_451 = 451; public static final int CODE_452 = 452; public static final int CODE_500 = 500; public static final int CODE_501 = 501; public static final int CODE_502 = 502; public static final int CODE_503 = 503; public static final int CODE_504 = 504; public static final int CODE_550 = 550; public static final int CODE_551 = 551; public static final int CODE_552 = 552; public static final int CODE_553 = 553; public static final int CODE_554 = 554; public static final int SYSTEM_STATUS = CODE_211; public static final int HELP_MESSAGE = CODE_214; public static final int SERVICE_READY = CODE_220; public static final int SERVICE_CLOSING_TRANSMISSION_CHANNEL = CODE_221; public static final int ACTION_OK = CODE_250; public static final int USER_NOT_LOCAL_WILL_FORWARD = CODE_251; public static final int START_MAIL_INPUT = CODE_354; public static final int SERVICE_NOT_AVAILABLE = CODE_421; public static final int ACTION_NOT_TAKEN = CODE_450; public static final int ACTION_ABORTED = CODE_451; public static final int INSUFFICIENT_STORAGE = CODE_452; public static final int UNRECOGNIZED_COMMAND = CODE_500; public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501; public static final int COMMAND_NOT_IMPLEMENTED = CODE_502; public static final int BAD_COMMAND_SEQUENCE = CODE_503; public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504; public static final int MAILBOX_UNAVAILABLE = CODE_550; public static final int USER_NOT_LOCAL = CODE_551; public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552; public static final int MAILBOX_NAME_NOT_ALLOWED = CODE_553; public static final int TRANSACTION_FAILED = CODE_554; // Cannot be instantiated private SMTPReply() {} /*** * Determine if a reply code is a positive preliminary response. All * codes beginning with a 1 are positive preliminary responses. * Postitive preliminary responses are used to indicate tentative success. * No further commands can be issued to the SMTP server after a positive * preliminary response until a follow up response is received from the * server. *

* Note: No SMTP commands defined in RFC 822 provide this * type of reply. *

* @param reply The reply code to test. * @return True if a reply code is a postive preliminary response, false * if not. ***/ public static boolean isPositivePreliminary(int reply) { return (reply >= 100 && reply < 200); } /*** * Determine if a reply code is a positive completion response. All * codes beginning with a 2 are positive completion responses. * The SMTP server will send a positive completion response on the final * successful completion of a command. *

* @param reply The reply code to test. * @return True if a reply code is a postive completion response, false * if not. ***/ public static boolean isPositiveCompletion(int reply) { return (reply >= 200 && reply < 300); } /*** * Determine if a reply code is a positive intermediate response. All * codes beginning with a 3 are positive intermediate responses. * The SMTP server will send a positive intermediate response on the * successful completion of one part of a multi-part sequence of * commands. For example, after a successful DATA command, a positive * intermediate response will be sent to indicate that the server is * ready to receive the message data. *

* @param reply The reply code to test. * @return True if a reply code is a postive intermediate response, false * if not. ***/ public static boolean isPositiveIntermediate(int reply) { return (reply >= 300 && reply < 400); } /*** * Determine if a reply code is a negative transient response. All * codes beginning with a 4 are negative transient responses. * The SMTP server will send a negative transient response on the * failure of a command that can be reattempted with success. *

* @param reply The reply code to test. * @return True if a reply code is a negative transient response, false * if not. ***/ public static boolean isNegativeTransient(int reply) { return (reply >= 400 && reply < 500); } /*** * Determine if a reply code is a negative permanent response. All * codes beginning with a 5 are negative permanent responses. * The SMTP server will send a negative permanent response on the * failure of a command that cannot be reattempted with success. *

* @param reply The reply code to test. * @return True if a reply code is a negative permanent response, false * if not. ***/ public static boolean isNegativePermanent(int reply) { return (reply >= 500 && reply < 600); } } commons-net-2.2/src/main/java/org/apache/commons/net/smtp/SMTPCommand.java0000644000175000017500000000645410542533103026374 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.smtp; /*** * SMTPCommand stores a set of constants for SMTP command codes. To interpret * the meaning of the codes, familiarity with RFC 821 is assumed. * The mnemonic constant names are transcriptions from the code descriptions * of RFC 821. For those who think in terms of the actual SMTP commands, * a set of constants such as {@link #HELO HELO } are provided * where the constant name is the same as the SMTP command. *

*

* @author Daniel F. Savarese ***/ public final class SMTPCommand { public static final int HELO = 0; public static final int MAIL = 1; public static final int RCPT = 2; public static final int DATA = 3; public static final int SEND = 4; public static final int SOML = 5; public static final int SAML = 6; public static final int RSET = 7; public static final int VRFY = 8; public static final int EXPN = 9; public static final int HELP = 10; public static final int NOOP = 11; public static final int TURN = 12; public static final int QUIT = 13; public static final int HELLO = HELO; public static final int LOGIN = HELO; public static final int MAIL_FROM = MAIL; public static final int RECIPIENT = RCPT; public static final int SEND_MESSAGE_DATA = DATA; public static final int SEND_FROM = SEND; public static final int SEND_OR_MAIL_FROM = SOML; public static final int SEND_AND_MAIL_FROM = SAML; public static final int RESET = RSET; public static final int VERIFY = VRFY; public static final int EXPAND = EXPN; // public static final int HELP = HELP; // public static final int NOOP = NOOP; // public static final int TURN = TURN; // public static final int QUIT = QUIT; public static final int LOGOUT = QUIT; // Cannot be instantiated private SMTPCommand() {} static final String[] _commands = { "HELO", "MAIL FROM:", "RCPT TO:", "DATA", "SEND FROM:", "SOML FROM:", "SAML FROM:", "RSET", "VRFY", "EXPN", "HELP", "NOOP", "TURN", "QUIT" }; /*** * Retrieve the SMTP protocol command string corresponding to a specified * command code. *

* @param command The command code. * @return The SMTP protcol command string corresponding to a specified * command code. ***/ public static final String getCommand(int command) { return _commands[command]; } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/0000755000175000017500000000000011617452467023451 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPReadRequestPacket.java0000644000175000017500000000603710542533103030353 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * A class derived from TFTPRequestPacket definiing a TFTP read request * packet type. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTPRequestPacket * @see TFTPPacketException * @see TFTP ***/ public final class TFTPReadRequestPacket extends TFTPRequestPacket { /*** * Creates a read request packet to be sent to a host at a * given port with a filename and transfer mode request. *

* @param destination The host to which the packet is going to be sent. * @param port The port to which the packet is going to be sent. * @param filename The requested filename. * @param mode The requested transfer mode. This should be on of the TFTP * class MODE constants (e.g., TFTP.NETASCII_MODE). ***/ public TFTPReadRequestPacket(InetAddress destination, int port, String filename, int mode) { super(destination, port, TFTPPacket.READ_REQUEST, filename, mode); } /*** * Creates a read request packet of based on a received * datagram and assumes the datagram has already been identified as a * read request. Assumes the datagram is at least length 4, else an * ArrayIndexOutOfBoundsException may be thrown. *

* @param datagram The datagram containing the received request. * @throws TFTPPacketException If the datagram isn't a valid TFTP * request packet. ***/ TFTPReadRequestPacket(DatagramPacket datagram) throws TFTPPacketException { super(TFTPPacket.READ_REQUEST, datagram); } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPRequestPacket.java0000644000175000017500000002066511416072763027575 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * An abstract class derived from TFTPPacket definiing a TFTP Request * packet type. It is subclassed by the * {@link org.apache.commons.net.tftp.TFTPReadRequestPacket} * and * {@link org.apache.commons.net.tftp.TFTPWriteRequestPacket} * classes. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTPReadRequestPacket * @see TFTPWriteRequestPacket * @see TFTPPacketException * @see TFTP ***/ public abstract class TFTPRequestPacket extends TFTPPacket { /*** * An array containing the string names of the transfer modes and indexed * by the transfer mode constants. ***/ static final String[] _modeStrings = { "netascii", "octet" }; /*** * A null terminated byte array representation of the ascii names of the * transfer mode constants. This is convenient for creating the TFTP * request packets. ***/ private static final byte[] _modeBytes[] = { { (byte)'n', (byte)'e', (byte)'t', (byte)'a', (byte)'s', (byte)'c', (byte)'i', (byte)'i', 0 }, { (byte)'o', (byte)'c', (byte)'t', (byte)'e', (byte)'t', 0 } }; /*** The transfer mode of the request. ***/ private final int _mode; /*** The filename of the request. ***/ private final String _filename; /*** * Creates a request packet of a given type to be sent to a host at a * given port with a filename and transfer mode request. *

* @param destination The host to which the packet is going to be sent. * @param port The port to which the packet is going to be sent. * @param type The type of the request (either TFTPPacket.READ_REQUEST or * TFTPPacket.WRITE_REQUEST). * @param filename The requested filename. * @param mode The requested transfer mode. This should be on of the TFTP * class MODE constants (e.g., TFTP.NETASCII_MODE). ***/ TFTPRequestPacket(InetAddress destination, int port, int type, String filename, int mode) { super(type, destination, port); _filename = filename; _mode = mode; } /*** * Creates a request packet of a given type based on a received * datagram. Assumes the datagram is at least length 4, else an * ArrayIndexOutOfBoundsException may be thrown. *

* @param type The type of the request (either TFTPPacket.READ_REQUEST or * TFTPPacket.WRITE_REQUEST). * @param datagram The datagram containing the received request. * @throws TFTPPacketException If the datagram isn't a valid TFTP * request packet of the appropriate type. ***/ TFTPRequestPacket(int type, DatagramPacket datagram) throws TFTPPacketException { super(type, datagram.getAddress(), datagram.getPort()); byte[] data = datagram.getData(); if (getType() != data[1]) throw new TFTPPacketException("TFTP operator code does not match type."); StringBuilder buffer = new StringBuilder(); int index = 2; int length = datagram.getLength(); while (index < length && data[index] != 0) { buffer.append((char)data[index]); ++index; } _filename = buffer.toString(); if (index >= length) throw new TFTPPacketException("Bad filename and mode format."); buffer.setLength(0); ++index; // need to advance beyond the end of string marker while (index < length && data[index] != 0) { buffer.append((char)data[index]); ++index; } String modeString = buffer.toString().toLowerCase(java.util.Locale.ENGLISH); length = _modeStrings.length; int mode = 0; for (index = 0; index < length; index++) { if (modeString.equals(_modeStrings[index])) { mode = index; break; } } _mode = mode; if (index >= length) { throw new TFTPPacketException("Unrecognized TFTP transfer mode: " + modeString); // May just want to default to binary mode instead of throwing // exception. //_mode = TFTP.OCTET_MODE; } } /*** * This is a method only available within the package for * implementing efficient datagram transport by elminating buffering. * It takes a datagram as an argument, and a byte buffer in which * to store the raw datagram data. Inside the method, the data * is set as the datagram's data and the datagram returned. *

* @param datagram The datagram to create. * @param data The buffer to store the packet and to use in the datagram. * @return The datagram argument. ***/ @Override final DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) { int fileLength, modeLength; fileLength = _filename.length(); modeLength = _modeBytes[_mode].length; data[0] = 0; data[1] = (byte)_type; System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength); data[fileLength + 2] = 0; System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3, modeLength); datagram.setAddress(_address); datagram.setPort(_port); datagram.setData(data); datagram.setLength(fileLength + modeLength + 3); return datagram; } /*** * Creates a UDP datagram containing all the TFTP * request packet data in the proper format. * This is a method exposed to the programmer in case he * wants to implement his own TFTP client instead of using * the {@link org.apache.commons.net.tftp.TFTPClient} * class. Under normal circumstances, you should not have a need to call * this method. *

* @return A UDP datagram containing the TFTP request packet. ***/ @Override public final DatagramPacket newDatagram() { int fileLength, modeLength; byte[] data; fileLength = _filename.length(); modeLength = _modeBytes[_mode].length; data = new byte[fileLength + modeLength + 4]; data[0] = 0; data[1] = (byte)_type; System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength); data[fileLength + 2] = 0; System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3, modeLength); return new DatagramPacket(data, data.length, _address, _port); } /*** * Returns the transfer mode of the request. *

* @return The transfer mode of the request. ***/ public final int getMode() { return _mode; } /*** * Returns the requested filename. *

* @return The requested filename. ***/ public final String getFilename() { return _filename; } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPPacket.java0000644000175000017500000002007210542533103026201 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * TFTPPacket is an abstract class encapsulating the functionality common * to the 5 types of TFTP packets. It also provides a static factory * method that will create the correct TFTP packet instance from a * datagram. This relieves the programmer from having to figure out what * kind of TFTP packet is contained in a datagram and create it himself. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacketException * @see TFTP ***/ public abstract class TFTPPacket { /*** * The minimum size of a packet. This is 4 bytes. It is enough * to store the opcode and blocknumber or other required data * depending on the packet type. ***/ static final int MIN_PACKET_SIZE = 4; /*** * This is the actual TFTP spec * identifier and is equal to 1. * Identifier returned by {@link #getType getType()} * indicating a read request packet. ***/ public static final int READ_REQUEST = 1; /*** * This is the actual TFTP spec * identifier and is equal to 2. * Identifier returned by {@link #getType getType()} * indicating a write request packet. ***/ public static final int WRITE_REQUEST = 2; /*** * This is the actual TFTP spec * identifier and is equal to 3. * Identifier returned by {@link #getType getType()} * indicating a data packet. ***/ public static final int DATA = 3; /*** * This is the actual TFTP spec * identifier and is equal to 4. * Identifier returned by {@link #getType getType()} * indicating an acknowledgement packet. ***/ public static final int ACKNOWLEDGEMENT = 4; /*** * This is the actual TFTP spec * identifier and is equal to 5. * Identifier returned by {@link #getType getType()} * indicating an error packet. ***/ public static final int ERROR = 5; /*** * The TFTP data packet maximum segment size in bytes. This is 512 * and is useful for those familiar with the TFTP protocol who want * to use the {@link org.apache.commons.net.tftp.TFTP} * class methods to implement their own TFTP servers or clients. ***/ public static final int SEGMENT_SIZE = 512; /*** The type of packet. ***/ int _type; /*** The port the packet came from or is going to. ***/ int _port; /*** The host the packet is going to be sent or where it came from. ***/ InetAddress _address; /*** * When you receive a datagram that you expect to be a TFTP packet, you use * this factory method to create the proper TFTPPacket object * encapsulating the data contained in that datagram. This method is the * only way you can instantiate a TFTPPacket derived class from a * datagram. *

* @param datagram The datagram containing a TFTP packet. * @return The TFTPPacket object corresponding to the datagram. * @exception TFTPPacketException If the datagram does not contain a valid * TFTP packet. ***/ public final static TFTPPacket newTFTPPacket(DatagramPacket datagram) throws TFTPPacketException { byte[] data; TFTPPacket packet = null; if (datagram.getLength() < MIN_PACKET_SIZE) throw new TFTPPacketException( "Bad packet. Datagram data length is too short."); data = datagram.getData(); switch (data[1]) { case READ_REQUEST: packet = new TFTPReadRequestPacket(datagram); break; case WRITE_REQUEST: packet = new TFTPWriteRequestPacket(datagram); break; case DATA: packet = new TFTPDataPacket(datagram); break; case ACKNOWLEDGEMENT: packet = new TFTPAckPacket(datagram); break; case ERROR: packet = new TFTPErrorPacket(datagram); break; default: throw new TFTPPacketException( "Bad packet. Invalid TFTP operator code."); } return packet; } /*** * This constructor is not visible outside of the package. It is used * by subclasses within the package to initialize base data. *

* @param type The type of the packet. * @param address The host the packet came from or is going to be sent. * @param port The port the packet came from or is going to be sent. **/ TFTPPacket(int type, InetAddress address, int port) { _type = type; _address = address; _port = port; } /*** * This is an abstract method only available within the package for * implementing efficient datagram transport by elminating buffering. * It takes a datagram as an argument, and a byte buffer in which * to store the raw datagram data. Inside the method, the data * should be set as the datagram's data and the datagram returned. *

* @param datagram The datagram to create. * @param data The buffer to store the packet and to use in the datagram. * @return The datagram argument. ***/ abstract DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data); /*** * Creates a UDP datagram containing all the TFTP packet * data in the proper format. * This is an abstract method, exposed to the programmer in case he * wants to implement his own TFTP client instead of using * the {@link org.apache.commons.net.tftp.TFTPClient} * class. * Under normal circumstances, you should not have a need to call this * method. *

* @return A UDP datagram containing the TFTP packet. ***/ public abstract DatagramPacket newDatagram(); /*** * Returns the type of the packet. *

* @return The type of the packet. ***/ public final int getType() { return _type; } /*** * Returns the address of the host where the packet is going to be sent * or where it came from. *

* @return The type of the packet. ***/ public final InetAddress getAddress() { return _address; } /*** * Returns the port where the packet is going to be sent * or where it came from. *

* @return The port where the packet came from or where it is going. ***/ public final int getPort() { return _port; } /*** Sets the port where the packet is going to be sent. ***/ public final void setPort(int port) { _port = port; } /*** Sets the host address where the packet is going to be sent. ***/ public final void setAddress(InetAddress address) { _address = address; } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTP.java0000644000175000017500000002600110542533103025047 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.io.IOException; import java.io.InterruptedIOException; import java.net.DatagramPacket; import java.net.SocketException; import org.apache.commons.net.DatagramSocketClient; /*** * The TFTP class exposes a set of methods to allow you to deal with the TFTP * protocol directly, in case you want to write your own TFTP client or * server. However, almost every user should only be concerend with * the {@link org.apache.commons.net.DatagramSocketClient#open open() }, * and {@link org.apache.commons.net.DatagramSocketClient#close close() }, * methods. Additionally,the a * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() } * method may be of importance for performance tuning. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. *

*

* @author Daniel F. Savarese * @see org.apache.commons.net.DatagramSocketClient * @see TFTPPacket * @see TFTPPacketException * @see TFTPClient ***/ public class TFTP extends DatagramSocketClient { /*** * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE ***/ public static final int ASCII_MODE = 0; /*** * The netascii transfer mode. Its value is 0. ***/ public static final int NETASCII_MODE = 0; /*** * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE. ***/ public static final int BINARY_MODE = 1; /*** * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE. ***/ public static final int IMAGE_MODE = 1; /*** * The octet transfer mode. Its value is 1. ***/ public static final int OCTET_MODE = 1; /*** * The default number of milliseconds to wait to receive a datagram * before timing out. The default is 5000 milliseconds (5 seconds). ***/ public static final int DEFAULT_TIMEOUT = 5000; /*** * The default TFTP port according to RFC 783 is 69. ***/ public static final int DEFAULT_PORT = 69; /*** * The size to use for TFTP packet buffers. Its 4 plus the * TFTPPacket.SEGMENT_SIZE, i.e. 516. ***/ static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4; /*** A buffer used to accelerate receives in bufferedReceive() ***/ private byte[] __receiveBuffer; /*** A datagram used to minimize memory allocation in bufferedReceive() ***/ private DatagramPacket __receiveDatagram; /*** A datagram used to minimize memory allocation in bufferedSend() ***/ private DatagramPacket __sendDatagram; /*** * A buffer used to accelerate sends in bufferedSend(). * It is left package visible so that TFTPClient may be slightly more * efficient during file sends. It saves the creation of an * additional buffer and prevents a buffer copy in _newDataPcket(). ***/ byte[] _sendBuffer; /*** * Returns the TFTP string representation of a TFTP transfer mode. * Will throw an ArrayIndexOutOfBoundsException if an invalid transfer * mode is specified. *

* @param mode The TFTP transfer mode. One of the MODE constants. * @return The TFTP string representation of the TFTP transfer mode. ***/ public static final String getModeName(int mode) { return TFTPRequestPacket._modeStrings[mode]; } /*** * Creates a TFTP instance with a default timeout of DEFAULT_TIMEOUT, * a null socket, and buffered operations disabled. ***/ public TFTP() { setDefaultTimeout(DEFAULT_TIMEOUT); __receiveBuffer = null; __receiveDatagram = null; } /*** * This method synchronizes a connection by discarding all packets that * may be in the local socket buffer. This method need only be called * when you implement your own TFTP client or server. *

* @exception IOException if an I/O error occurs. ***/ public final void discardPackets() throws IOException { int to; DatagramPacket datagram; datagram = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE); to = getSoTimeout(); setSoTimeout(1); try { while (true) _socket_.receive(datagram); } catch (SocketException e) { // Do nothing. We timed out so we hope we're caught up. } catch (InterruptedIOException e) { // Do nothing. We timed out so we hope we're caught up. } setSoTimeout(to); } /*** * This is a special method to perform a more efficient packet receive. * It should only be used after calling * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps() * initializes a set of buffers used internally that prevent the new * allocation of a DatagramPacket and byte array for each send and receive. * To use these buffers you must call the bufferedReceive() and * bufferedSend() methods instead of send() and receive(). You must * also be certain that you don't manipulate the resulting packet in * such a way that it interferes with future buffered operations. * For example, a TFTPDataPacket received with bufferedReceive() will * have a reference to the internal byte buffer. You must finish using * this data before calling bufferedReceive() again, or else the data * will be overwritten by the the call. *

* @return The TFTPPacket received. * @exception InterruptedIOException If a socket timeout occurs. The * Java documentation claims an InterruptedIOException is thrown * on a DatagramSocket timeout, but in practice we find a * SocketException is thrown. You should catch both to be safe. * @exception SocketException If a socket timeout occurs. The * Java documentation claims an InterruptedIOException is thrown * on a DatagramSocket timeout, but in practice we find a * SocketException is thrown. You should catch both to be safe. * @exception IOException If some other I/O error occurs. * @exception TFTPPacketException If an invalid TFTP packet is received. ***/ public final TFTPPacket bufferedReceive() throws IOException, InterruptedIOException, SocketException, TFTPPacketException { __receiveDatagram.setData(__receiveBuffer); __receiveDatagram.setLength(__receiveBuffer.length); _socket_.receive(__receiveDatagram); return TFTPPacket.newTFTPPacket(__receiveDatagram); } /*** * This is a special method to perform a more efficient packet send. * It should only be used after calling * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps() * initializes a set of buffers used internally that prevent the new * allocation of a DatagramPacket and byte array for each send and receive. * To use these buffers you must call the bufferedReceive() and * bufferedSend() methods instead of send() and receive(). You must * also be certain that you don't manipulate the resulting packet in * such a way that it interferes with future buffered operations. * For example, a TFTPDataPacket received with bufferedReceive() will * have a reference to the internal byte buffer. You must finish using * this data before calling bufferedReceive() again, or else the data * will be overwritten by the the call. *

* @param packet The TFTP packet to send. * @exception IOException If some I/O error occurs. ***/ public final void bufferedSend(TFTPPacket packet) throws IOException { _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer)); } /*** * Initializes the internal buffers. Buffers are used by * {@link #bufferedSend bufferedSend() } and * {@link #bufferedReceive bufferedReceive() }. This * method must be called before calling either one of those two * methods. When you finish using buffered operations, you must * call {@link #endBufferedOps endBufferedOps() }. ***/ public final void beginBufferedOps() { __receiveBuffer = new byte[PACKET_SIZE]; __receiveDatagram = new DatagramPacket(__receiveBuffer, __receiveBuffer.length); _sendBuffer = new byte[PACKET_SIZE]; __sendDatagram = new DatagramPacket(_sendBuffer, _sendBuffer.length); } /*** * Releases the resources used to perform buffered sends and receives. ***/ public final void endBufferedOps() { __receiveBuffer = null; __receiveDatagram = null; _sendBuffer = null; __sendDatagram = null; } /*** * Sends a TFTP packet to its destination. *

* @param packet The TFTP packet to send. * @exception IOException If some I/O error occurs. ***/ public final void send(TFTPPacket packet) throws IOException { _socket_.send(packet.newDatagram()); } /*** * Receives a TFTPPacket. *

* @return The TFTPPacket received. * @exception InterruptedIOException If a socket timeout occurs. The * Java documentation claims an InterruptedIOException is thrown * on a DatagramSocket timeout, but in practice we find a * SocketException is thrown. You should catch both to be safe. * @exception SocketException If a socket timeout occurs. The * Java documentation claims an InterruptedIOException is thrown * on a DatagramSocket timeout, but in practice we find a * SocketException is thrown. You should catch both to be safe. * @exception IOException If some other I/O error occurs. * @exception TFTPPacketException If an invalid TFTP packet is received. ***/ public final TFTPPacket receive() throws IOException, InterruptedIOException, SocketException, TFTPPacketException { DatagramPacket packet; packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE); _socket_.receive(packet); return TFTPPacket.newTFTPPacket(packet); } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPAckPacket.java0000644000175000017500000001241310766271714026637 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * A final class derived from TFTPPacket definiing the TFTP Acknowledgement * packet type. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTPPacketException * @see TFTP ***/ public final class TFTPAckPacket extends TFTPPacket { /*** The block number being acknowledged by the packet. ***/ int _blockNumber; /*** * Creates an acknowledgment packet to be sent to a host at a given port * acknowledging receipt of a block. *

* @param destination The host to which the packet is going to be sent. * @param port The port to which the packet is going to be sent. * @param blockNumber The block number being acknowledged. ***/ public TFTPAckPacket(InetAddress destination, int port, int blockNumber) { super(TFTPPacket.ACKNOWLEDGEMENT, destination, port); _blockNumber = blockNumber; } /*** * Creates an acknowledgement packet based from a received * datagram. Assumes the datagram is at least length 4, else an * ArrayIndexOutOfBoundsException may be thrown. *

* @param datagram The datagram containing the received acknowledgement. * @throws TFTPPacketException If the datagram isn't a valid TFTP * acknowledgement packet. ***/ TFTPAckPacket(DatagramPacket datagram) throws TFTPPacketException { super(TFTPPacket.ACKNOWLEDGEMENT, datagram.getAddress(), datagram.getPort()); byte[] data; data = datagram.getData(); if (getType() != data[1]) throw new TFTPPacketException("TFTP operator code does not match type."); _blockNumber = (((data[2] & 0xff) << 8) | (data[3] & 0xff)); } /*** * This is a method only available within the package for * implementing efficient datagram transport by elminating buffering. * It takes a datagram as an argument, and a byte buffer in which * to store the raw datagram data. Inside the method, the data * is set as the datagram's data and the datagram returned. *

* @param datagram The datagram to create. * @param data The buffer to store the packet and to use in the datagram. * @return The datagram argument. ***/ @Override DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) { data[0] = 0; data[1] = (byte)_type; data[2] = (byte)((_blockNumber & 0xffff) >> 8); data[3] = (byte)(_blockNumber & 0xff); datagram.setAddress(_address); datagram.setPort(_port); datagram.setData(data); datagram.setLength(4); return datagram; } /*** * Creates a UDP datagram containing all the TFTP * acknowledgement packet data in the proper format. * This is a method exposed to the programmer in case he * wants to implement his own TFTP client instead of using * the {@link org.apache.commons.net.tftp.TFTPClient} * class. Under normal circumstances, you should not have a need to call this * method. *

* @return A UDP datagram containing the TFTP acknowledgement packet. ***/ @Override public DatagramPacket newDatagram() { byte[] data; data = new byte[4]; data[0] = 0; data[1] = (byte)_type; data[2] = (byte)((_blockNumber & 0xffff) >> 8); data[3] = (byte)(_blockNumber & 0xff); return new DatagramPacket(data, data.length, _address, _port); } /*** * Returns the block number of the acknowledgement. *

* @return The block number of the acknowledgement. ***/ public int getBlockNumber() { return _blockNumber; } /*** Sets the block number of the acknowledgement. ***/ public void setBlockNumber(int blockNumber) { _blockNumber = blockNumber; } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java0000644000175000017500000000605010542533103030565 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * A class derived from TFTPRequestPacket definiing a TFTP write request * packet type. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTPRequestPacket * @see TFTPPacketException * @see TFTP ***/ public final class TFTPWriteRequestPacket extends TFTPRequestPacket { /*** * Creates a write request packet to be sent to a host at a * given port with a filename and transfer mode request. *

* @param destination The host to which the packet is going to be sent. * @param port The port to which the packet is going to be sent. * @param filename The requested filename. * @param mode The requested transfer mode. This should be on of the TFTP * class MODE constants (e.g., TFTP.NETASCII_MODE). ***/ public TFTPWriteRequestPacket(InetAddress destination, int port, String filename, int mode) { super(destination, port, TFTPPacket.WRITE_REQUEST, filename, mode); } /*** * Creates a write request packet of based on a received * datagram and assumes the datagram has already been identified as a * write request. Assumes the datagram is at least length 4, else an * ArrayIndexOutOfBoundsException may be thrown. *

* @param datagram The datagram containing the received request. * @throws TFTPPacketException If the datagram isn't a valid TFTP * request packet. ***/ TFTPWriteRequestPacket(DatagramPacket datagram) throws TFTPPacketException { super(TFTPPacket.WRITE_REQUEST, datagram); } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPClient.java0000644000175000017500000006020511445714020026214 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import org.apache.commons.net.io.FromNetASCIIOutputStream; import org.apache.commons.net.io.ToNetASCIIInputStream; /*** * The TFTPClient class encapsulates all the aspects of the TFTP protocol * necessary to receive and send files through TFTP. It is derived from * the {@link org.apache.commons.net.tftp.TFTP} because * it is more convenient than using aggregation, and as a result exposes * the same set of methods to allow you to deal with the TFTP protocol * directly. However, almost every user should only be concerend with the * the {@link org.apache.commons.net.DatagramSocketClient#open open() }, * {@link org.apache.commons.net.DatagramSocketClient#close close() }, * {@link #sendFile sendFile() }, and * {@link #receiveFile receiveFile() } methods. Additionally, the * {@link #setMaxTimeouts setMaxTimeouts() } and * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() } * methods may be of importance for performance * tuning. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. *

*

* @author Daniel F. Savarese * @see TFTP * @see TFTPPacket * @see TFTPPacketException ***/ public class TFTPClient extends TFTP { /*** * The default number of times a receive attempt is allowed to timeout * before ending attempts to retry the receive and failing. The default * is 5 timeouts. ***/ public static final int DEFAULT_MAX_TIMEOUTS = 5; /*** The maximum number of timeouts allowed before failing. ***/ private int __maxTimeouts; /*** * Creates a TFTPClient instance with a default timeout of DEFAULT_TIMEOUT, * maximum timeouts value of DEFAULT_MAX_TIMEOUTS, a null socket, * and buffered operations disabled. ***/ public TFTPClient() { __maxTimeouts = DEFAULT_MAX_TIMEOUTS; } /*** * Sets the maximum number of times a receive attempt is allowed to * timeout during a receiveFile() or sendFile() operation before ending * attempts to retry the receive and failing. * The default is DEFAULT_MAX_TIMEOUTS. *

* @param numTimeouts The maximum number of timeouts to allow. Values * less than 1 should not be used, but if they are, they are * treated as 1. ***/ public void setMaxTimeouts(int numTimeouts) { if (numTimeouts < 1) __maxTimeouts = 1; else __maxTimeouts = numTimeouts; } /*** * Returns the maximum number of times a receive attempt is allowed to * timeout before ending attempts to retry the receive and failing. *

* @return The maximum number of timeouts allowed. ***/ public int getMaxTimeouts() { return __maxTimeouts; } /*** * Requests a named file from a remote host, writes the * file to an OutputStream, closes the connection, and returns the number * of bytes read. A local UDP socket must first be created by * {@link org.apache.commons.net.DatagramSocketClient#open open()} before * invoking this method. This method will not close the OutputStream * containing the file; you must close it after the method invocation. *

* @param filename The name of the file to receive. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param output The OutputStream to which the file should be written. * @param host The remote host serving the file. * @param port The port number of the remote TFTP server. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. ***/ public int receiveFile(String filename, int mode, OutputStream output, InetAddress host, int port) throws IOException { int bytesRead, timeouts, lastBlock, block, hostPort, dataLength; TFTPPacket sent, received = null; TFTPErrorPacket error; TFTPDataPacket data; TFTPAckPacket ack = new TFTPAckPacket(host, port, 0); beginBufferedOps(); dataLength = lastBlock = hostPort = bytesRead = 0; block = 1; if (mode == TFTP.ASCII_MODE) output = new FromNetASCIIOutputStream(output); sent = new TFTPReadRequestPacket(host, port, filename, mode); _sendPacket: do { bufferedSend(sent); _receivePacket: while (true) { timeouts = 0; while (timeouts < __maxTimeouts) { try { received = bufferedReceive(); break; } catch (SocketException e) { if (++timeouts >= __maxTimeouts) { endBufferedOps(); throw new IOException("Connection timed out."); } continue; } catch (InterruptedIOException e) { if (++timeouts >= __maxTimeouts) { endBufferedOps(); throw new IOException("Connection timed out."); } continue; } catch (TFTPPacketException e) { endBufferedOps(); throw new IOException("Bad packet: " + e.getMessage()); } } // The first time we receive we get the port number and // answering host address (for hosts with multiple IPs) if (lastBlock == 0) { hostPort = received.getPort(); ack.setPort(hostPort); if(!host.equals(received.getAddress())) { host = received.getAddress(); ack.setAddress(host); sent.setAddress(host); } } // Comply with RFC 783 indication that an error acknowledgement // should be sent to originator if unexpected TID or host. if (host.equals(received.getAddress()) && received.getPort() == hostPort) { switch (received.getType()) { case TFTPPacket.ERROR: error = (TFTPErrorPacket)received; endBufferedOps(); throw new IOException("Error code " + error.getError() + " received: " + error.getMessage()); case TFTPPacket.DATA: data = (TFTPDataPacket)received; dataLength = data.getDataLength(); lastBlock = data.getBlockNumber(); if (lastBlock == block) { try { output.write(data.getData(), data.getDataOffset(), dataLength); } catch (IOException e) { error = new TFTPErrorPacket(host, hostPort, TFTPErrorPacket.OUT_OF_SPACE, "File write failed."); bufferedSend(error); endBufferedOps(); throw e; } ++block; if (block > 65535) { // wrap the block number block = 0; } break _receivePacket; } else { discardPackets(); if (lastBlock == (block == 0 ? 65535 : (block - 1))) continue _sendPacket; // Resend last acknowledgement. continue _receivePacket; // Start fetching packets again. } //break; default: endBufferedOps(); throw new IOException("Received unexpected packet type."); } } else { error = new TFTPErrorPacket(received.getAddress(), received.getPort(), TFTPErrorPacket.UNKNOWN_TID, "Unexpected host or port."); bufferedSend(error); continue _sendPacket; } // We should never get here, but this is a safety to avoid // infinite loop. If only Java had the goto statement. //break; } ack.setBlockNumber(lastBlock); sent = ack; bytesRead += dataLength; } // First data packet less than 512 bytes signals end of stream. while (dataLength == TFTPPacket.SEGMENT_SIZE); bufferedSend(sent); endBufferedOps(); return bytesRead; } /*** * Requests a named file from a remote host, writes the * file to an OutputStream, closes the connection, and returns the number * of bytes read. A local UDP socket must first be created by * {@link org.apache.commons.net.DatagramSocketClient#open open()} before * invoking this method. This method will not close the OutputStream * containing the file; you must close it after the method invocation. *

* @param filename The name of the file to receive. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param output The OutputStream to which the file should be written. * @param hostname The name of the remote host serving the file. * @param port The port number of the remote TFTP server. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. * @exception UnknownHostException If the hostname cannot be resolved. ***/ public int receiveFile(String filename, int mode, OutputStream output, String hostname, int port) throws UnknownHostException, IOException { return receiveFile(filename, mode, output, InetAddress.getByName(hostname), port); } /*** * Same as calling receiveFile(filename, mode, output, host, TFTP.DEFAULT_PORT). * * @param filename The name of the file to receive. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param output The OutputStream to which the file should be written. * @param host The remote host serving the file. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. ***/ public int receiveFile(String filename, int mode, OutputStream output, InetAddress host) throws IOException { return receiveFile(filename, mode, output, host, DEFAULT_PORT); } /*** * Same as calling receiveFile(filename, mode, output, hostname, TFTP.DEFAULT_PORT). * * @param filename The name of the file to receive. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param output The OutputStream to which the file should be written. * @param hostname The name of the remote host serving the file. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. * @exception UnknownHostException If the hostname cannot be resolved. ***/ public int receiveFile(String filename, int mode, OutputStream output, String hostname) throws UnknownHostException, IOException { return receiveFile(filename, mode, output, InetAddress.getByName(hostname), DEFAULT_PORT); } /*** * Requests to send a file to a remote host, reads the file from an * InputStream, sends the file to the remote host, and closes the * connection. A local UDP socket must first be created by * {@link org.apache.commons.net.DatagramSocketClient#open open()} before * invoking this method. This method will not close the InputStream * containing the file; you must close it after the method invocation. *

* @param filename The name the remote server should use when creating * the file on its file system. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param host The remote host receiving the file. * @param port The port number of the remote TFTP server. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. ***/ public void sendFile(String filename, int mode, InputStream input, InetAddress host, int port) throws IOException { int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset, totalThisPacket; TFTPPacket sent, received = null; TFTPErrorPacket error; TFTPDataPacket data = new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0); TFTPAckPacket ack; boolean justStarted = true; beginBufferedOps(); dataLength = lastBlock = hostPort = bytesRead = totalThisPacket = 0; block = 0; boolean lastAckWait = false; if (mode == TFTP.ASCII_MODE) input = new ToNetASCIIInputStream(input); sent = new TFTPWriteRequestPacket(host, port, filename, mode); _sendPacket: do { // first time: block is 0, lastBlock is 0, send a request packet. // subsequent: block is integer starting at 1, send data packet. bufferedSend(sent); // this is trying to receive an ACK _receivePacket: while (true) { timeouts = 0; while (timeouts < __maxTimeouts) { try { received = bufferedReceive(); break; } catch (SocketException e) { if (++timeouts >= __maxTimeouts) { endBufferedOps(); throw new IOException("Connection timed out."); } continue; } catch (InterruptedIOException e) { if (++timeouts >= __maxTimeouts) { endBufferedOps(); throw new IOException("Connection timed out."); } continue; } catch (TFTPPacketException e) { endBufferedOps(); throw new IOException("Bad packet: " + e.getMessage()); } } // end of while loop over tries to receive // The first time we receive we get the port number and // answering host address (for hosts with multiple IPs) if (justStarted) { justStarted = false; hostPort = received.getPort(); data.setPort(hostPort); if(!host.equals(received.getAddress())) { host = received.getAddress(); data.setAddress(host); sent.setAddress(host); } } // Comply with RFC 783 indication that an error acknowledgement // should be sent to originator if unexpected TID or host. if (host.equals(received.getAddress()) && received.getPort() == hostPort) { switch (received.getType()) { case TFTPPacket.ERROR: error = (TFTPErrorPacket)received; endBufferedOps(); throw new IOException("Error code " + error.getError() + " received: " + error.getMessage()); case TFTPPacket.ACKNOWLEDGEMENT: ack = (TFTPAckPacket)received; lastBlock = ack.getBlockNumber(); if (lastBlock == block) { ++block; if (block > 65535) { // wrap the block number block = 0; } if (lastAckWait) { break _sendPacket; } else { break _receivePacket; } } else { discardPackets(); if (lastBlock == (block == 0 ? 65535 : (block - 1))) continue _sendPacket; // Resend last acknowledgement. continue _receivePacket; // Start fetching packets again. } //break; default: endBufferedOps(); throw new IOException("Received unexpected packet type."); } } else { error = new TFTPErrorPacket(received.getAddress(), received.getPort(), TFTPErrorPacket.UNKNOWN_TID, "Unexpected host or port."); bufferedSend(error); continue _sendPacket; } // We should never get here, but this is a safety to avoid // infinite loop. If only Java had the goto statement. //break; } // OK, we have just gotten ACK about the last data we sent. Make another // and send it dataLength = TFTPPacket.SEGMENT_SIZE; offset = 4; totalThisPacket = 0; while (dataLength > 0 && (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0) { offset += bytesRead; dataLength -= bytesRead; totalThisPacket += bytesRead; } if( totalThisPacket < TFTPPacket.SEGMENT_SIZE ) { /* this will be our last packet -- send, wait for ack, stop */ lastAckWait = true; } data.setBlockNumber(block); data.setData(_sendBuffer, 4, totalThisPacket); sent = data; } while ( totalThisPacket > 0 || lastAckWait ); // Note: this was looping while dataLength == 0 || lastAckWait, // which was discarding the last packet if it was not full size // Should send the packet. endBufferedOps(); } /*** * Requests to send a file to a remote host, reads the file from an * InputStream, sends the file to the remote host, and closes the * connection. A local UDP socket must first be created by * {@link org.apache.commons.net.DatagramSocketClient#open open()} before * invoking this method. This method will not close the InputStream * containing the file; you must close it after the method invocation. *

* @param filename The name the remote server should use when creating * the file on its file system. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param hostname The name of the remote host receiving the file. * @param port The port number of the remote TFTP server. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. * @exception UnknownHostException If the hostname cannot be resolved. ***/ public void sendFile(String filename, int mode, InputStream input, String hostname, int port) throws UnknownHostException, IOException { sendFile(filename, mode, input, InetAddress.getByName(hostname), port); } /*** * Same as calling sendFile(filename, mode, input, host, TFTP.DEFAULT_PORT). * * @param filename The name the remote server should use when creating * the file on its file system. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param host The name of the remote host receiving the file. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. * @exception UnknownHostException If the hostname cannot be resolved. ***/ public void sendFile(String filename, int mode, InputStream input, InetAddress host) throws IOException { sendFile(filename, mode, input, host, DEFAULT_PORT); } /*** * Same as calling sendFile(filename, mode, input, hostname, TFTP.DEFAULT_PORT). * * @param filename The name the remote server should use when creating * the file on its file system. * @param mode The TFTP mode of the transfer (one of the MODE constants). * @param hostname The name of the remote host receiving the file. * @exception IOException If an I/O error occurs. The nature of the * error will be reported in the message. * @exception UnknownHostException If the hostname cannot be resolved. ***/ public void sendFile(String filename, int mode, InputStream input, String hostname) throws UnknownHostException, IOException { sendFile(filename, mode, input, InetAddress.getByName(hostname), DEFAULT_PORT); } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPPacketException.java0000644000175000017500000000350710542533103030064 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; /*** * A class used to signify the occurrence of an error in the creation of * a TFTP packet. It is not declared final so that it may be subclassed * to identify more specific errors. You would only want to do this if * you were building your own TFTP client or server on top of the * {@link org.apache.commons.net.tftp.TFTP} * class if you * wanted more functionality than the * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods provide. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTP ***/ public class TFTPPacketException extends Exception { /*** * Simply calls the corresponding constructor of its superclass. ***/ public TFTPPacketException() { super(); } /*** * Simply calls the corresponding constructor of its superclass. ***/ public TFTPPacketException(String message) { super(message); } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPDataPacket.java0000644000175000017500000001771210766271714027021 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * A final class derived from TFTPPacket definiing the TFTP Data * packet type. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTPPacketException * @see TFTP ***/ public final class TFTPDataPacket extends TFTPPacket { /*** The maximum number of bytes in a TFTP data packet (512) ***/ public static final int MAX_DATA_LENGTH = 512; /*** The minimum number of bytes in a TFTP data packet (0) ***/ public static final int MIN_DATA_LENGTH = 0; /*** The block number of the packet. ***/ int _blockNumber; /*** The length of the data. ***/ int _length; /*** The offset into the _data array at which the data begins. ***/ int _offset; /*** The data stored in the packet. ***/ byte[] _data; /*** * Creates a data packet to be sent to a host at a given port * with a given block number. The actual data to be sent is passed as * an array, an offset, and a length. The offset is the offset into * the byte array where the data starts. The length is the length of * the data. If the length is greater than MAX_DATA_LENGTH, it is * truncated. *

* @param destination The host to which the packet is going to be sent. * @param port The port to which the packet is going to be sent. * @param blockNumber The block number of the data. * @param data The byte array containing the data. * @param offset The offset into the array where the data starts. * @param length The length of the data. ***/ public TFTPDataPacket(InetAddress destination, int port, int blockNumber, byte[] data, int offset, int length) { super(TFTPPacket.DATA, destination, port); _blockNumber = blockNumber; _data = data; _offset = offset; if (length > MAX_DATA_LENGTH) _length = MAX_DATA_LENGTH; else _length = length; } public TFTPDataPacket(InetAddress destination, int port, int blockNumber, byte[] data) { this(destination, port, blockNumber, data, 0, data.length); } /*** * Creates a data packet based from a received * datagram. Assumes the datagram is at least length 4, else an * ArrayIndexOutOfBoundsException may be thrown. *

* @param datagram The datagram containing the received data. * @throws TFTPPacketException If the datagram isn't a valid TFTP * data packet. ***/ TFTPDataPacket(DatagramPacket datagram) throws TFTPPacketException { super(TFTPPacket.DATA, datagram.getAddress(), datagram.getPort()); _data = datagram.getData(); _offset = 4; if (getType() != _data[1]) throw new TFTPPacketException("TFTP operator code does not match type."); _blockNumber = (((_data[2] & 0xff) << 8) | (_data[3] & 0xff)); _length = datagram.getLength() - 4; if (_length > MAX_DATA_LENGTH) _length = MAX_DATA_LENGTH; } /*** * This is a method only available within the package for * implementing efficient datagram transport by elminating buffering. * It takes a datagram as an argument, and a byte buffer in which * to store the raw datagram data. Inside the method, the data * is set as the datagram's data and the datagram returned. *

* @param datagram The datagram to create. * @param data The buffer to store the packet and to use in the datagram. * @return The datagram argument. ***/ @Override DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) { data[0] = 0; data[1] = (byte)_type; data[2] = (byte)((_blockNumber & 0xffff) >> 8); data[3] = (byte)(_blockNumber & 0xff); // Doublecheck we're not the same if (data != _data) System.arraycopy(_data, _offset, data, 4, _length); datagram.setAddress(_address); datagram.setPort(_port); datagram.setData(data); datagram.setLength(_length + 4); return datagram; } /*** * Creates a UDP datagram containing all the TFTP * data packet data in the proper format. * This is a method exposed to the programmer in case he * wants to implement his own TFTP client instead of using * the {@link org.apache.commons.net.tftp.TFTPClient} * class. * Under normal circumstances, you should not have a need to call this * method. *

* @return A UDP datagram containing the TFTP data packet. ***/ @Override public DatagramPacket newDatagram() { byte[] data; data = new byte[_length + 4]; data[0] = 0; data[1] = (byte)_type; data[2] = (byte)((_blockNumber & 0xffff) >> 8); data[3] = (byte)(_blockNumber & 0xff); System.arraycopy(_data, _offset, data, 4, _length); return new DatagramPacket(data, _length + 4, _address, _port); } /*** * Returns the block number of the data packet. *

* @return The block number of the data packet. ***/ public int getBlockNumber() { return _blockNumber; } /*** Sets the block number of the data packet. ***/ public void setBlockNumber(int blockNumber) { _blockNumber = blockNumber; } /*** * Sets the data for the data packet. *

* @param data The byte array containing the data. * @param offset The offset into the array where the data starts. * @param length The length of the data. ***/ public void setData(byte[] data, int offset, int length) { _data = data; _offset = offset; _length = length; if (length > MAX_DATA_LENGTH) _length = MAX_DATA_LENGTH; else _length = length; } /*** * Returns the length of the data part of the data packet. *

* @return The length of the data part of the data packet. ***/ public int getDataLength() { return _length; } /*** * Returns the offset into the byte array where the packet data actually * starts. *

* @return The offset into the byte array where the packet data actually * starts. ***/ public int getDataOffset() { return _offset; } /*** * Returns the byte array containing the packet data. *

* @return The byte array containing the packet data. ***/ public byte[] getData() { return _data; } } commons-net-2.2/src/main/java/org/apache/commons/net/tftp/TFTPErrorPacket.java0000644000175000017500000001601111354512541027216 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.net.DatagramPacket; import java.net.InetAddress; /*** * A final class derived from TFTPPacket definiing the TFTP Error * packet type. *

* Details regarding the TFTP protocol and the format of TFTP packets can * be found in RFC 783. But the point of these classes is to keep you * from having to worry about the internals. Additionally, only very * few people should have to care about any of the TFTPPacket classes * or derived classes. Almost all users should only be concerned with the * {@link org.apache.commons.net.tftp.TFTPClient} class * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} * and * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} * methods. *

*

* @author Daniel F. Savarese * @see TFTPPacket * @see TFTPPacketException * @see TFTP ***/ public final class TFTPErrorPacket extends TFTPPacket { /*** The undefined error code according to RFC 783, value 0. ***/ public static final int UNDEFINED = 0; /*** The file not found error code according to RFC 783, value 1. ***/ public static final int FILE_NOT_FOUND = 1; /*** The access violation error code according to RFC 783, value 2. ***/ public static final int ACCESS_VIOLATION = 2; /*** The disk full error code according to RFC 783, value 3. ***/ public static final int OUT_OF_SPACE = 3; /*** * The illegal TFTP operation error code according to RFC 783, value 4. ***/ public static final int ILLEGAL_OPERATION = 4; /*** The unknown transfer id error code according to RFC 783, value 5. ***/ public static final int UNKNOWN_TID = 5; /*** The file already exists error code according to RFC 783, value 6. ***/ public static final int FILE_EXISTS = 6; /*** The no such user error code according to RFC 783, value 7. ***/ public static final int NO_SUCH_USER = 7; /*** The error code of this packet. ***/ int _error; /*** The error message of this packet. ***/ String _message; /*** * Creates an error packet to be sent to a host at a given port * with an error code and error message. *

* @param destination The host to which the packet is going to be sent. * @param port The port to which the packet is going to be sent. * @param error The error code of the packet. * @param message The error message of the packet. ***/ public TFTPErrorPacket(InetAddress destination, int port, int error, String message) { super(TFTPPacket.ERROR, destination, port); _error = error; _message = message; } /*** * Creates an error packet based from a received * datagram. Assumes the datagram is at least length 4, else an * ArrayIndexOutOfBoundsException may be thrown. *

* @param datagram The datagram containing the received error. * @throws TFTPPacketException If the datagram isn't a valid TFTP * error packet. ***/ TFTPErrorPacket(DatagramPacket datagram) throws TFTPPacketException { super(TFTPPacket.ERROR, datagram.getAddress(), datagram.getPort()); int index, length; byte[] data; StringBuilder buffer; data = datagram.getData(); length = datagram.getLength(); if (getType() != data[1]) throw new TFTPPacketException("TFTP operator code does not match type."); _error = (((data[2] & 0xff) << 8) | (data[3] & 0xff)); if (length < 5) throw new TFTPPacketException("Bad error packet. No message."); index = 4; buffer = new StringBuilder(); while (index < length && data[index] != 0) { buffer.append((char)data[index]); ++index; } _message = buffer.toString(); } /*** * This is a method only available within the package for * implementing efficient datagram transport by elminating buffering. * It takes a datagram as an argument, and a byte buffer in which * to store the raw datagram data. Inside the method, the data * is set as the datagram's data and the datagram returned. *

* @param datagram The datagram to create. * @param data The buffer to store the packet and to use in the datagram. * @return The datagram argument. ***/ @Override DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) { int length; length = _message.length(); data[0] = 0; data[1] = (byte)_type; data[2] = (byte)((_error & 0xffff) >> 8); data[3] = (byte)(_error & 0xff); System.arraycopy(_message.getBytes(), 0, data, 4, length); data[length + 4] = 0; datagram.setAddress(_address); datagram.setPort(_port); datagram.setData(data); datagram.setLength(length + 4); return datagram; } /*** * Creates a UDP datagram containing all the TFTP * error packet data in the proper format. * This is a method exposed to the programmer in case he * wants to implement his own TFTP client instead of using * the {@link org.apache.commons.net.tftp.TFTPClient} * class. * Under normal circumstances, you should not have a need to call this * method. *

* @return A UDP datagram containing the TFTP error packet. ***/ @Override public DatagramPacket newDatagram() { byte[] data; int length; length = _message.length(); data = new byte[length + 5]; data[0] = 0; data[1] = (byte)_type; data[2] = (byte)((_error & 0xffff) >> 8); data[3] = (byte)(_error & 0xff); System.arraycopy(_message.getBytes(), 0, data, 4, length); data[length + 4] = 0; return new DatagramPacket(data, data.length, _address, _port); } /*** * Returns the error code of the packet. *

* @return The error code of the packet. ***/ public int getError() { return _error; } /*** * Returns the error message of the packet. *

* @return The error message of the packet. ***/ public String getMessage() { return _message; } } commons-net-2.2/src/main/java/org/apache/commons/net/PrintCommandListener.java0000644000175000017500000000327111416072763027435 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.io.PrintWriter; import org.apache.commons.net.ProtocolCommandEvent; import org.apache.commons.net.ProtocolCommandListener; /*** * This is a support class for some of the example programs. It is * a sample implementation of the ProtocolCommandListener interface * which just prints out to a specified stream all command/reply traffic. *

* * @since 2.0 ***/ public class PrintCommandListener implements ProtocolCommandListener { private final PrintWriter __writer; public PrintCommandListener(PrintWriter writer) { __writer = writer; } public void protocolCommandSent(ProtocolCommandEvent event) { __writer.print(event.getMessage()); __writer.flush(); } public void protocolReplyReceived(ProtocolCommandEvent event) { __writer.print(event.getMessage()); __writer.flush(); } } commons-net-2.2/src/main/java/org/apache/commons/net/pop3/0000755000175000017500000000000011617452466023354 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/pop3/POP3Command.java0000644000175000017500000000467010542533103026226 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; /*** * POP3Command stores POP3 command code constants. *

*

* @author Daniel F. Savarese ***/ public final class POP3Command { /*** Send user name. ***/ public static final int USER = 0; /*** Send password. ***/ public static final int PASS = 1; /*** Quit session. ***/ public static final int QUIT = 2; /*** Get status. ***/ public static final int STAT = 3; /*** List message(s). ***/ public static final int LIST = 4; /*** Retrieve message(s). ***/ public static final int RETR = 5; /*** Delete message(s). ***/ public static final int DELE = 6; /*** No operation. Used as a session keepalive. ***/ public static final int NOOP = 7; /*** Reset session. ***/ public static final int RSET = 8; /*** Authorization. ***/ public static final int APOP = 9; /*** Retrieve top number lines from message. ***/ public static final int TOP = 10; /*** List unique message identifier(s). ***/ public static final int UIDL = 11; static final String[] _commands = { "USER", "PASS", "QUIT", "STAT", "LIST", "RETR", "DELE", "NOOP", "RSET", "APOP", "TOP", "UIDL" }; // Cannot be instantiated. private POP3Command() {} /*** * Get the POP3 protocol string command corresponding to a command code. *

* @return The POP3 protocol string command corresponding to a command code. ***/ public static final String getCommand(int command) { return _commands[command]; } } commons-net-2.2/src/main/java/org/apache/commons/net/pop3/POP3MessageInfo.java0000644000175000017500000000550311416072763027057 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; /*** * POP3MessageInfo is used to return information about messages stored on * a POP3 server. Its fields are used to mean slightly different things * depending on the information being returned. *

* In response to a status command, number * contains the number of messages in the mailbox, size * contains the size of the mailbox in bytes, and identifier * is null. *

* In response to a message listings, number * contains the message number, size contains the * size of the message in bytes, and identifier is null. *

* In response to unique identifier listings, number contains * the message number, size is undefined, and * identifier contains the message's unique identifier. *

*

* @author Daniel F. Savarese ***/ public final class POP3MessageInfo { // TODO - make these fields final? They are all set on construction public int number; public int size; public String identifier; /*** * Creates a POP3MessageInfo instance with number and * size set to 0, and identifier set to * null. ***/ public POP3MessageInfo() { number = size = 0; identifier = null; } /*** * Creates a POP3MessageInfo instance with number set * to num , size set to octets , * and identifier set to null. ***/ public POP3MessageInfo(int num, int octets) { number = num; size = octets; identifier = null; } /*** * Creates a POP3MessageInfo instance with number set * to num , size undefined, * and identifier set to uid. ***/ public POP3MessageInfo(int num, String uid) { number = num; size = -1; identifier = uid; } } commons-net-2.2/src/main/java/org/apache/commons/net/pop3/POP3Client.java0000644000175000017500000005165011354512541026073 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; import java.io.IOException; import java.io.Reader; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Enumeration; import java.util.StringTokenizer; import org.apache.commons.net.io.DotTerminatedMessageReader; /*** * The POP3Client class implements the client side of the Internet POP3 * Protocol defined in RFC 1939. All commands are supported, including * the APOP command which requires MD5 encryption. See RFC 1939 for * more details on the POP3 protocol. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @see POP3MessageInfo * @see org.apache.commons.net.io.DotTerminatedMessageReader * @see org.apache.commons.net.MalformedServerReplyException ***/ public class POP3Client extends POP3 { private static POP3MessageInfo __parseStatus(String line) { int num, size; StringTokenizer tokenizer; tokenizer = new StringTokenizer(line); if (!tokenizer.hasMoreElements()) return null; num = size = 0; try { num = Integer.parseInt(tokenizer.nextToken()); if (!tokenizer.hasMoreElements()) return null; size = Integer.parseInt(tokenizer.nextToken()); } catch (NumberFormatException e) { return null; } return new POP3MessageInfo(num, size); } private static POP3MessageInfo __parseUID(String line) { int num; StringTokenizer tokenizer; tokenizer = new StringTokenizer(line); if (!tokenizer.hasMoreElements()) return null; num = 0; try { num = Integer.parseInt(tokenizer.nextToken()); if (!tokenizer.hasMoreElements()) return null; line = tokenizer.nextToken(); } catch (NumberFormatException e) { return null; } return new POP3MessageInfo(num, line); } /*** * Login to the POP3 server with the given username and password. You * must first connect to the server with * {@link org.apache.commons.net.SocketClient#connect connect } * before attempting to login. A login attempt is only valid if * the client is in the * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE } * . After logging in, the client enters the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . *

* @param username The account name being logged in to. * @param password The plain text password of the account. * @return True if the login attempt was successful, false if not. * @exception IOException If a network I/O error occurs in the process of * logging in. ***/ public boolean login(String username, String password) throws IOException { if (getState() != AUTHORIZATION_STATE) return false; if (sendCommand(POP3Command.USER, username) != POP3Reply.OK) return false; if (sendCommand(POP3Command.PASS, password) != POP3Reply.OK) return false; setState(TRANSACTION_STATE); return true; } /*** * Login to the POP3 server with the given username and authentication * information. Use this method when connecting to a server requiring * authentication using the APOP command. Because the timestamp * produced in the greeting banner varies from server to server, it is * not possible to consistently extract the information. Therefore, * after connecting to the server, you must call * {@link org.apache.commons.net.pop3.POP3#getReplyString getReplyString } * and parse out the timestamp information yourself. *

* You must first connect to the server with * {@link org.apache.commons.net.SocketClient#connect connect } * before attempting to login. A login attempt is only valid if * the client is in the * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE } * . After logging in, the client enters the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . After connecting, you must parse out the * server specific information to use as a timestamp, and pass that * information to this method. The secret is a shared secret known * to you and the server. See RFC 1939 for more details regarding * the APOP command. *

* @param username The account name being logged in to. * @param timestamp The timestamp string to combine with the secret. * @param secret The shared secret which produces the MD5 digest when * combined with the timestamp. * @return True if the login attempt was successful, false if not. * @exception IOException If a network I/O error occurs in the process of * logging in. * @exception NoSuchAlgorithmException If the MD5 encryption algorithm * cannot be instantiated by the Java runtime system. ***/ public boolean login(String username, String timestamp, String secret) throws IOException, NoSuchAlgorithmException { int i; byte[] digest; StringBuilder buffer, digestBuffer; MessageDigest md5; if (getState() != AUTHORIZATION_STATE) return false; md5 = MessageDigest.getInstance("MD5"); timestamp += secret; digest = md5.digest(timestamp.getBytes()); digestBuffer = new StringBuilder(128); for (i = 0; i < digest.length; i++) digestBuffer.append(Integer.toHexString(digest[i] & 0xff)); buffer = new StringBuilder(256); buffer.append(username); buffer.append(' '); buffer.append(digestBuffer.toString()); if (sendCommand(POP3Command.APOP, buffer.toString()) != POP3Reply.OK) return false; setState(TRANSACTION_STATE); return true; } /*** * Logout of the POP3 server. To fully disconnect from the server * you must call * {@link org.apache.commons.net.pop3.POP3#disconnect disconnect }. * A logout attempt is valid in any state. If * the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * , it enters the * {@link org.apache.commons.net.pop3.POP3#UPDATE_STATE UPDATE_STATE } * on a successful logout. *

* @return True if the logout attempt was successful, false if not. * @exception IOException If a network I/O error occurs in the process * of logging out. ***/ public boolean logout() throws IOException { if (getState() == TRANSACTION_STATE) setState(UPDATE_STATE); sendCommand(POP3Command.QUIT); return (_replyCode == POP3Reply.OK); } /*** * Send a NOOP command to the POP3 server. This is useful for keeping * a connection alive since most POP3 servers will timeout after 10 * minutes of inactivity. A noop attempt will only succeed if * the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . *

* @return True if the noop attempt was successful, false if not. * @exception IOException If a network I/O error occurs in the process of * sending the NOOP command. ***/ public boolean noop() throws IOException { if (getState() == TRANSACTION_STATE) return (sendCommand(POP3Command.NOOP) == POP3Reply.OK); return false; } /*** * Delete a message from the POP3 server. The message is only marked * for deletion by the server. If you decide to unmark the message, you * must issuse a {@link #reset reset } command. Messages marked * for deletion are only deleted by the server on * {@link #logout logout }. * A delete attempt can only succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . *

* @param messageId The message number to delete. * @return True if the deletion attempt was successful, false if not. * @exception IOException If a network I/O error occurs in the process of * sending the delete command. ***/ public boolean deleteMessage(int messageId) throws IOException { if (getState() == TRANSACTION_STATE) return (sendCommand(POP3Command.DELE, Integer.toString(messageId)) == POP3Reply.OK); return false; } /*** * Reset the POP3 session. This is useful for undoing any message * deletions that may have been performed. A reset attempt can only * succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . *

* @return True if the reset attempt was successful, false if not. * @exception IOException If a network I/O error occurs in the process of * sending the reset command. ***/ public boolean reset() throws IOException { if (getState() == TRANSACTION_STATE) return (sendCommand(POP3Command.RSET) == POP3Reply.OK); return false; } /*** * Get the mailbox status. A status attempt can only * succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns a POP3MessageInfo instance * containing the number of messages in the mailbox and the total * size of the messages in bytes. Returns null if the status the * attempt fails. *

* @return A POP3MessageInfo instance containing the number of * messages in the mailbox and the total size of the messages * in bytes. Returns null if the status the attempt fails. * @exception IOException If a network I/O error occurs in the process of * sending the status command. ***/ public POP3MessageInfo status() throws IOException { if (getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.STAT) != POP3Reply.OK) return null; return __parseStatus(_lastReplyLine.substring(3)); } /*** * List an individual message. A list attempt can only * succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns a POP3MessageInfo instance * containing the number of the listed message and the * size of the message in bytes. Returns null if the list * attempt fails (e.g., if the specified message number does * not exist). *

* @param messageId The number of the message list. * @return A POP3MessageInfo instance containing the number of the * listed message and the size of the message in bytes. Returns * null if the list attempt fails. * @exception IOException If a network I/O error occurs in the process of * sending the list command. ***/ public POP3MessageInfo listMessage(int messageId) throws IOException { if (getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.LIST, Integer.toString(messageId)) != POP3Reply.OK) return null; return __parseStatus(_lastReplyLine.substring(3)); } /*** * List all messages. A list attempt can only * succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns an array of POP3MessageInfo instances, * each containing the number of a message and its size in bytes. * If there are no messages, this method returns a zero length array. * If the list attempt fails, it returns null. *

* @return An array of POP3MessageInfo instances representing all messages * in the order they appear in the mailbox, * each containing the number of a message and its size in bytes. * If there are no messages, this method returns a zero length array. * If the list attempt fails, it returns null. * @exception IOException If a network I/O error occurs in the process of * sending the list command. ***/ public POP3MessageInfo[] listMessages() throws IOException { POP3MessageInfo[] messages; Enumeration en; int line; if (getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.LIST) != POP3Reply.OK) return null; getAdditionalReply(); // This could be a zero length array if no messages present messages = new POP3MessageInfo[_replyLines.size() - 2]; en = _replyLines.elements(); // Skip first line en.nextElement(); // Fetch lines. for (line = 0; line < messages.length; line++) messages[line] = __parseStatus(en.nextElement()); return messages; } /*** * List the unique identifier for a message. A list attempt can only * succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns a POP3MessageInfo instance * containing the number of the listed message and the * unique identifier for that message. Returns null if the list * attempt fails (e.g., if the specified message number does * not exist). *

* @param messageId The number of the message list. * @return A POP3MessageInfo instance containing the number of the * listed message and the unique identifier for that message. * Returns null if the list attempt fails. * @exception IOException If a network I/O error occurs in the process of * sending the list unique identifier command. ***/ public POP3MessageInfo listUniqueIdentifier(int messageId) throws IOException { if (getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.UIDL, Integer.toString(messageId)) != POP3Reply.OK) return null; return __parseUID(_lastReplyLine.substring(3)); } /*** * List the unique identifiers for all messages. A list attempt can only * succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns an array of POP3MessageInfo instances, * each containing the number of a message and its unique identifier. * If there are no messages, this method returns a zero length array. * If the list attempt fails, it returns null. *

* @return An array of POP3MessageInfo instances representing all messages * in the order they appear in the mailbox, * each containing the number of a message and its unique identifier * If there are no messages, this method returns a zero length array. * If the list attempt fails, it returns null. * @exception IOException If a network I/O error occurs in the process of * sending the list unique identifier command. ***/ public POP3MessageInfo[] listUniqueIdentifiers() throws IOException { POP3MessageInfo[] messages; Enumeration en; int line; if (getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.UIDL) != POP3Reply.OK) return null; getAdditionalReply(); // This could be a zero length array if no messages present messages = new POP3MessageInfo[_replyLines.size() - 2]; en = _replyLines.elements(); // Skip first line en.nextElement(); // Fetch lines. for (line = 0; line < messages.length; line++) messages[line] = __parseUID(en.nextElement()); return messages; } /*** * Retrieve a message from the POP3 server. A retrieve message attempt * can only succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns a DotTerminatedMessageReader instance * from which the entire message can be read. * Returns null if the retrieval attempt fails (e.g., if the specified * message number does not exist). *

* You must not issue any commands to the POP3 server (i.e., call any * other methods) until you finish reading the message from the * returned Reader instance. * The POP3 protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the POP3 connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param messageId The number of the message to fetch. * @return A DotTerminatedMessageReader instance * from which the entire message can be read. * Returns null if the retrieval attempt fails (e.g., if the specified * message number does not exist). * @exception IOException If a network I/O error occurs in the process of * sending the retrieve message command. ***/ public Reader retrieveMessage(int messageId) throws IOException { if (getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.RETR, Integer.toString(messageId)) != POP3Reply.OK) return null; return new DotTerminatedMessageReader(_reader); } /*** * Retrieve only the specified top number of lines of a message from the * POP3 server. A retrieve top lines attempt * can only succeed if the client is in the * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE } * . Returns a DotTerminatedMessageReader instance * from which the specified top number of lines of the message can be * read. * Returns null if the retrieval attempt fails (e.g., if the specified * message number does not exist). *

* You must not issue any commands to the POP3 server (i.e., call any * other methods) until you finish reading the message from the returned * Reader instance. * The POP3 protocol uses the same stream for issuing commands as it does * for returning results. Therefore the returned Reader actually reads * directly from the POP3 connection. After the end of message has been * reached, new commands can be executed and their replies read. If * you do not follow these requirements, your program will not work * properly. *

* @param messageId The number of the message to fetch. * @param numLines The top number of lines to fetch. This must be >= 0. * @return A DotTerminatedMessageReader instance * from which the specified top number of lines of the message can be * read. * Returns null if the retrieval attempt fails (e.g., if the specified * message number does not exist). * @exception IOException If a network I/O error occurs in the process of * sending the top command. ***/ public Reader retrieveMessageTop(int messageId, int numLines) throws IOException { if (numLines < 0 || getState() != TRANSACTION_STATE) return null; if (sendCommand(POP3Command.TOP, Integer.toString(messageId) + " " + Integer.toString(numLines)) != POP3Reply.OK) return null; return new DotTerminatedMessageReader(_reader); } } commons-net-2.2/src/main/java/org/apache/commons/net/pop3/POP3Reply.java0000644000175000017500000000233710766305177025761 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; /*** * POP3Reply stores POP3 reply code constants. *

*

* @author Daniel F. Savarese ***/ public final class POP3Reply { /*** The reply code indicating success of an operation. ***/ public static final int OK = 0; /*** The reply code indicating failure of an operation. ***/ public static final int ERROR = 1; // Cannot be instantiated. private POP3Reply() {} } commons-net-2.2/src/main/java/org/apache/commons/net/pop3/POP3.java0000644000175000017500000002663211354512541024736 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.EOFException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.Enumeration; import java.util.Vector; import org.apache.commons.net.MalformedServerReplyException; import org.apache.commons.net.ProtocolCommandListener; import org.apache.commons.net.ProtocolCommandSupport; import org.apache.commons.net.SocketClient; /*** * The POP3 class is not meant to be used by itself and is provided * only so that you may easily implement your own POP3 client if * you so desire. If you have no need to perform your own implementation, * you should use {@link org.apache.commons.net.pop3.POP3Client}. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @see POP3Client * @see org.apache.commons.net.MalformedServerReplyException ***/ public class POP3 extends SocketClient { /*** The default POP3 port. Set to 110 according to RFC 1288. ***/ public static final int DEFAULT_PORT = 110; /*** * A constant representing the state where the client is not yet connected * to a POP3 server. ***/ public static final int DISCONNECTED_STATE = -1; /*** A constant representing the POP3 authorization state. ***/ public static final int AUTHORIZATION_STATE = 0; /*** A constant representing the POP3 transaction state. ***/ public static final int TRANSACTION_STATE = 1; /*** A constant representing the POP3 update state. ***/ public static final int UPDATE_STATE = 2; static final String _OK = "+OK"; static final String _ERROR = "-ERR"; // We have to ensure that the protocol communication is in ASCII // but we use ISO-8859-1 just in case 8-bit characters cross // the wire. private static final String __DEFAULT_ENCODING = "ISO-8859-1"; private int __popState; private BufferedWriter __writer; private StringBuffer __commandBuffer; BufferedReader _reader; int _replyCode; String _lastReplyLine; Vector _replyLines; /*** * A ProtocolCommandSupport object used to manage the registering of * ProtocolCommandListeners and te firing of ProtocolCommandEvents. ***/ protected ProtocolCommandSupport _commandSupport_; /*** * The default POP3Client constructor. Initializes the state * to DISCONNECTED_STATE. ***/ public POP3() { setDefaultPort(DEFAULT_PORT); __commandBuffer = new StringBuffer(); __popState = DISCONNECTED_STATE; _reader = null; __writer = null; _replyLines = new Vector(); _commandSupport_ = new ProtocolCommandSupport(this); } private void __getReply() throws IOException { String line; _replyLines.setSize(0); line = _reader.readLine(); if (line == null) throw new EOFException("Connection closed without indication."); if (line.startsWith(_OK)) _replyCode = POP3Reply.OK; else if (line.startsWith(_ERROR)) _replyCode = POP3Reply.ERROR; else throw new MalformedServerReplyException( "Received invalid POP3 protocol response from server."); _replyLines.addElement(line); _lastReplyLine = line; if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireReplyReceived(_replyCode, getReplyString()); } /*** * Performs connection initialization and sets state to * AUTHORIZATION_STATE . ***/ @Override protected void _connectAction_() throws IOException { super._connectAction_(); _reader = new BufferedReader(new InputStreamReader(_input_, __DEFAULT_ENCODING)); __writer = new BufferedWriter(new OutputStreamWriter(_output_, __DEFAULT_ENCODING)); __getReply(); setState(AUTHORIZATION_STATE); } /*** * Adds a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to add. ***/ public void addProtocolCommandListener(ProtocolCommandListener listener) { _commandSupport_.addProtocolCommandListener(listener); } /*** * Removes a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to remove. ***/ public void removeProtocolCommandistener(ProtocolCommandListener listener) { _commandSupport_.removeProtocolCommandListener(listener); } /*** * Sets POP3 client state. This must be one of the * _STATE constants. *

* @param state The new state. ***/ public void setState(int state) { __popState = state; } /*** * Returns the current POP3 client state. *

* @return The current POP3 client state. ***/ public int getState() { return __popState; } /*** * Retrieves the additional lines of a multi-line server reply. ***/ public void getAdditionalReply() throws IOException { String line; line = _reader.readLine(); while (line != null) { _replyLines.addElement(line); if (line.equals(".")) break; line = _reader.readLine(); } } /*** * Disconnects the client from the server, and sets the state to * DISCONNECTED_STATE . The reply text information * from the last issued command is voided to allow garbage collection * of the memory used to store that information. *

* @exception IOException If there is an error in disconnecting. ***/ @Override public void disconnect() throws IOException { super.disconnect(); _reader = null; __writer = null; _lastReplyLine = null; _replyLines.setSize(0); setState(DISCONNECTED_STATE); } /*** * Sends a command an arguments to the server and returns the reply code. *

* @param command The POP3 command to send. * @param args The command arguments. * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR). ***/ public int sendCommand(String command, String args) throws IOException { String message; __commandBuffer.setLength(0); __commandBuffer.append(command); if (args != null) { __commandBuffer.append(' '); __commandBuffer.append(args); } __commandBuffer.append(SocketClient.NETASCII_EOL); __writer.write(message = __commandBuffer.toString()); __writer.flush(); if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireCommandSent(command, message); __getReply(); return _replyCode; } /*** * Sends a command with no arguments to the server and returns the * reply code. *

* @param command The POP3 command to send. * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR). ***/ public int sendCommand(String command) throws IOException { return sendCommand(command, null); } /*** * Sends a command an arguments to the server and returns the reply code. *

* @param command The POP3 command to send * (one of the POP3Command constants). * @param args The command arguments. * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR). ***/ public int sendCommand(int command, String args) throws IOException { return sendCommand(POP3Command._commands[command], args); } /*** * Sends a command with no arguments to the server and returns the * reply code. *

* @param command The POP3 command to send * (one of the POP3Command constants). * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR). ***/ public int sendCommand(int command) throws IOException { return sendCommand(POP3Command._commands[command], null); } /*** * Returns an array of lines received as a reply to the last command * sent to the server. The lines have end of lines truncated. If * the reply is a single line, but its format ndicates it should be * a multiline reply, then you must call * {@link #getAdditionalReply getAdditionalReply() } to * fetch the rest of the reply, and then call getReplyStrings * again. You only have to worry about this if you are implementing * your own client using the {@link #sendCommand sendCommand } methods. *

* @return The last server response. ***/ public String[] getReplyStrings() { String[] lines; lines = new String[_replyLines.size()]; _replyLines.copyInto(lines); return lines; } /*** * Returns the reply to the last command sent to the server. * The value is a single string containing all the reply lines including * newlines. If the reply is a single line, but its format ndicates it * should be a multiline reply, then you must call * {@link #getAdditionalReply getAdditionalReply() } to * fetch the rest of the reply, and then call getReplyString * again. You only have to worry about this if you are implementing * your own client using the {@link #sendCommand sendCommand } methods. *

* @return The last server response. ***/ public String getReplyString() { Enumeration en; StringBuilder buffer = new StringBuilder(256); en = _replyLines.elements(); while (en.hasMoreElements()) { buffer.append(en.nextElement()); buffer.append(SocketClient.NETASCII_EOL); } return buffer.toString(); } } commons-net-2.2/src/main/java/org/apache/commons/net/MalformedServerReplyException.java0000644000175000017500000000370110542533103031307 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.io.IOException; /*** * This exception is used to indicate that the reply from a server * could not be interpreted. Most of the NetComponents classes attempt * to be as lenient as possible when receiving server replies. Many * server implementations deviate from IETF protocol specifications, making * it necessary to be as flexible as possible. However, there will be * certain situations where it is not possible to continue an operation * because the server reply could not be interpreted in a meaningful manner. * In these cases, a MalformedServerReplyException should be thrown. *

*

* @author Daniel F. Savarese ***/ public class MalformedServerReplyException extends IOException { /*** Constructs a MalformedServerReplyException with no message ***/ public MalformedServerReplyException() { super(); } /*** * Constructs a MalformedServerReplyException with a specified message. *

* @param message The message explaining the reason for the exception. ***/ public MalformedServerReplyException(String message) { super(message); } } commons-net-2.2/src/main/java/org/apache/commons/net/SocketClient.java0000644000175000017500000005252711466231525025731 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import javax.net.ServerSocketFactory; import javax.net.SocketFactory; /** * The SocketClient provides the basic operations that are required of * client objects accessing sockets. It is meant to be * subclassed to avoid having to rewrite the same code over and over again * to open a socket, close a socket, set timeouts, etc. Of special note * is the {@link #setSocketFactory setSocketFactory } * method, which allows you to control the type of Socket the SocketClient * creates for initiating network connections. This is especially useful * for adding SSL or proxy support as well as better support for applets. For * example, you could create a * {@link javax.net.SocketFactory} that * requests browser security capabilities before creating a socket. * All classes derived from SocketClient should use the * {@link #_socketFactory_ _socketFactory_ } member variable to * create Socket and ServerSocket instances rather than instanting * them by directly invoking a constructor. By honoring this contract * you guarantee that a user will always be able to provide his own * Socket implementations by substituting his own SocketFactory. * @author Daniel F. Savarese * @see SocketFactory */ public abstract class SocketClient { /** * The end of line character sequence used by most IETF protocols. That * is a carriage return followed by a newline: "\r\n" */ public static final String NETASCII_EOL = "\r\n"; /** The default SocketFactory shared by all SocketClient instances. */ private static final SocketFactory __DEFAULT_SOCKET_FACTORY = SocketFactory.getDefault(); /** The default {@link ServerSocketFactory} */ private static final ServerSocketFactory __DEFAULT_SERVER_SOCKET_FACTORY = ServerSocketFactory.getDefault(); /** The timeout to use after opening a socket. */ protected int _timeout_; /** The socket used for the connection. */ protected Socket _socket_; /** The default port the client should connect to. */ protected int _defaultPort_; /** The socket's InputStream. */ protected InputStream _input_; /** The socket's OutputStream. */ protected OutputStream _output_; /** The socket's SocketFactory. */ protected SocketFactory _socketFactory_; /** The socket's ServerSocket Factory. */ protected ServerSocketFactory _serverSocketFactory_; /** The socket's connect timeout (0 = infinite timeout) */ private static final int DEFAULT_CONNECT_TIMEOUT = 0; protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT; /** Hint for SO_RCVBUF size */ int receiveBufferSize = -1; /** Hint for SO_SNDBUF size */ int sendBufferSize = -1; /** * Default constructor for SocketClient. Initializes * _socket_ to null, _timeout_ to 0, _defaultPort to 0, * _isConnected_ to false, and _socketFactory_ to a shared instance of * {@link org.apache.commons.net.DefaultSocketFactory}. */ public SocketClient() { _socket_ = null; _input_ = null; _output_ = null; _timeout_ = 0; _defaultPort_ = 0; _socketFactory_ = __DEFAULT_SOCKET_FACTORY; _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY; } /** * Because there are so many connect() methods, the _connectAction_() * method is provided as a means of performing some action immediately * after establishing a connection, rather than reimplementing all * of the connect() methods. The last action performed by every * connect() method after opening a socket is to call this method. *

* This method sets the timeout on the just opened socket to the default * timeout set by {@link #setDefaultTimeout setDefaultTimeout() }, * sets _input_ and _output_ to the socket's InputStream and OutputStream * respectively, and sets _isConnected_ to true. *

* Subclasses overriding this method should start by calling * super._connectAction_() first to ensure the * initialization of the aforementioned protected variables. */ protected void _connectAction_() throws IOException { _socket_.setSoTimeout(_timeout_); _input_ = _socket_.getInputStream(); _output_ = _socket_.getOutputStream(); } /** * Opens a Socket connected to a remote host at the specified port and * originating from the current host at a system assigned port. * Before returning, {@link #_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param host The remote host. * @param port The port to connect to on the remote host. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. */ public void connect(InetAddress host, int port) throws SocketException, IOException { _socket_ = _socketFactory_.createSocket(); if (receiveBufferSize != -1) _socket_.setReceiveBufferSize(receiveBufferSize); if (sendBufferSize != -1) _socket_.setSendBufferSize(sendBufferSize); _socket_.connect(new InetSocketAddress(host, port), connectTimeout); _connectAction_(); } /** * Opens a Socket connected to a remote host at the specified port and * originating from the current host at a system assigned port. * Before returning, {@link #_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param hostname The name of the remote host. * @param port The port to connect to on the remote host. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. * @exception UnknownHostException If the hostname cannot be resolved. */ public void connect(String hostname, int port) throws SocketException, IOException { connect(InetAddress.getByName(hostname), port); } /** * Opens a Socket connected to a remote host at the specified port and * originating from the specified local address and port. * Before returning, {@link #_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param host The remote host. * @param port The port to connect to on the remote host. * @param localAddr The local address to use. * @param localPort The local port to use. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. */ public void connect(InetAddress host, int port, InetAddress localAddr, int localPort) throws SocketException, IOException { _socket_ = _socketFactory_.createSocket(); if (receiveBufferSize != -1) _socket_.setReceiveBufferSize(receiveBufferSize); if (sendBufferSize != -1) _socket_.setSendBufferSize(sendBufferSize); _socket_.bind(new InetSocketAddress(localAddr, localPort)); _socket_.connect(new InetSocketAddress(host, port), connectTimeout); _connectAction_(); } /** * Opens a Socket connected to a remote host at the specified port and * originating from the specified local address and port. * Before returning, {@link #_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param hostname The name of the remote host. * @param port The port to connect to on the remote host. * @param localAddr The local address to use. * @param localPort The local port to use. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. * @exception UnknownHostException If the hostname cannot be resolved. */ public void connect(String hostname, int port, InetAddress localAddr, int localPort) throws SocketException, IOException { connect(InetAddress.getByName(hostname), port, localAddr, localPort); } /** * Opens a Socket connected to a remote host at the current default port * and originating from the current host at a system assigned port. * Before returning, {@link #_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param host The remote host. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. */ public void connect(InetAddress host) throws SocketException, IOException { connect(host, _defaultPort_); } /** * Opens a Socket connected to a remote host at the current default * port and originating from the current host at a system assigned port. * Before returning, {@link #_connectAction_ _connectAction_() } * is called to perform connection initialization actions. *

* @param hostname The name of the remote host. * @exception SocketException If the socket timeout could not be set. * @exception IOException If the socket could not be opened. In most * cases you will only want to catch IOException since SocketException is * derived from it. * @exception UnknownHostException If the hostname cannot be resolved. */ public void connect(String hostname) throws SocketException, IOException { connect(hostname, _defaultPort_); } /** * Disconnects the socket connection. * You should call this method after you've finished using the class * instance and also before you call * {@link #connect connect() } * again. _isConnected_ is set to false, _socket_ is set to null, * _input_ is set to null, and _output_ is set to null. *

* @exception IOException If there is an error closing the socket. */ public void disconnect() throws IOException { closeQuietly(_socket_); closeQuietly(_input_); closeQuietly(_output_); _socket_ = null; _input_ = null; _output_ = null; } private void closeQuietly(Socket socket) { if (socket != null){ try { socket.close(); } catch (IOException e) { } } } private void closeQuietly(Closeable close){ if (close != null){ try { close.close(); } catch (IOException e) { } } } /** * Returns true if the client is currently connected to a server. *

* @return True if the client is currently connected to a server, * false otherwise. */ public boolean isConnected() { if (_socket_ == null) return false; return _socket_.isConnected(); } /** * Sets the default port the SocketClient should connect to when a port * is not specified. The {@link #_defaultPort_ _defaultPort_ } * variable stores this value. If never set, the default port is equal * to zero. *

* @param port The default port to set. */ public void setDefaultPort(int port) { _defaultPort_ = port; } /** * Returns the current value of the default port (stored in * {@link #_defaultPort_ _defaultPort_ }). *

* @return The current value of the default port. */ public int getDefaultPort() { return _defaultPort_; } /** * Set the default timeout in milliseconds to use when opening a socket. * This value is only used previous to a call to * {@link #connect connect()} * and should not be confused with {@link #setSoTimeout setSoTimeout()} * which operates on an the currently opened socket. _timeout_ contains * the new timeout value. *

* @param timeout The timeout in milliseconds to use for the socket * connection. */ public void setDefaultTimeout(int timeout) { _timeout_ = timeout; } /** * Returns the default timeout in milliseconds that is used when * opening a socket. *

* @return The default timeout in milliseconds that is used when * opening a socket. */ public int getDefaultTimeout() { return _timeout_; } /** * Set the timeout in milliseconds of a currently open connection. * Only call this method after a connection has been opened * by {@link #connect connect()}. *

* @param timeout The timeout in milliseconds to use for the currently * open socket connection. * @exception SocketException If the operation fails. */ public void setSoTimeout(int timeout) throws SocketException { _socket_.setSoTimeout(timeout); } /** * Set the underlying socket send buffer size. *

* @param size The size of the buffer in bytes. * @throws SocketException * @since 2.0 */ public void setSendBufferSize(int size) throws SocketException { sendBufferSize = size; } /** * Sets the underlying socket receive buffer size. *

* @param size The size of the buffer in bytes. * @throws SocketException * @since 2.0 */ public void setReceiveBufferSize(int size) throws SocketException { receiveBufferSize = size; } /** * Returns the timeout in milliseconds of the currently opened socket. *

* @return The timeout in milliseconds of the currently opened socket. * @exception SocketException If the operation fails. */ public int getSoTimeout() throws SocketException { return _socket_.getSoTimeout(); } /** * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the * currently opened socket. *

* @param on True if Nagle's algorithm is to be enabled, false if not. * @exception SocketException If the operation fails. */ public void setTcpNoDelay(boolean on) throws SocketException { _socket_.setTcpNoDelay(on); } /** * Returns true if Nagle's algorithm is enabled on the currently opened * socket. *

* @return True if Nagle's algorithm is enabled on the currently opened * socket, false otherwise. * @exception SocketException If the operation fails. */ public boolean getTcpNoDelay() throws SocketException { return _socket_.getTcpNoDelay(); } /** * Sets the SO_KEEPALIVE flag on the currently opened socket. * * From the Javadocs, the default keepalive time is 2 hours (although this is * implementation dependent). It looks as though the Windows WSA sockets implementation * allows a specific keepalive value to be set, although this seems not to be the case on * other systems. * @param keepAlive If true, keepAlive is turned on * @throws SocketException * @since 2.2 */ public void setKeepAlive(boolean keepAlive) throws SocketException { _socket_.setKeepAlive(keepAlive); } /** * Returns the current value of the SO_KEEPALIVE flag on the currently opened socket. * * @return True if SO_KEEPALIVE is enabled. * @throws SocketException * @since 2.2 */ public boolean getKeepAlive() throws SocketException { return _socket_.getKeepAlive(); } /** * Sets the SO_LINGER timeout on the currently opened socket. *

* @param on True if linger is to be enabled, false if not. * @param val The linger timeout (in hundredths of a second?) * @exception SocketException If the operation fails. */ public void setSoLinger(boolean on, int val) throws SocketException { _socket_.setSoLinger(on, val); } /** * Returns the current SO_LINGER timeout of the currently opened socket. *

* @return The current SO_LINGER timeout. If SO_LINGER is disabled returns * -1. * @exception SocketException If the operation fails. */ public int getSoLinger() throws SocketException { return _socket_.getSoLinger(); } /** * Returns the port number of the open socket on the local host used * for the connection. *

* @return The port number of the open socket on the local host used * for the connection. */ public int getLocalPort() { return _socket_.getLocalPort(); } /** * Returns the local address to which the client's socket is bound. *

* @return The local address to which the client's socket is bound. */ public InetAddress getLocalAddress() { return _socket_.getLocalAddress(); } /** * Returns the port number of the remote host to which the client is * connected. *

* @return The port number of the remote host to which the client is * connected. */ public int getRemotePort() { return _socket_.getPort(); } /** * @return The remote address to which the client is connected. */ public InetAddress getRemoteAddress() { return _socket_.getInetAddress(); } /** * Verifies that the remote end of the given socket is connected to the * the same host that the SocketClient is currently connected to. This * is useful for doing a quick security check when a client needs to * accept a connection from a server, such as an FTP data connection or * a BSD R command standard error stream. *

* @return True if the remote hosts are the same, false if not. */ public boolean verifyRemote(Socket socket) { InetAddress host1, host2; host1 = socket.getInetAddress(); host2 = getRemoteAddress(); return host1.equals(host2); } /** * Sets the SocketFactory used by the SocketClient to open socket * connections. If the factory value is null, then a default * factory is used (only do this to reset the factory after having * previously altered it). *

* @param factory The new SocketFactory the SocketClient should use. */ public void setSocketFactory(SocketFactory factory) { if (factory == null) _socketFactory_ = __DEFAULT_SOCKET_FACTORY; else _socketFactory_ = factory; } /** * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket * connections. If the factory value is null, then a default * factory is used (only do this to reset the factory after having * previously altered it). *

* @param factory The new ServerSocketFactory the SocketClient should use. * @since 2.0 */ public void setServerSocketFactory(ServerSocketFactory factory) { if (factory == null) _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY; else _serverSocketFactory_ = factory; } /** * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's * connect() method. * @param connectTimeout The connection timeout to use (in ms) * @since 2.0 */ public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } /** * Get the underlying socket connection timeout. * @return timeout (in ms) * @since 2.0 */ public int getConnectTimeout() { return connectTimeout; } /** * Get the underlying {@link ServerSocketFactory} * @return The server socket factory * @since 2.2 */ public ServerSocketFactory getServerSocketFactory() { return _serverSocketFactory_; } } commons-net-2.2/src/main/java/org/apache/commons/net/DefaultSocketFactory.java0000644000175000017500000001422410766271714027425 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import javax.net.SocketFactory; /*** * DefaultSocketFactory implements the SocketFactory interface by * simply wrapping the java.net.Socket and java.net.ServerSocket * constructors. It is the default SocketFactory used by * {@link org.apache.commons.net.SocketClient} * implementations. *

*

* @author Daniel F. Savarese * @see SocketFactory * @see SocketClient * @see SocketClient#setSocketFactory ***/ public class DefaultSocketFactory extends SocketFactory { /*** * Creates a Socket connected to the given host and port. *

* @param host The hostname to connect to. * @param port The port to connect to. * @return A Socket connected to the given host and port. * @exception UnknownHostException If the hostname cannot be resolved. * @exception IOException If an I/O error occurs while creating the Socket. ***/ @Override public Socket createSocket(String host, int port) throws UnknownHostException, IOException { return new Socket(host, port); } /*** * Creates a Socket connected to the given host and port. *

* @param address The address of the host to connect to. * @param port The port to connect to. * @return A Socket connected to the given host and port. * @exception IOException If an I/O error occurs while creating the Socket. ***/ @Override public Socket createSocket(InetAddress address, int port) throws IOException { return new Socket(address, port); } /*** * Creates a Socket connected to the given host and port and * originating from the specified local address and port. *

* @param host The hostname to connect to. * @param port The port to connect to. * @param localAddr The local address to use. * @param localPort The local port to use. * @return A Socket connected to the given host and port. * @exception UnknownHostException If the hostname cannot be resolved. * @exception IOException If an I/O error occurs while creating the Socket. ***/ @Override public Socket createSocket(String host, int port, InetAddress localAddr, int localPort) throws UnknownHostException, IOException { return new Socket(host, port, localAddr, localPort); } /*** * Creates a Socket connected to the given host and port and * originating from the specified local address and port. *

* @param address The address of the host to connect to. * @param port The port to connect to. * @param localAddr The local address to use. * @param localPort The local port to use. * @return A Socket connected to the given host and port. * @exception IOException If an I/O error occurs while creating the Socket. ***/ @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException { return new Socket(address, port, localAddr, localPort); } /*** * Creates a ServerSocket bound to a specified port. A port * of 0 will create the ServerSocket on a system-determined free port. *

* @param port The port on which to listen, or 0 to use any free port. * @return A ServerSocket that will listen on a specified port. * @exception IOException If an I/O error occurs while creating * the ServerSocket. ***/ public ServerSocket createServerSocket(int port) throws IOException { return new ServerSocket(port); } /*** * Creates a ServerSocket bound to a specified port with a given * maximum queue length for incoming connections. A port of 0 will * create the ServerSocket on a system-determined free port. *

* @param port The port on which to listen, or 0 to use any free port. * @param backlog The maximum length of the queue for incoming connections. * @return A ServerSocket that will listen on a specified port. * @exception IOException If an I/O error occurs while creating * the ServerSocket. ***/ public ServerSocket createServerSocket(int port, int backlog) throws IOException { return new ServerSocket(port, backlog); } /*** * Creates a ServerSocket bound to a specified port on a given local * address with a given maximum queue length for incoming connections. * A port of 0 will * create the ServerSocket on a system-determined free port. *

* @param port The port on which to listen, or 0 to use any free port. * @param backlog The maximum length of the queue for incoming connections. * @param bindAddr The local address to which the ServerSocket should bind. * @return A ServerSocket that will listen on a specified port. * @exception IOException If an I/O error occurs while creating * the ServerSocket. ***/ public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException { return new ServerSocket(port, backlog, bindAddr); } } commons-net-2.2/src/main/java/org/apache/commons/net/DatagramSocketFactory.java0000644000175000017500000000461110542533103027541 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /*** * The DatagramSocketFactory interface provides a means for the * programmer to control the creation of datagram sockets and * provide his own DatagramSocket implementations for use by all * classes derived from * {@link org.apache.commons.net.DatagramSocketClient} * . * This allows you to provide your own DatagramSocket implementations and * to perform security checks or browser capability requests before * creating a DatagramSocket. *

*

* @author Daniel F. Savarese ***/ public interface DatagramSocketFactory { /*** * Creates a DatagramSocket on the local host at the first available port. *

* @exception SocketException If the socket could not be created. ***/ public DatagramSocket createDatagramSocket() throws SocketException; /*** * Creates a DatagramSocket on the local host at a specified port. *

* @param port The port to use for the socket. * @exception SocketException If the socket could not be created. ***/ public DatagramSocket createDatagramSocket(int port) throws SocketException; /*** * Creates a DatagramSocket at the specified address on the local host * at a specified port. *

* @param port The port to use for the socket. * @param laddr The local address to use. * @exception SocketException If the socket could not be created. ***/ public DatagramSocket createDatagramSocket(int port, InetAddress laddr) throws SocketException; } commons-net-2.2/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java0000644000175000017500000001070611416072763030032 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import java.io.Serializable; import java.util.EventListener; import org.apache.commons.net.util.ListenerList; /*** * ProtocolCommandSupport is a convenience class for managing a list of * ProtocolCommandListeners and firing ProtocolCommandEvents. You can * simply delegate ProtocolCommandEvent firing and listener * registering/unregistering tasks to this class. *

*

* @see ProtocolCommandEvent * @see ProtocolCommandListener * @author Daniel F. Savarese ***/ public class ProtocolCommandSupport implements Serializable { private final Object __source; private final ListenerList __listeners; /*** * Creates a ProtocolCommandSupport instant using the indicated source * as the source of fired ProtocolCommandEvents. *

* @param source The source to use for all generated ProtocolCommandEvents. ***/ public ProtocolCommandSupport(Object source) { __listeners = new ListenerList(); __source = source; } /*** * Fires a ProtocolCommandEvent signalling the sending of a command to all * registered listeners, invoking their * {@link org.apache.commons.net.ProtocolCommandListener#protocolCommandSent protocolCommandSent() } * methods. *

* @param command The string representation of the command type sent, not * including the arguments (e.g., "STAT" or "GET"). * @param message The entire command string verbatim as sent to the server, * including all arguments. ***/ public void fireCommandSent(String command, String message) { ProtocolCommandEvent event; event = new ProtocolCommandEvent(__source, command, message); for (EventListener listener : __listeners) { ((ProtocolCommandListener)listener).protocolCommandSent(event); } } /*** * Fires a ProtocolCommandEvent signalling the reception of a command reply * to all registered listeners, invoking their * {@link org.apache.commons.net.ProtocolCommandListener#protocolReplyReceived protocolReplyReceived() } * methods. *

* @param replyCode The integer code indicating the natureof the reply. * This will be the protocol integer value for protocols * that use integer reply codes, or the reply class constant * corresponding to the reply for protocols like POP3 that use * strings like OK rather than integer codes (i.e., POP3Repy.OK). * @param message The entire reply as received from the server. ***/ public void fireReplyReceived(int replyCode, String message) { ProtocolCommandEvent event; event = new ProtocolCommandEvent(__source, replyCode, message); for (EventListener listener : __listeners) { ((ProtocolCommandListener)listener).protocolReplyReceived(event); } } /*** * Adds a ProtocolCommandListener. *

* @param listener The ProtocolCommandListener to add. ***/ public void addProtocolCommandListener(ProtocolCommandListener listener) { __listeners.addListener(listener); } /*** * Removes a ProtocolCommandListener. *

* @param listener The ProtocolCommandListener to remove. ***/ public void removeProtocolCommandListener(ProtocolCommandListener listener) { __listeners.removeListener(listener); } /*** * Returns the number of ProtocolCommandListeners currently registered. *

* @return The number of ProtocolCommandListeners currently registered. ***/ public int getListenerCount() { return __listeners.getListenerCount(); } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/0000755000175000017500000000000011617452467023767 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/telnet/WindowSizeOptionHandler.java0000644000175000017500000001224011416446036031412 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * Implements the telnet window size option RFC 1073. *

* @author Yuval Kashtan * @version $Id: WindowSizeOptionHandler.java 963157 2010-07-11 22:56:30Z sebb $ * @since 2.0 ***/ public class WindowSizeOptionHandler extends TelnetOptionHandler { /*** * Horizontal Size ***/ private int m_nWidth = 80; /*** * Vertical Size ***/ private int m_nHeight = 24; /*** * Window size option ***/ protected static final int WINDOW_SIZE = 31; /*** * Constructor for the WindowSizeOptionHandler. Allows defining desired * initial setting for local/remote activation of this option and * behaviour in case a local/remote activation request for this * option is received. *

* @param nWidth - Window width. * @param nHeight - Window Height * @param initlocal - if set to true, a WILL is sent upon connection. * @param initremote - if set to true, a DO is sent upon connection. * @param acceptlocal - if set to true, any DO request is accepted. * @param acceptremote - if set to true, any WILL request is accepted. ***/ public WindowSizeOptionHandler( int nWidth, int nHeight, boolean initlocal, boolean initremote, boolean acceptlocal, boolean acceptremote ) { super ( TelnetOption.WINDOW_SIZE, initlocal, initremote, acceptlocal, acceptremote ); m_nWidth = nWidth; m_nHeight = nHeight; } /*** * Constructor for the WindowSizeOptionHandler. Initial and accept * behaviour flags are set to false *

* @param nWidth - Window width. * @param nHeight - Window Height ***/ public WindowSizeOptionHandler( int nWidth, int nHeight ) { super ( TelnetOption.WINDOW_SIZE, false, false, false, false ); m_nWidth = nWidth; m_nHeight = nHeight; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @param suboptionData - the sequence received, whithout IAC SB & IAC SE * @param suboptionLength - the length of data in suboption_data *

* @return terminal type information ***/ @Override public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. * This will send the client Height and Width to the server. *

* @return array to send to remote system ***/ @Override public int[] startSubnegotiationLocal() { int nCompoundWindowSize = m_nWidth * 0x10000 + m_nHeight; int nResponseSize = 5; int nIndex; int nShift; int nTurnedOnBits; if ((m_nWidth % 0x100) == 0xFF) { nResponseSize += 1; } if ((m_nWidth / 0x100) == 0xFF) { nResponseSize += 1; } if ((m_nHeight % 0x100) == 0xFF) { nResponseSize += 1; } if ((m_nHeight / 0x100) == 0xFF) { nResponseSize += 1; } // // allocate response array // int response[] = new int[nResponseSize]; // // Build response array. // --------------------- // 1. put option name. // 2. loop through Window size and fill the values, // 3. duplicate 'ff' if needed. // response[0] = WINDOW_SIZE; // 1 // for ( // 2 // nIndex=1, nShift = 24; nIndex < nResponseSize; nIndex++, nShift -=8 ) { nTurnedOnBits = 0xFF; nTurnedOnBits <<= nShift; response[nIndex] = (nCompoundWindowSize & nTurnedOnBits) >>> nShift; if (response[nIndex] == 0xff) { // 3 // nIndex++; response[nIndex] = 0xff; } } return response; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationRemote() { return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetOption.java0000644000175000017500000001505611416315620027247 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * The TelnetOption class cannot be instantiated and only serves as a * storehouse for telnet option constants. *

* Details regarding Telnet option specification can be found in RFC 855. *

*

* @author Daniel F. Savarese * @see org.apache.commons.net.telnet.Telnet * @see org.apache.commons.net.telnet.TelnetClient ***/ public class TelnetOption { /*** The maximum value an option code can have. This value is 255. ***/ public static final int MAX_OPTION_VALUE = 255; public static final int BINARY = 0; public static final int ECHO = 1; public static final int PREPARE_TO_RECONNECT = 2; public static final int SUPPRESS_GO_AHEAD = 3; public static final int APPROXIMATE_MESSAGE_SIZE = 4; public static final int STATUS = 5; public static final int TIMING_MARK = 6; public static final int REMOTE_CONTROLLED_TRANSMISSION = 7; public static final int NEGOTIATE_OUTPUT_LINE_WIDTH = 8; public static final int NEGOTIATE_OUTPUT_PAGE_SIZE = 9; public static final int NEGOTIATE_CARRIAGE_RETURN = 10; public static final int NEGOTIATE_HORIZONTAL_TAB_STOP = 11; public static final int NEGOTIATE_HORIZONTAL_TAB = 12; public static final int NEGOTIATE_FORMFEED = 13; public static final int NEGOTIATE_VERTICAL_TAB_STOP = 14; public static final int NEGOTIATE_VERTICAL_TAB = 15; public static final int NEGOTIATE_LINEFEED = 16; public static final int EXTENDED_ASCII = 17; public static final int FORCE_LOGOUT = 18; public static final int BYTE_MACRO = 19; public static final int DATA_ENTRY_TERMINAL = 20; public static final int SUPDUP = 21; public static final int SUPDUP_OUTPUT = 22; public static final int SEND_LOCATION = 23; public static final int TERMINAL_TYPE = 24; public static final int END_OF_RECORD = 25; public static final int TACACS_USER_IDENTIFICATION = 26; public static final int OUTPUT_MARKING = 27; public static final int TERMINAL_LOCATION_NUMBER = 28; public static final int REGIME_3270 = 29; public static final int X3_PAD = 30; public static final int WINDOW_SIZE = 31; public static final int TERMINAL_SPEED = 32; public static final int REMOTE_FLOW_CONTROL = 33; public static final int LINEMODE = 34; public static final int X_DISPLAY_LOCATION = 35; public static final int OLD_ENVIRONMENT_VARIABLES = 36; public static final int AUTHENTICATION = 37; public static final int ENCRYPTION = 38; public static final int NEW_ENVIRONMENT_VARIABLES = 39; public static final int EXTENDED_OPTIONS_LIST = 255; @SuppressWarnings("unused") private static final int __FIRST_OPTION = BINARY; private static final int __LAST_OPTION = EXTENDED_OPTIONS_LIST; private static final String __optionString[] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON", "TN3270E", "XAUTH", "CHARSET", "RSP", "Com Port Control", "Suppress Local Echo", "Start TLS", "KERMIT", "SEND-URL", "FORWARD_X", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "TELOPT PRAGMA LOGON", "TELOPT SSPI LOGON", "TELOPT PRAGMA HEARTBEAT", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Extended-Options-List" }; /*** * Returns the string representation of the telnet protocol option * corresponding to the given option code. *

* @param code The option code of the telnet protocol option * @return The string representation of the telnet protocol option. ***/ public static final String getOption(int code) { if(__optionString[code].length() == 0) { return "UNASSIGNED"; } else { return __optionString[code]; } } /*** * Determines if a given option code is valid. Returns true if valid, * false if not. *

* @param code The option code to test. * @return True if the option code is valid, false if not. **/ public static final boolean isValidOption(int code) { return (code <= __LAST_OPTION); } // Cannot be instantiated private TelnetOption() { } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java0000644000175000017500000005154111416437422030256 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; /*** * *

* *

*

* @author Daniel F. Savarese * @author Bruno D'Avanzo ***/ final class TelnetInputStream extends BufferedInputStream implements Runnable { /** End of file has been reached */ private static final int EOF = -1; /** Read would block */ private static final int WOULD_BLOCK = -2; // TODO should these be private enums? static final int _STATE_DATA = 0, _STATE_IAC = 1, _STATE_WILL = 2, _STATE_WONT = 3, _STATE_DO = 4, _STATE_DONT = 5, _STATE_SB = 6, _STATE_SE = 7, _STATE_CR = 8, _STATE_IAC_SB = 9; private boolean __hasReachedEOF, __isClosed; private boolean __readIsWaiting; private int __receiveState, __queueHead, __queueTail, __bytesAvailable; private final int[] __queue; private final TelnetClient __client; private final Thread __thread; private IOException __ioException; /* TERMINAL-TYPE option (start)*/ private final int __suboption[] = new int[256]; private int __suboption_count = 0; /* TERMINAL-TYPE option (end)*/ private boolean __threaded; TelnetInputStream(InputStream input, TelnetClient client, boolean readerThread) { super(input); __client = client; __receiveState = _STATE_DATA; __isClosed = true; __hasReachedEOF = false; // Make it 2049, because when full, one slot will go unused, and we // want a 2048 byte buffer just to have a round number (base 2 that is) __queue = new int[2049]; __queueHead = 0; __queueTail = 0; __bytesAvailable = 0; __ioException = null; __readIsWaiting = false; __threaded = false; if(readerThread) __thread = new Thread(this); else __thread = null; } TelnetInputStream(InputStream input, TelnetClient client) { this(input, client, true); } void _start() { if(__thread == null) return; int priority; __isClosed = false; // TODO remove this // Need to set a higher priority in case JVM does not use pre-emptive // threads. This should prevent scheduler induced deadlock (rather than // deadlock caused by a bug in this code). priority = Thread.currentThread().getPriority() + 1; if (priority > Thread.MAX_PRIORITY) priority = Thread.MAX_PRIORITY; __thread.setPriority(priority); __thread.setDaemon(true); __thread.start(); __threaded = true; } // synchronized(__client) critical sections are to protect against // TelnetOutputStream writing through the telnet client at same time // as a processDo/Will/etc. command invoked from TelnetInputStream // tries to write. /** * Get the next byte of data. * IAC commands are processed internally and do not return data. * * @param mayBlock true if method is allowed to block * @return the next byte of data, * or -1 (EOF) if end of stread reached, * or -2 (WOULD_BLOCK) if mayBlock is false and there is no data available */ private int __read(boolean mayBlock) throws IOException { int ch; while (true) { // If there is no more data AND we were told not to block, just return WOULD_BLOCK (-2). (More efficient than exception.) if(!mayBlock && super.available() == 0) return WOULD_BLOCK; // Otherwise, exit only when we reach end of stream. if ((ch = super.read()) < 0) return EOF; ch = (ch & 0xff); /* Code Section added for supporting AYT (start)*/ synchronized (__client) { __client._processAYTResponse(); } /* Code Section added for supporting AYT (end)*/ /* Code Section added for supporting spystreams (start)*/ __client._spyRead(ch); /* Code Section added for supporting spystreams (end)*/ switch (__receiveState) { case _STATE_CR: if (ch == '\0') { // Strip null continue; } // How do we handle newline after cr? // else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) && // Handle as normal data by falling through to _STATE_DATA case //$FALL-THROUGH$ case _STATE_DATA: if (ch == TelnetCommand.IAC) { __receiveState = _STATE_IAC; continue; } if (ch == '\r') { synchronized (__client) { if (__client._requestedDont(TelnetOption.BINARY)) __receiveState = _STATE_CR; else __receiveState = _STATE_DATA; } } else __receiveState = _STATE_DATA; break; case _STATE_IAC: switch (ch) { case TelnetCommand.WILL: __receiveState = _STATE_WILL; continue; case TelnetCommand.WONT: __receiveState = _STATE_WONT; continue; case TelnetCommand.DO: __receiveState = _STATE_DO; continue; case TelnetCommand.DONT: __receiveState = _STATE_DONT; continue; /* TERMINAL-TYPE option (start)*/ case TelnetCommand.SB: __suboption_count = 0; __receiveState = _STATE_SB; continue; /* TERMINAL-TYPE option (end)*/ case TelnetCommand.IAC: __receiveState = _STATE_DATA; break; // exit to enclosing switch to return IAC from read default: __receiveState = _STATE_DATA; __client._processCommand(ch); // Notify the user continue; // move on the next char } break; // exit and return from read case _STATE_WILL: synchronized (__client) { __client._processWill(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; case _STATE_WONT: synchronized (__client) { __client._processWont(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; case _STATE_DO: synchronized (__client) { __client._processDo(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; case _STATE_DONT: synchronized (__client) { __client._processDont(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; /* TERMINAL-TYPE option (start)*/ case _STATE_SB: switch (ch) { case TelnetCommand.IAC: __receiveState = _STATE_IAC_SB; continue; default: // store suboption char __suboption[__suboption_count++] = ch; break; } __receiveState = _STATE_SB; continue; case _STATE_IAC_SB: switch (ch) { case TelnetCommand.SE: synchronized (__client) { __client._processSuboption(__suboption, __suboption_count); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; default: __receiveState = _STATE_SB; break; } __receiveState = _STATE_DATA; continue; /* TERMINAL-TYPE option (end)*/ } break; } return ch; } // synchronized(__client) critical sections are to protect against // TelnetOutputStream writing through the telnet client at same time // as a processDo/Will/etc. command invoked from TelnetInputStream // tries to write. private void __processChar(int ch) throws InterruptedException { // Critical section because we're altering __bytesAvailable, // __queueTail, and the contents of _queue. synchronized (__queue) { while (__bytesAvailable >= __queue.length - 1) { // The queue is full. We need to wait before adding any more data to it. Hopefully the stream owner // will consume some data soon! if(__threaded) { __queue.notify(); try { __queue.wait(); } catch (InterruptedException e) { throw e; } } else { // We've been asked to add another character to the queue, but it is already full and there's // no other thread to drain it. This should not have happened! throw new IllegalStateException("Queue is full! Cannot process another character."); } } // Need to do this in case we're not full, but block on a read if (__readIsWaiting && __threaded) { __queue.notify(); } __queue[__queueTail] = ch; ++__bytesAvailable; if (++__queueTail >= __queue.length) __queueTail = 0; } } @Override public int read() throws IOException { // Critical section because we're altering __bytesAvailable, // __queueHead, and the contents of _queue in addition to // testing value of __hasReachedEOF. synchronized (__queue) { while (true) { if (__ioException != null) { IOException e; e = __ioException; __ioException = null; throw e; } if (__bytesAvailable == 0) { // Return EOF if at end of file if (__hasReachedEOF) return EOF; // Otherwise, we have to wait for queue to get something if(__threaded) { __queue.notify(); try { __readIsWaiting = true; __queue.wait(); __readIsWaiting = false; } catch (InterruptedException e) { throw new InterruptedIOException("Fatal thread interruption during read."); } } else { //__alreadyread = false; __readIsWaiting = true; int ch; boolean mayBlock = true; // block on the first read only do { try { if ((ch = __read(mayBlock)) < 0) // EOF or WOULD_BLOCK if(ch != WOULD_BLOCK) return (ch); // must be EOF } catch (InterruptedIOException e) { synchronized (__queue) { __ioException = e; __queue.notifyAll(); try { __queue.wait(100); } catch (InterruptedException interrupted) { } } return EOF; } try { if(ch != WOULD_BLOCK) { __processChar(ch); } } catch (InterruptedException e) { if (__isClosed) return EOF; } // Reads should not block on subsequent iterations. Potentially, this could happen if the // remaining buffered socket data consists entirely of Telnet command sequence and no "user" data. mayBlock = false; } // Continue reading as long as there is data available and the queue is not full. while (super.available() > 0 && __bytesAvailable < __queue.length - 1); __readIsWaiting = false; } continue; } else { int ch; ch = __queue[__queueHead]; if (++__queueHead >= __queue.length) __queueHead = 0; --__bytesAvailable; // Need to explicitly notify() so available() works properly if(__bytesAvailable == 0 && __threaded) { __queue.notify(); } return ch; } } } } /*** * Reads the next number of bytes from the stream into an array and * returns the number of bytes read. Returns -1 if the end of the * stream has been reached. *

* @param buffer The byte array in which to store the data. * @return The number of bytes read. Returns -1 if the * end of the message has been reached. * @exception IOException If an error occurs in reading the underlying * stream. ***/ @Override public int read(byte buffer[]) throws IOException { return read(buffer, 0, buffer.length); } /*** * Reads the next number of bytes from the stream into an array and returns * the number of bytes read. Returns -1 if the end of the * message has been reached. The characters are stored in the array * starting from the given offset and up to the length specified. *

* @param buffer The byte array in which to store the data. * @param offset The offset into the array at which to start storing data. * @param length The number of bytes to read. * @return The number of bytes read. Returns -1 if the * end of the stream has been reached. * @exception IOException If an error occurs while reading the underlying * stream. ***/ @Override public int read(byte buffer[], int offset, int length) throws IOException { int ch, off; if (length < 1) return 0; // Critical section because run() may change __bytesAvailable synchronized (__queue) { if (length > __bytesAvailable) length = __bytesAvailable; } if ((ch = read()) == EOF) return EOF; off = offset; do { buffer[offset++] = (byte)ch; } while (--length > 0 && (ch = read()) != EOF); //__client._spyRead(buffer, off, offset - off); return (offset - off); } /*** Returns false. Mark is not supported. ***/ @Override public boolean markSupported() { return false; } @Override public int available() throws IOException { // Critical section because run() may change __bytesAvailable synchronized (__queue) { return __bytesAvailable; } } // Cannot be synchronized. Will cause deadlock if run() is blocked // in read because BufferedInputStream read() is synchronized. @Override public void close() throws IOException { // Completely disregard the fact thread may still be running. // We can't afford to block on this close by waiting for // thread to terminate because few if any JVM's will actually // interrupt a system read() from the interrupt() method. super.close(); synchronized (__queue) { __hasReachedEOF = true; __isClosed = true; if (__thread != null && __thread.isAlive()) { __thread.interrupt(); } __queue.notifyAll(); } __threaded = false; } public void run() { int ch; try { _outerLoop: while (!__isClosed) { try { if ((ch = __read(true)) < 0) break; } catch (InterruptedIOException e) { synchronized (__queue) { __ioException = e; __queue.notifyAll(); try { __queue.wait(100); } catch (InterruptedException interrupted) { if (__isClosed) break _outerLoop; } continue; } } catch(RuntimeException re) { // We treat any runtime exceptions as though the // stream has been closed. We close the // underlying stream just to be sure. super.close(); // Breaking the loop has the effect of setting // the state to closed at the end of the method. break _outerLoop; } try { __processChar(ch); } catch (InterruptedException e) { if (__isClosed) break _outerLoop; } } } catch (IOException ioe) { synchronized (__queue) { __ioException = ioe; } } synchronized (__queue) { __isClosed = true; // Possibly redundant __hasReachedEOF = true; __queue.notify(); } __threaded = false; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/telnet/SimpleOptionHandler.java0000644000175000017500000000623410766271714030555 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * Simple option handler that can be used for options * that don't require subnegotiation. *

* @author Bruno D'Avanzo ***/ public class SimpleOptionHandler extends TelnetOptionHandler { /*** * Constructor for the SimpleOptionHandler. Allows defining desired * initial setting for local/remote activation of this option and * behaviour in case a local/remote activation request for this * option is received. *

* @param optcode - option code. * @param initlocal - if set to true, a WILL is sent upon connection. * @param initremote - if set to true, a DO is sent upon connection. * @param acceptlocal - if set to true, any DO request is accepted. * @param acceptremote - if set to true, any WILL request is accepted. ***/ public SimpleOptionHandler(int optcode, boolean initlocal, boolean initremote, boolean acceptlocal, boolean acceptremote) { super(optcode, initlocal, initremote, acceptlocal, acceptremote); } /*** * Constructor for the SimpleOptionHandler. Initial and accept * behaviour flags are set to false *

* @param optcode - option code. ***/ public SimpleOptionHandler(int optcode) { super(optcode, false, false, false, false); } /*** * Implements the abstract method of TelnetOptionHandler. *

* @param suboptionData - the sequence received, whithout IAC SB & IAC SE * @param suboptionLength - the length of data in suboption_data *

* @return always null (no response to subnegotiation) ***/ @Override public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationLocal() { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationRemote() { return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetClient.java0000644000175000017500000002216611151644177027225 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.net.io.FromNetASCIIInputStream; import org.apache.commons.net.io.ToNetASCIIOutputStream; /*** * The TelnetClient class implements the simple network virtual * terminal (NVT) for the Telnet protocol according to RFC 854. It * does not implement any of the extra Telnet options because it * is meant to be used within a Java program providing automated * access to Telnet accessible resources. *

* The class can be used by first connecting to a server using the * SocketClient * {@link org.apache.commons.net.SocketClient#connect connect} * method. Then an InputStream and OutputStream for sending and * receiving data over the Telnet connection can be obtained by * using the {@link #getInputStream getInputStream() } and * {@link #getOutputStream getOutputStream() } methods. * When you finish using the streams, you must call * {@link #disconnect disconnect } rather than simply * closing the streams. *

*

* @author Daniel F. Savarese * @author Bruno D'Avanzo ***/ public class TelnetClient extends Telnet { private InputStream __input; private OutputStream __output; protected boolean readerThread = true; /*** * Default TelnetClient constructor. ***/ public TelnetClient() { /* TERMINAL-TYPE option (start)*/ super ("VT100"); /* TERMINAL-TYPE option (end)*/ __input = null; __output = null; } /* TERMINAL-TYPE option (start)*/ public TelnetClient(String termtype) { super (termtype); __input = null; __output = null; } /* TERMINAL-TYPE option (end)*/ void _flushOutputStream() throws IOException { _output_.flush(); } void _closeOutputStream() throws IOException { _output_.close(); } /*** * Handles special connection requirements. *

* @exception IOException If an error occurs during connection setup. ***/ @Override protected void _connectAction_() throws IOException { super._connectAction_(); InputStream input; TelnetInputStream tmp; if (FromNetASCIIInputStream.isConversionRequired()) input = new FromNetASCIIInputStream(_input_); else input = _input_; tmp = new TelnetInputStream(input, this, readerThread); if(readerThread) { tmp._start(); } // __input CANNOT refer to the TelnetInputStream. We run into // blocking problems when some classes use TelnetInputStream, so // we wrap it with a BufferedInputStream which we know is safe. // This blocking behavior requires further investigation, but right // now it looks like classes like InputStreamReader are not implemented // in a safe manner. __input = new BufferedInputStream(tmp); __output = new ToNetASCIIOutputStream(new TelnetOutputStream(this)); } /*** * Disconnects the telnet session, closing the input and output streams * as well as the socket. If you have references to the * input and output streams of the telnet connection, you should not * close them yourself, but rather call disconnect to properly close * the connection. ***/ @Override public void disconnect() throws IOException { if (__input != null) __input.close(); if (__output != null) __output.close(); super.disconnect(); } /*** * Returns the telnet connection output stream. You should not close the * stream when you finish with it. Rather, you should call * {@link #disconnect disconnect }. *

* @return The telnet connection output stream. ***/ public OutputStream getOutputStream() { return __output; } /*** * Returns the telnet connection input stream. You should not close the * stream when you finish with it. Rather, you should call * {@link #disconnect disconnect }. *

* @return The telnet connection input stream. ***/ public InputStream getInputStream() { return __input; } /*** * Returns the state of the option on the local side. *

* @param option - Option to be checked. *

* @return The state of the option on the local side. ***/ public boolean getLocalOptionState(int option) { /* BUG (option active when not already acknowledged) (start)*/ return (_stateIsWill(option) && _requestedWill(option)); /* BUG (option active when not already acknowledged) (end)*/ } /*** * Returns the state of the option on the remote side. *

* @param option - Option to be checked. *

* @return The state of the option on the remote side. ***/ public boolean getRemoteOptionState(int option) { /* BUG (option active when not already acknowledged) (start)*/ return (_stateIsDo(option) && _requestedDo(option)); /* BUG (option active when not already acknowledged) (end)*/ } /* open TelnetOptionHandler functionality (end)*/ /* Code Section added for supporting AYT (start)*/ /*** * Sends an Are You There sequence and waits for the result. *

* @param timeout - Time to wait for a response (millis.) *

* @return true if AYT received a response, false otherwise *

* @throws InterruptedException * @throws IllegalArgumentException * @throws IOException ***/ public boolean sendAYT(long timeout) throws IOException, IllegalArgumentException, InterruptedException { return (_sendAYT(timeout)); } /* Code Section added for supporting AYT (start)*/ /* open TelnetOptionHandler functionality (start)*/ /*** * Registers a new TelnetOptionHandler for this telnet client to use. *

* @param opthand - option handler to be registered. *

* @throws InvalidTelnetOptionException ***/ @Override public void addOptionHandler(TelnetOptionHandler opthand) throws InvalidTelnetOptionException { super.addOptionHandler(opthand); } /* open TelnetOptionHandler functionality (end)*/ /*** * Unregisters a TelnetOptionHandler. *

* @param optcode - Code of the option to be unregistered. *

* @throws InvalidTelnetOptionException ***/ @Override public void deleteOptionHandler(int optcode) throws InvalidTelnetOptionException { super.deleteOptionHandler(optcode); } /* Code Section added for supporting spystreams (start)*/ /*** * Registers an OutputStream for spying what's going on in * the TelnetClient session. *

* @param spystream - OutputStream on which session activity * will be echoed. ***/ public void registerSpyStream(OutputStream spystream) { super._registerSpyStream(spystream); } /*** * Stops spying this TelnetClient. *

***/ public void stopSpyStream() { super._stopSpyStream(); } /* Code Section added for supporting spystreams (end)*/ /*** * Registers a notification handler to which will be sent * notifications of received telnet option negotiation commands. *

* @param notifhand - TelnetNotificationHandler to be registered ***/ @Override public void registerNotifHandler(TelnetNotificationHandler notifhand) { super.registerNotifHandler(notifhand); } /*** * Unregisters the current notification handler. *

***/ @Override public void unregisterNotifHandler() { super.unregisterNotifHandler(); } /*** * Sets the status of the reader thread. * The reader thread status will apply to all subsequent connections *

* @param flag - true switches the reader thread on, false switches it off ***/ public void setReaderThread(boolean flag) { readerThread = flag; } /*** * Gets the status of the reader thread. *

* @return true if the reader thread is on, false otherwise ***/ public boolean getReaderThread() { return (readerThread); } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetOutputStream.java0000644000175000017500000001032411416072763030454 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import java.io.IOException; import java.io.OutputStream; /*** * *

* *

*

* @author Daniel F. Savarese ***/ final class TelnetOutputStream extends OutputStream { private final TelnetClient __client; // TODO there does not appear to be any way to change this value - should it be a ctor parameter? private boolean __convertCRtoCRLF = true; private boolean __lastWasCR = false; TelnetOutputStream(TelnetClient client) { __client = client; } /*** * Writes a byte to the stream. *

* @param ch The byte to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public void write(int ch) throws IOException { synchronized (__client) { ch &= 0xff; if (__client._requestedWont(TelnetOption.BINARY)) { if (__lastWasCR) { if (__convertCRtoCRLF) { __client._sendByte('\n'); if (ch == '\n') { __lastWasCR = false; return ; } } else if (ch != '\n') __client._sendByte('\0'); } __lastWasCR = false; switch (ch) { case '\r': __client._sendByte('\r'); __lastWasCR = true; break; case TelnetCommand.IAC: __client._sendByte(TelnetCommand.IAC); __client._sendByte(TelnetCommand.IAC); break; default: __client._sendByte(ch); break; } } else if (ch == TelnetCommand.IAC) { __client._sendByte(ch); __client._sendByte(TelnetCommand.IAC); } else __client._sendByte(ch); } } /*** * Writes a byte array to the stream. *

* @param buffer The byte array to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public void write(byte buffer[]) throws IOException { write(buffer, 0, buffer.length); } /*** * Writes a number of bytes from a byte array to the stream starting from * a given offset. *

* @param buffer The byte array to write. * @param offset The offset into the array at which to start copying data. * @param length The number of bytes to write. * @exception IOException If an error occurs while writing to the underlying * stream. ***/ @Override public void write(byte buffer[], int offset, int length) throws IOException { synchronized (__client) { while (length-- > 0) write(buffer[offset++]); } } /*** Flushes the stream. ***/ @Override public void flush() throws IOException { __client._flushOutputStream(); } /*** Closes the stream. ***/ @Override public void close() throws IOException { __client._closeOutputStream(); } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java0000644000175000017500000001041111416072763031725 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * Implements the telnet terminal type option RFC 1091. *

* @author Bruno D'Avanzo ***/ public class TerminalTypeOptionHandler extends TelnetOptionHandler { /*** * Terminal type ***/ private final String termType; /*** * Terminal type option ***/ protected static final int TERMINAL_TYPE = 24; /*** * Send (for subnegotiation) ***/ protected static final int TERMINAL_TYPE_SEND = 1; /*** * Is (for subnegotiation) ***/ protected static final int TERMINAL_TYPE_IS = 0; /*** * Constructor for the TerminalTypeOptionHandler. Allows defining desired * initial setting for local/remote activation of this option and * behaviour in case a local/remote activation request for this * option is received. *

* @param termtype - terminal type that will be negotiated. * @param initlocal - if set to true, a WILL is sent upon connection. * @param initremote - if set to true, a DO is sent upon connection. * @param acceptlocal - if set to true, any DO request is accepted. * @param acceptremote - if set to true, any WILL request is accepted. ***/ public TerminalTypeOptionHandler(String termtype, boolean initlocal, boolean initremote, boolean acceptlocal, boolean acceptremote) { super(TelnetOption.TERMINAL_TYPE, initlocal, initremote, acceptlocal, acceptremote); termType = termtype; } /*** * Constructor for the TerminalTypeOptionHandler. Initial and accept * behaviour flags are set to false *

* @param termtype - terminal type that will be negotiated. ***/ public TerminalTypeOptionHandler(String termtype) { super(TelnetOption.TERMINAL_TYPE, false, false, false, false); termType = termtype; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @param suboptionData - the sequence received, whithout IAC SB & IAC SE * @param suboptionLength - the length of data in suboption_data *

* @return terminal type information ***/ @Override public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { if ((suboptionData != null) && (suboptionLength > 1) && (termType != null)) { if ((suboptionData[0] == TERMINAL_TYPE) && (suboptionData[1] == TERMINAL_TYPE_SEND)) { int response[] = new int[termType.length() + 2]; response[0] = TERMINAL_TYPE; response[1] = TERMINAL_TYPE_IS; for (int ii = 0; ii < termType.length(); ii++) { response[ii + 2] = termType.charAt(ii); } return response; } } return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationLocal() { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationRemote() { return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/InvalidTelnetOptionException.java0000644000175000017500000000335511416072763032444 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * The InvalidTelnetOptionException is the exception that is * thrown whenever a TelnetOptionHandler with an invlaid * option code is registered in TelnetClient with addOptionHandler. *

* @author Bruno D'Avanzo ***/ public class InvalidTelnetOptionException extends Exception { /*** * Option code ***/ private final int optionCode; /*** * Error message ***/ private final String msg; /*** * Constructor for the exception. *

* @param message - Error message. * @param optcode - Option code. ***/ public InvalidTelnetOptionException(String message, int optcode) { optionCode = optcode; msg = message; } /*** * Gets the error message of ths exception. *

* @return the error message. ***/ @Override public String getMessage() { return (msg + ": " + optionCode); } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetCommand.java0000644000175000017500000001117410542533103027347 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /** * The TelnetCommand class cannot be instantiated and only serves as a * storehouse for telnet command constants. * @author Daniel F. Savarese * @see org.apache.commons.net.telnet.Telnet * @see org.apache.commons.net.telnet.TelnetClient */ public final class TelnetCommand { /*** The maximum value a command code can have. This value is 255. ***/ public static final int MAX_COMMAND_VALUE = 255; /*** Interpret As Command code. Value is 255 according to RFC 854. ***/ public static final int IAC = 255; /*** Don't use option code. Value is 254 according to RFC 854. ***/ public static final int DONT = 254; /*** Request to use option code. Value is 253 according to RFC 854. ***/ public static final int DO = 253; /*** Refuse to use option code. Value is 252 according to RFC 854. ***/ public static final int WONT = 252; /*** Agree to use option code. Value is 251 according to RFC 854. ***/ public static final int WILL = 251; /*** Start subnegotiation code. Value is 250 according to RFC 854. ***/ public static final int SB = 250; /*** Go Ahead code. Value is 249 according to RFC 854. ***/ public static final int GA = 249; /*** Erase Line code. Value is 248 according to RFC 854. ***/ public static final int EL = 248; /*** Erase Character code. Value is 247 according to RFC 854. ***/ public static final int EC = 247; /*** Are You There code. Value is 246 according to RFC 854. ***/ public static final int AYT = 246; /*** Abort Output code. Value is 245 according to RFC 854. ***/ public static final int AO = 245; /*** Interrupt Process code. Value is 244 according to RFC 854. ***/ public static final int IP = 244; /*** Break code. Value is 243 according to RFC 854. ***/ public static final int BREAK = 243; /*** Data mark code. Value is 242 according to RFC 854. ***/ public static final int DM = 242; /*** No Operation code. Value is 241 according to RFC 854. ***/ public static final int NOP = 241; /*** End subnegotiation code. Value is 240 according to RFC 854. ***/ public static final int SE = 240; /*** End of record code. Value is 239. ***/ public static final int EOR = 239; /*** Abort code. Value is 238. ***/ public static final int ABORT = 238; /*** Suspend process code. Value is 237. ***/ public static final int SUSP = 237; /*** End of file code. Value is 236. ***/ public static final int EOF = 236; /*** Synchronize code. Value is 242. ***/ public static final int SYNCH = 242; /*** String representations of commands. ***/ private static final String __commandString[] = { "IAC", "DONT", "DO", "WONT", "WILL", "SB", "GA", "EL", "EC", "AYT", "AO", "IP", "BRK", "DMARK", "NOP", "SE", "EOR", "ABORT", "SUSP", "EOF" }; private static final int __FIRST_COMMAND = IAC; private static final int __LAST_COMMAND = EOF; /*** * Returns the string representation of the telnet protocol command * corresponding to the given command code. *

* @param code The command code of the telnet protocol command. * @return The string representation of the telnet protocol command. ***/ public static final String getCommand(int code) { return __commandString[__FIRST_COMMAND - code]; } /*** * Determines if a given command code is valid. Returns true if valid, * false if not. *

* @param code The command code to test. * @return True if the command code is valid, false if not. **/ public static final boolean isValidCommand(int code) { return (code <= __FIRST_COMMAND && code >= __LAST_COMMAND); } // Cannot be instantiated private TelnetCommand() { } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/SuppressGAOptionHandler.java0000644000175000017500000000576010766271714031363 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * Implements the telnet suppress go ahead option RFC 858. *

* @author Bruno D'Avanzo ***/ public class SuppressGAOptionHandler extends TelnetOptionHandler { /*** * Constructor for the SuppressGAOptionHandler. Allows defining desired * initial setting for local/remote activation of this option and * behaviour in case a local/remote activation request for this * option is received. *

* @param initlocal - if set to true, a WILL is sent upon connection. * @param initremote - if set to true, a DO is sent upon connection. * @param acceptlocal - if set to true, any DO request is accepted. * @param acceptremote - if set to true, any WILL request is accepted. ***/ public SuppressGAOptionHandler(boolean initlocal, boolean initremote, boolean acceptlocal, boolean acceptremote) { super(TelnetOption.SUPPRESS_GO_AHEAD, initlocal, initremote, acceptlocal, acceptremote); } /*** * Constructor for the SuppressGAOptionHandler. Initial and accept * behaviour flags are set to false ***/ public SuppressGAOptionHandler() { super(TelnetOption.SUPPRESS_GO_AHEAD, false, false, false, false); } /*** * Implements the abstract method of TelnetOptionHandler. *

* @param suboptionData - the sequence received, whithout IAC SB & IAC SE * @param suboptionLength - the length of data in suboption_data *

* @return always null (no response to subnegotiation) ***/ @Override public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationLocal() { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationRemote() { return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/Telnet.java0000644000175000017500000010662511416437422026066 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.OutputStream; import java.io.IOException; import org.apache.commons.net.SocketClient; /** * @author Daniel F. Savarese * @author Bruno D'Avanzo */ class Telnet extends SocketClient { static final boolean debug = /*true;*/ false; static final boolean debugoptions = /*true;*/ false; static final byte[] _COMMAND_DO = { (byte)TelnetCommand.IAC, (byte)TelnetCommand.DO }; static final byte[] _COMMAND_DONT = { (byte)TelnetCommand.IAC, (byte)TelnetCommand.DONT }; static final byte[] _COMMAND_WILL = { (byte)TelnetCommand.IAC, (byte)TelnetCommand.WILL }; static final byte[] _COMMAND_WONT = { (byte)TelnetCommand.IAC, (byte)TelnetCommand.WONT }; static final byte[] _COMMAND_SB = { (byte)TelnetCommand.IAC, (byte)TelnetCommand.SB }; static final byte[] _COMMAND_SE = { (byte)TelnetCommand.IAC, (byte)TelnetCommand.SE }; static final int _WILL_MASK = 0x01, _DO_MASK = 0x02, _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08; /* public */ static final int DEFAULT_PORT = 23; int[] _doResponse, _willResponse, _options; /* TERMINAL-TYPE option (start)*/ /*** * Terminal type option ***/ protected static final int TERMINAL_TYPE = 24; /*** * Send (for subnegotiation) ***/ protected static final int TERMINAL_TYPE_SEND = 1; /*** * Is (for subnegotiation) ***/ protected static final int TERMINAL_TYPE_IS = 0; /*** * Is sequence (for subnegotiation) ***/ static final byte[] _COMMAND_IS = { (byte) TERMINAL_TYPE, (byte) TERMINAL_TYPE_IS }; /*** * Terminal type ***/ private String terminalType = null; /* TERMINAL-TYPE option (end)*/ /* open TelnetOptionHandler functionality (start)*/ /*** * Array of option handlers ***/ private TelnetOptionHandler optionHandlers[]; /* open TelnetOptionHandler functionality (end)*/ /* Code Section added for supporting AYT (start)*/ /*** * AYT sequence ***/ static final byte[] _COMMAND_AYT = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT }; /*** * monitor to wait for AYT ***/ private Object aytMonitor = new Object(); /*** * flag for AYT ***/ private boolean aytFlag = true; /* Code Section added for supporting AYT (end)*/ /*** * The stream on which to spy ***/ private volatile OutputStream spyStream = null; /*** * The notification handler ***/ private TelnetNotificationHandler __notifhand = null; /*** * Empty Constructor ***/ Telnet() { setDefaultPort(DEFAULT_PORT); _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1]; _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1]; _options = new int[TelnetOption.MAX_OPTION_VALUE + 1]; optionHandlers = new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1]; } /* TERMINAL-TYPE option (start)*/ /*** * This constructor lets you specify the terminal type. *

* @param termtype - terminal type to be negotiated (ej. VT100) ***/ Telnet(String termtype) { setDefaultPort(DEFAULT_PORT); _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1]; _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1]; _options = new int[TelnetOption.MAX_OPTION_VALUE + 1]; terminalType = termtype; optionHandlers = new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1]; } /* TERMINAL-TYPE option (end)*/ /*** * Looks for the state of the option. *

* @return returns true if a will has been acknowledged *

* @param option - option code to be looked up. ***/ boolean _stateIsWill(int option) { return ((_options[option] & _WILL_MASK) != 0); } /*** * Looks for the state of the option. *

* @return returns true if a wont has been acknowledged *

* @param option - option code to be looked up. ***/ boolean _stateIsWont(int option) { return !_stateIsWill(option); } /*** * Looks for the state of the option. *

* @return returns true if a do has been acknowledged *

* @param option - option code to be looked up. ***/ boolean _stateIsDo(int option) { return ((_options[option] & _DO_MASK) != 0); } /*** * Looks for the state of the option. *

* @return returns true if a dont has been acknowledged *

* @param option - option code to be looked up. ***/ boolean _stateIsDont(int option) { return !_stateIsDo(option); } /*** * Looks for the state of the option. *

* @return returns true if a will has been reuqested *

* @param option - option code to be looked up. ***/ boolean _requestedWill(int option) { return ((_options[option] & _REQUESTED_WILL_MASK) != 0); } /*** * Looks for the state of the option. *

* @return returns true if a wont has been reuqested *

* @param option - option code to be looked up. ***/ boolean _requestedWont(int option) { return !_requestedWill(option); } /*** * Looks for the state of the option. *

* @return returns true if a do has been reuqested *

* @param option - option code to be looked up. ***/ boolean _requestedDo(int option) { return ((_options[option] & _REQUESTED_DO_MASK) != 0); } /*** * Looks for the state of the option. *

* @return returns true if a dont has been reuqested *

* @param option - option code to be looked up. ***/ boolean _requestedDont(int option) { return !_requestedDo(option); } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setWill(int option) { _options[option] |= _WILL_MASK; /* open TelnetOptionHandler functionality (start)*/ if (_requestedWill(option)) { if (optionHandlers[option] != null) { optionHandlers[option].setWill(true); int subneg[] = optionHandlers[option].startSubnegotiationLocal(); if (subneg != null) { try { _sendSubnegotiation(subneg); } catch (IOException e) { System.err.println( "Exception in option subnegotiation" + e.getMessage()); } } } } /* open TelnetOptionHandler functionality (end)*/ } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setDo(int option) { _options[option] |= _DO_MASK; /* open TelnetOptionHandler functionality (start)*/ if (_requestedDo(option)) { if (optionHandlers[option] != null) { optionHandlers[option].setDo(true); int subneg[] = optionHandlers[option].startSubnegotiationRemote(); if (subneg != null) { try { _sendSubnegotiation(subneg); } catch (IOException e) { System.err.println("Exception in option subnegotiation" + e.getMessage()); } } } } /* open TelnetOptionHandler functionality (end)*/ } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setWantWill(int option) { _options[option] |= _REQUESTED_WILL_MASK; } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setWantDo(int option) { _options[option] |= _REQUESTED_DO_MASK; } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setWont(int option) { _options[option] &= ~_WILL_MASK; /* open TelnetOptionHandler functionality (start)*/ if (optionHandlers[option] != null) { optionHandlers[option].setWill(false); } /* open TelnetOptionHandler functionality (end)*/ } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setDont(int option) { _options[option] &= ~_DO_MASK; /* open TelnetOptionHandler functionality (start)*/ if (optionHandlers[option] != null) { optionHandlers[option].setDo(false); } /* open TelnetOptionHandler functionality (end)*/ } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setWantWont(int option) { _options[option] &= ~_REQUESTED_WILL_MASK; } /*** * Sets the state of the option. *

* @param option - option code to be set. ***/ void _setWantDont(int option) { _options[option] &= ~_REQUESTED_DO_MASK; } /** * Processes a COMMAND. * * @param command - option code to be set. **/ void _processCommand(int command) { if (debugoptions) { System.err.println("RECEIVED COMMAND: " + command); } if (__notifhand != null) { __notifhand.receivedNegotiation( TelnetNotificationHandler.RECEIVED_COMMAND, command); } } /** * Processes a DO request. * * @param option - option code to be set. * @throws IOException - Exception in I/O. **/ void _processDo(int option) throws IOException { if (debugoptions) { System.err.println("RECEIVED DO: " + TelnetOption.getOption(option)); } if (__notifhand != null) { __notifhand.receivedNegotiation( TelnetNotificationHandler.RECEIVED_DO, option); } boolean acceptNewState = false; /* open TelnetOptionHandler functionality (start)*/ if (optionHandlers[option] != null) { acceptNewState = optionHandlers[option].getAcceptLocal(); } else { /* open TelnetOptionHandler functionality (end)*/ /* TERMINAL-TYPE option (start)*/ if (option == TERMINAL_TYPE) { if ((terminalType != null) && (terminalType.length() > 0)) { acceptNewState = true; } } /* TERMINAL-TYPE option (end)*/ /* open TelnetOptionHandler functionality (start)*/ } /* open TelnetOptionHandler functionality (end)*/ if (_willResponse[option] > 0) { --_willResponse[option]; if (_willResponse[option] > 0 && _stateIsWill(option)) { --_willResponse[option]; } } if (_willResponse[option] == 0) { if (_requestedWont(option)) { switch (option) { default: break; } if (acceptNewState) { _setWantWill(option); _sendWill(option); } else { ++_willResponse[option]; _sendWont(option); } } else { // Other end has acknowledged option. switch (option) { default: break; } } } _setWill(option); } /** * Processes a DONT request. * * @param option - option code to be set. * @throws IOException - Exception in I/O. **/ void _processDont(int option) throws IOException { if (debugoptions) { System.err.println("RECEIVED DONT: " + TelnetOption.getOption(option)); } if (__notifhand != null) { __notifhand.receivedNegotiation( TelnetNotificationHandler.RECEIVED_DONT, option); } if (_willResponse[option] > 0) { --_willResponse[option]; if (_willResponse[option] > 0 && _stateIsWont(option)) { --_willResponse[option]; } } if (_willResponse[option] == 0 && _requestedWill(option)) { switch (option) { default: break; } /* FIX for a BUG in the negotiation (start)*/ if ((_stateIsWill(option)) || (_requestedWill(option))) { _sendWont(option); } _setWantWont(option); /* FIX for a BUG in the negotiation (end)*/ } _setWont(option); } /** * Processes a WILL request. * * @param option - option code to be set. * @throws IOException - Exception in I/O. **/ void _processWill(int option) throws IOException { if (debugoptions) { System.err.println("RECEIVED WILL: " + TelnetOption.getOption(option)); } if (__notifhand != null) { __notifhand.receivedNegotiation( TelnetNotificationHandler.RECEIVED_WILL, option); } boolean acceptNewState = false; /* open TelnetOptionHandler functionality (start)*/ if (optionHandlers[option] != null) { acceptNewState = optionHandlers[option].getAcceptRemote(); } /* open TelnetOptionHandler functionality (end)*/ if (_doResponse[option] > 0) { --_doResponse[option]; if (_doResponse[option] > 0 && _stateIsDo(option)) { --_doResponse[option]; } } if (_doResponse[option] == 0 && _requestedDont(option)) { switch (option) { default: break; } if (acceptNewState) { _setWantDo(option); _sendDo(option); } else { ++_doResponse[option]; _sendDont(option); } } _setDo(option); } /** * Processes a WONT request. * * @param option - option code to be set. * @throws IOException - Exception in I/O. **/ void _processWont(int option) throws IOException { if (debugoptions) { System.err.println("RECEIVED WONT: " + TelnetOption.getOption(option)); } if (__notifhand != null) { __notifhand.receivedNegotiation( TelnetNotificationHandler.RECEIVED_WONT, option); } if (_doResponse[option] > 0) { --_doResponse[option]; if (_doResponse[option] > 0 && _stateIsDont(option)) { --_doResponse[option]; } } if (_doResponse[option] == 0 && _requestedDo(option)) { switch (option) { default: break; } /* FIX for a BUG in the negotiation (start)*/ if ((_stateIsDo(option)) || (_requestedDo(option))) { _sendDont(option); } _setWantDont(option); /* FIX for a BUG in the negotiation (end)*/ } _setDont(option); } /* TERMINAL-TYPE option (start)*/ /** * Processes a suboption negotiation. * * @param suboption - subnegotiation data received * @param suboptionLength - length of data received * @throws IOException - Exception in I/O. **/ void _processSuboption(int suboption[], int suboptionLength) throws IOException { if (debug) { System.err.println("PROCESS SUBOPTION."); } /* open TelnetOptionHandler functionality (start)*/ if (suboptionLength > 0) { if (optionHandlers[suboption[0]] != null) { int responseSuboption[] = optionHandlers[suboption[0]].answerSubnegotiation(suboption, suboptionLength); _sendSubnegotiation(responseSuboption); } else { if (suboptionLength > 1) { if (debug) { for (int ii = 0; ii < suboptionLength; ii++) { System.err.println("SUB[" + ii + "]: " + suboption[ii]); } } if ((suboption[0] == TERMINAL_TYPE) && (suboption[1] == TERMINAL_TYPE_SEND)) { _sendTerminalType(); } } } } /* open TelnetOptionHandler functionality (end)*/ } /*** * Sends terminal type information. *

* @throws IOException - Exception in I/O. ***/ final synchronized void _sendTerminalType() throws IOException { if (debug) { System.err.println("SEND TERMINAL-TYPE: " + terminalType); } if (terminalType != null) { _output_.write(_COMMAND_SB); _output_.write(_COMMAND_IS); _output_.write(terminalType.getBytes()); _output_.write(_COMMAND_SE); _output_.flush(); } } /* TERMINAL-TYPE option (end)*/ /* open TelnetOptionHandler functionality (start)*/ /** * Manages subnegotiation for Terminal Type. * * @param subn - subnegotiation data to be sent * @throws IOException - Exception in I/O. **/ final synchronized void _sendSubnegotiation(int subn[]) throws IOException { if (debug) { System.err.println("SEND SUBNEGOTIATION: "); if (subn != null) { for (int ii = 0; ii < subn.length; ii++) { System.err.println("subn[" + ii + "]=" + subn[ii]); } } } if (subn != null) { byte byteresp[] = new byte[subn.length]; for (int ii = 0; ii < subn.length; ii++) { byteresp[ii] = (byte) subn[ii]; } _output_.write(_COMMAND_SB); _output_.write(byteresp); _output_.write(_COMMAND_SE); /* Code Section added for sending the negotiation ASAP (start)*/ _output_.flush(); /* Code Section added for sending the negotiation ASAP (end)*/ } } /* open TelnetOptionHandler functionality (end)*/ /* Code Section added for supporting AYT (start)*/ /*** * Processes the response of an AYT ***/ final synchronized void _processAYTResponse() { if (!aytFlag) { synchronized (aytMonitor) { aytFlag = true; try { aytMonitor.notifyAll(); } catch (IllegalMonitorStateException e) { System.err.println("Exception notifying:" + e.getMessage()); } } } } /* Code Section added for supporting AYT (end)*/ /*** * Called upon connection. *

* @throws IOException - Exception in I/O. ***/ @Override protected void _connectAction_() throws IOException { /* (start). BUGFIX: clean the option info for each connection*/ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++) { _doResponse[ii] = 0; _willResponse[ii] = 0; _options[ii] = 0; if (optionHandlers[ii] != null) { optionHandlers[ii].setDo(false); optionHandlers[ii].setWill(false); } } /* (end). BUGFIX: clean the option info for each connection*/ super._connectAction_(); _input_ = new BufferedInputStream(_input_); _output_ = new BufferedOutputStream(_output_); /* open TelnetOptionHandler functionality (start)*/ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++) { if (optionHandlers[ii] != null) { if (optionHandlers[ii].getInitLocal()) { try { _requestWill(optionHandlers[ii].getOptionCode()); } catch (IOException e) { System.err.println( "Exception while initializing option: " + e.getMessage()); } } if (optionHandlers[ii].getInitRemote()) { try { _requestDo(optionHandlers[ii].getOptionCode()); } catch (IOException e) { System.err.println( "Exception while initializing option: " + e.getMessage()); } } } } /* open TelnetOptionHandler functionality (end)*/ } /** * Sends a DO. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _sendDo(int option) throws IOException { if (debug || debugoptions) { System.err.println("DO: " + TelnetOption.getOption(option)); } _output_.write(_COMMAND_DO); _output_.write(option); /* Code Section added for sending the negotiation ASAP (start)*/ _output_.flush(); /* Code Section added for sending the negotiation ASAP (end)*/ } /** * Requests a DO. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _requestDo(int option) throws IOException { if ((_doResponse[option] == 0 && _stateIsDo(option)) || _requestedDo(option)) { return ; } _setWantDo(option); ++_doResponse[option]; _sendDo(option); } /** * Sends a DONT. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _sendDont(int option) throws IOException { if (debug || debugoptions) { System.err.println("DONT: " + TelnetOption.getOption(option)); } _output_.write(_COMMAND_DONT); _output_.write(option); /* Code Section added for sending the negotiation ASAP (start)*/ _output_.flush(); /* Code Section added for sending the negotiation ASAP (end)*/ } /** * Requests a DONT. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _requestDont(int option) throws IOException { if ((_doResponse[option] == 0 && _stateIsDont(option)) || _requestedDont(option)) { return ; } _setWantDont(option); ++_doResponse[option]; _sendDont(option); } /** * Sends a WILL. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _sendWill(int option) throws IOException { if (debug || debugoptions) { System.err.println("WILL: " + TelnetOption.getOption(option)); } _output_.write(_COMMAND_WILL); _output_.write(option); /* Code Section added for sending the negotiation ASAP (start)*/ _output_.flush(); /* Code Section added for sending the negotiation ASAP (end)*/ } /** * Requests a WILL. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _requestWill(int option) throws IOException { if ((_willResponse[option] == 0 && _stateIsWill(option)) || _requestedWill(option)) { return ; } _setWantWill(option); ++_doResponse[option]; _sendWill(option); } /** * Sends a WONT. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _sendWont(int option) throws IOException { if (debug || debugoptions) { System.err.println("WONT: " + TelnetOption.getOption(option)); } _output_.write(_COMMAND_WONT); _output_.write(option); /* Code Section added for sending the negotiation ASAP (start)*/ _output_.flush(); /* Code Section added for sending the negotiation ASAP (end)*/ } /** * Requests a WONT. * * @param option - Option code. * @throws IOException - Exception in I/O. **/ final synchronized void _requestWont(int option) throws IOException { if ((_willResponse[option] == 0 && _stateIsWont(option)) || _requestedWont(option)) { return ; } _setWantWont(option); ++_doResponse[option]; _sendWont(option); } /** * Sends a byte. * * @param b - byte to send * @throws IOException - Exception in I/O. **/ final synchronized void _sendByte(int b) throws IOException { _output_.write(b); /* Code Section added for supporting spystreams (start)*/ _spyWrite(b); /* Code Section added for supporting spystreams (end)*/ } /* Code Section added for supporting AYT (start)*/ /** * Sends an Are You There sequence and waits for the result. * * @param timeout - Time to wait for a response (millis.) * @throws IOException - Exception in I/O. * @throws IllegalArgumentException - Illegal argument * @throws InterruptedException - Interrupted during wait. * @return true if AYT received a response, false otherwise **/ final boolean _sendAYT(long timeout) throws IOException, IllegalArgumentException, InterruptedException { boolean retValue = false; synchronized (aytMonitor) { synchronized (this) { aytFlag = false; _output_.write(_COMMAND_AYT); _output_.flush(); } try { aytMonitor.wait(timeout); if (aytFlag == false) { retValue = false; aytFlag = true; } else { retValue = true; } } catch (IllegalMonitorStateException e) { System.err.println("Exception processing AYT:" + e.getMessage()); } } return (retValue); } /* Code Section added for supporting AYT (end)*/ /* open TelnetOptionHandler functionality (start)*/ /** * Registers a new TelnetOptionHandler for this telnet to use. * * @param opthand - option handler to be registered. * @throws InvalidTelnetOptionException - The option code is invalid. **/ void addOptionHandler(TelnetOptionHandler opthand) throws InvalidTelnetOptionException { int optcode = opthand.getOptionCode(); if (TelnetOption.isValidOption(optcode)) { if (optionHandlers[optcode] == null) { optionHandlers[optcode] = opthand; if (isConnected()) { if (opthand.getInitLocal()) { try { _requestWill(optcode); } catch (IOException e) { System.err.println( "Exception while initializing option: " + e.getMessage()); } } if (opthand.getInitRemote()) { try { _requestDo(optcode); } catch (IOException e) { System.err.println( "Exception while initializing option: " + e.getMessage()); } } } } else { throw (new InvalidTelnetOptionException( "Already registered option", optcode)); } } else { throw (new InvalidTelnetOptionException( "Invalid Option Code", optcode)); } } /** * Unregisters a TelnetOptionHandler. * * @param optcode - Code of the option to be unregistered. * @throws InvalidTelnetOptionException - The option code is invalid. **/ void deleteOptionHandler(int optcode) throws InvalidTelnetOptionException { if (TelnetOption.isValidOption(optcode)) { if (optionHandlers[optcode] == null) { throw (new InvalidTelnetOptionException( "Unregistered option", optcode)); } else { TelnetOptionHandler opthand = optionHandlers[optcode]; optionHandlers[optcode] = null; if (opthand.getWill()) { try { _requestWont(optcode); } catch (IOException e) { System.err.println( "Exception while turning off option: " + e.getMessage()); } } if (opthand.getDo()) { try { _requestDont(optcode); } catch (IOException e) { System.err.println( "Exception while turning off option: " + e.getMessage()); } } } } else { throw (new InvalidTelnetOptionException( "Invalid Option Code", optcode)); } } /* open TelnetOptionHandler functionality (end)*/ /* Code Section added for supporting spystreams (start)*/ /*** * Registers an OutputStream for spying what's going on in * the Telnet session. *

* @param spystream - OutputStream on which session activity * will be echoed. ***/ void _registerSpyStream(OutputStream spystream) { spyStream = spystream; } /*** * Stops spying this Telnet. *

***/ void _stopSpyStream() { spyStream = null; } /*** * Sends a read char on the spy stream. *

* @param ch - character read from the session ***/ void _spyRead(int ch) { OutputStream spy = spyStream; if (spy != null) { try { if (ch != '\r') { spy.write(ch); if (ch == '\n') { spy.write('\r'); } spy.flush(); } } catch (IOException e) { spyStream = null; } } } /*** * Sends a written char on the spy stream. *

* @param ch - character written to the session ***/ void _spyWrite(int ch) { if (!(_stateIsDo(TelnetOption.ECHO) && _requestedDo(TelnetOption.ECHO))) { OutputStream spy = spyStream; if (spy != null) { try { spy.write(ch); spy.flush(); } catch (IOException e) { spyStream = null; } } } } /* Code Section added for supporting spystreams (end)*/ /*** * Registers a notification handler to which will be sent * notifications of received telnet option negotiation commands. *

* @param notifhand - TelnetNotificationHandler to be registered ***/ public void registerNotifHandler(TelnetNotificationHandler notifhand) { __notifhand = notifhand; } /*** * Unregisters the current notification handler. *

***/ public void unregisterNotifHandler() { __notifhand = null; } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetNotificationHandler.java0000644000175000017500000000446011466231525031726 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * The TelnetNotificationHandler interface can be used to handle * notification of options negotiation commands received on a telnet * session. *

* The user can implement this interface and register a * TelnetNotificationHandler by using the registerNotificationHandler() * of TelnetClient to be notified of option negotiation commands. *

*

* @author Bruno D'Avanzo ***/ public interface TelnetNotificationHandler { /*** * The remote party sent a DO command. ***/ public static final int RECEIVED_DO = 1; /*** * The remote party sent a DONT command. ***/ public static final int RECEIVED_DONT = 2; /*** * The remote party sent a WILL command. ***/ public static final int RECEIVED_WILL = 3; /*** * The remote party sent a WONT command. ***/ public static final int RECEIVED_WONT = 4; /*** * The remote party sent a COMMAND. * @since 2.2 ***/ public static final int RECEIVED_COMMAND = 5; /*** * Callback method called when TelnetClient receives an * command or option negotiation command *

* @param negotiation_code - type of (negotiation) command received * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT, RECEIVED_COMMAND) *

* @param option_code - code of the option negotiated, or the command code itself (e.g. NOP). *

***/ public void receivedNegotiation(int negotiation_code, int option_code); } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/EchoOptionHandler.java0000644000175000017500000000572310766271714030204 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * Implements the telnet echo option RFC 857. *

* @author Bruno D'Avanzo ***/ public class EchoOptionHandler extends TelnetOptionHandler { /*** * Constructor for the EchoOptionHandler. Allows defining desired * initial setting for local/remote activation of this option and * behaviour in case a local/remote activation request for this * option is received. *

* @param initlocal - if set to true, a WILL is sent upon connection. * @param initremote - if set to true, a DO is sent upon connection. * @param acceptlocal - if set to true, any DO request is accepted. * @param acceptremote - if set to true, any WILL request is accepted. ***/ public EchoOptionHandler(boolean initlocal, boolean initremote, boolean acceptlocal, boolean acceptremote) { super(TelnetOption.ECHO, initlocal, initremote, acceptlocal, acceptremote); } /*** * Constructor for the EchoOptionHandler. Initial and accept * behaviour flags are set to false ***/ public EchoOptionHandler() { super(TelnetOption.ECHO, false, false, false, false); } /*** * Implements the abstract method of TelnetOptionHandler. *

* @param suboptionData - the sequence received, whithout IAC SB & IAC SE * @param suboptionLength - the length of data in suboption_data *

* @return always null (no response to subnegotiation) ***/ @Override public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationLocal() { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

* @return always null (no response to subnegotiation) ***/ @Override public int[] startSubnegotiationRemote() { return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/telnet/TelnetOptionHandler.java0000644000175000017500000002016410542533103030536 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * The TelnetOptionHandler class is the base class to be used * for implementing handlers for telnet options. *

* TelnetOptionHandler implements basic option handling * functionality and defines abstract methods that must be * implemented to define subnegotiation behaviour. *

* @author Bruno D'Avanzo ***/ public abstract class TelnetOptionHandler { /*** * Option code ***/ private int optionCode = -1; /*** * true if the option should be activated on the local side ***/ private boolean initialLocal = false; /*** * true if the option should be activated on the remote side ***/ private boolean initialRemote = false; /*** * true if the option should be accepted on the local side ***/ private boolean acceptLocal = false; /*** * true if the option should be accepted on the remote side ***/ private boolean acceptRemote = false; /*** * true if the option is active on the local side ***/ private boolean doFlag = false; /*** * true if the option is active on the remote side ***/ private boolean willFlag = false; /*** * Constructor for the TelnetOptionHandler. Allows defining desired * initial setting for local/remote activation of this option and * behaviour in case a local/remote activation request for this * option is received. *

* @param optcode - Option code. * @param initlocal - if set to true, a WILL is sent upon connection. * @param initremote - if set to true, a DO is sent upon connection. * @param acceptlocal - if set to true, any DO request is accepted. * @param acceptremote - if set to true, any WILL request is accepted. ***/ public TelnetOptionHandler(int optcode, boolean initlocal, boolean initremote, boolean acceptlocal, boolean acceptremote) { optionCode = optcode; initialLocal = initlocal; initialRemote = initremote; acceptLocal = acceptlocal; acceptRemote = acceptremote; } /*** * Returns the option code for this option. *

* @return Option code. ***/ public int getOptionCode() { return (optionCode); } /*** * Returns a boolean indicating whether to accept a DO * request coming from the other end. *

* @return true if a DO request shall be accepted. ***/ public boolean getAcceptLocal() { return (acceptLocal); } /*** * Returns a boolean indicating whether to accept a WILL * request coming from the other end. *

* @return true if a WILL request shall be accepted. ***/ public boolean getAcceptRemote() { return (acceptRemote); } /*** * Set behaviour of the option for DO requests coming from * the other end. *

* @param accept - if true, subsequent DO requests will be accepted. ***/ public void setAcceptLocal(boolean accept) { acceptLocal = accept; } /*** * Set behaviour of the option for WILL requests coming from * the other end. *

* @param accept - if true, subsequent WILL requests will be accepted. ***/ public void setAcceptRemote(boolean accept) { acceptRemote = accept; } /*** * Returns a boolean indicating whether to send a WILL request * to the other end upon connection. *

* @return true if a WILL request shall be sent upon connection. ***/ public boolean getInitLocal() { return (initialLocal); } /*** * Returns a boolean indicating whether to send a DO request * to the other end upon connection. *

* @return true if a DO request shall be sent upon connection. ***/ public boolean getInitRemote() { return (initialRemote); } /*** * Tells this option whether to send a WILL request upon connection. *

* @param init - if true, a WILL request will be sent upon subsequent * connections. ***/ public void setInitLocal(boolean init) { initialLocal = init; } /*** * Tells this option whether to send a DO request upon connection. *

* @param init - if true, a DO request will be sent upon subsequent * connections. ***/ public void setInitRemote(boolean init) { initialRemote = init; } /*** * Method called upon reception of a subnegotiation for this option * coming from the other end. * Must be implemented by the actual TelnetOptionHandler to specify * which response must be sent for the subnegotiation request. *

* @param suboptionData - the sequence received, whithout IAC SB & IAC SE * @param suboptionLength - the length of data in suboption_data *

* @return response to be sent to the subnegotiation sequence. TelnetClient * will add IAC SB & IAC SE. null means no response ***/ public abstract int[] answerSubnegotiation(int suboptionData[], int suboptionLength); /*** * This method is invoked whenever this option is acknowledged active on * the local end (TelnetClient sent a WILL, remote side sent a DO). * The method is used to specify a subnegotiation sequence that will be * sent by TelnetClient when the option is activated. *

* @return subnegotiation sequence to be sent by TelnetClient. TelnetClient * will add IAC SB & IAC SE. null means no subnegotiation. ***/ public abstract int[] startSubnegotiationLocal(); /*** * This method is invoked whenever this option is acknowledged active on * the remote end (TelnetClient sent a DO, remote side sent a WILL). * The method is used to specify a subnegotiation sequence that will be * sent by TelnetClient when the option is activated. *

* @return subnegotiation sequence to be sent by TelnetClient. TelnetClient * will add IAC SB & IAC SE. null means no subnegotiation. ***/ public abstract int[] startSubnegotiationRemote(); /*** * Returns a boolean indicating whether a WILL request sent to the other * side has been acknowledged. *

* @return true if a WILL sent to the other side has been acknowledged. ***/ boolean getWill() { return willFlag; } /*** * Tells this option whether a WILL request sent to the other * side has been acknowledged (invoked by TelnetClient). *

* @param state - if true, a WILL request has been acknowledged. ***/ void setWill(boolean state) { willFlag = state; } /*** * Returns a boolean indicating whether a DO request sent to the other * side has been acknowledged. *

* @return true if a DO sent to the other side has been acknowledged. ***/ boolean getDo() { return doFlag; } /*** * Tells this option whether a DO request sent to the other * side has been acknowledged (invoked by TelnetClient). *

* @param state - if true, a DO request has been acknowledged. ***/ void setDo(boolean state) { doFlag = state; } } commons-net-2.2/src/main/java/org/apache/commons/net/time/0000755000175000017500000000000011617452467023432 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/time/TimeUDPClient.java0000644000175000017500000001113311416072763026674 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.time; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.util.Date; import org.apache.commons.net.DatagramSocketClient; /*** * The TimeUDPClient class is a UDP implementation of a client for the * Time protocol described in RFC 868. To use the class, merely * open a local datagram socket with * {@link org.apache.commons.net.DatagramSocketClient#open open } * and call {@link #getTime getTime } or * {@link #getTime getDate } to retrieve the time. Then call * {@link org.apache.commons.net.DatagramSocketClient#close close } * to close the connection properly. Unlike * {@link org.apache.commons.net.time.TimeTCPClient}, * successive calls to {@link #getTime getTime } or * {@link #getDate getDate } are permitted * without re-establishing a connection. That is because UDP is a * connectionless protocol and the Time protocol is stateless. *

*

* @author Daniel F. Savarese * @see TimeTCPClient ***/ public final class TimeUDPClient extends DatagramSocketClient { /*** The default time port. It is set to 37 according to RFC 868. ***/ public static final int DEFAULT_PORT = 37; /*** * The number of seconds between 00:00 1 January 1900 and * 00:00 1 January 1970. This value can be useful for converting * time values to other formats. ***/ public static final long SECONDS_1900_TO_1970 = 2208988800L; private final byte[] __dummyData = new byte[1]; private final byte[] __timeData = new byte[4]; /*** * Retrieves the time from the specified server and port and * returns it. The time is the number of seconds since * 00:00 (midnight) 1 January 1900 GMT, as specified by RFC 868. * This method reads the raw 32-bit big-endian * unsigned integer from the server, converts it to a Java long, and * returns the value. *

* @param host The address of the server. * @param port The port of the service. * @return The time value retrieved from the server. * @exception IOException If an error occurs while retrieving the time. ***/ public long getTime(InetAddress host, int port) throws IOException { long time; DatagramPacket sendPacket, receivePacket; sendPacket = new DatagramPacket(__dummyData, __dummyData.length, host, port); receivePacket = new DatagramPacket(__timeData, __timeData.length); _socket_.send(sendPacket); _socket_.receive(receivePacket); time = 0L; time |= (((__timeData[0] & 0xff) << 24) & 0xffffffffL); time |= (((__timeData[1] & 0xff) << 16) & 0xffffffffL); time |= (((__timeData[2] & 0xff) << 8) & 0xffffffffL); time |= ((__timeData[3] & 0xff) & 0xffffffffL); return time; } /*** Same as getTime(host, DEFAULT_PORT); ***/ public long getTime(InetAddress host) throws IOException { return getTime(host, DEFAULT_PORT); } /*** * Retrieves the time from the server and returns a Java Date * containing the time converted to the local timezone. *

* @param host The address of the server. * @param port The port of the service. * @return A Date value containing the time retrieved from the server * converted to the local timezone. * @exception IOException If an error occurs while fetching the time. ***/ public Date getDate(InetAddress host, int port) throws IOException { return new Date((getTime(host, port) - SECONDS_1900_TO_1970)*1000L); } /*** Same as getTime(host, DEFAULT_PORT); ***/ public Date getDate(InetAddress host) throws IOException { return new Date((getTime(host, DEFAULT_PORT) - SECONDS_1900_TO_1970)*1000L); } } commons-net-2.2/src/main/java/org/apache/commons/net/time/TimeTCPClient.java0000644000175000017500000001002310766054003026661 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.time; import java.io.DataInputStream; import java.io.IOException; import java.util.Date; import org.apache.commons.net.SocketClient; /*** * The TimeTCPClient class is a TCP implementation of a client for the * Time protocol described in RFC 868. To use the class, merely * establish a connection with * {@link org.apache.commons.net.SocketClient#connect connect } * and call either {@link #getTime getTime() } or * {@link #getDate getDate() } to retrieve the time, then * call {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to close the connection properly. *

*

* @author Daniel F. Savarese * @see TimeUDPClient ***/ public final class TimeTCPClient extends SocketClient { /*** The default time port. It is set to 37 according to RFC 868. ***/ public static final int DEFAULT_PORT = 37; /*** * The number of seconds between 00:00 1 January 1900 and * 00:00 1 January 1970. This value can be useful for converting * time values to other formats. ***/ public static final long SECONDS_1900_TO_1970 = 2208988800L; /*** * The default TimeTCPClient constructor. It merely sets the default * port to DEFAULT_PORT . ***/ public TimeTCPClient () { setDefaultPort(DEFAULT_PORT); } /*** * Retrieves the time from the server and returns it. The time * is the number of seconds since 00:00 (midnight) 1 January 1900 GMT, * as specified by RFC 868. This method reads the raw 32-bit big-endian * unsigned integer from the server, converts it to a Java long, and * returns the value. *

* The server will have closed the connection at this point, so you should * call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * after calling this method. To retrieve another time, you must * initiate another connection with * {@link org.apache.commons.net.SocketClient#connect connect } * before calling getTime() again. *

* @return The time value retrieved from the server. * @exception IOException If an error occurs while fetching the time. ***/ public long getTime() throws IOException { DataInputStream input; input = new DataInputStream(_input_); return (input.readInt() & 0xffffffffL); } /*** * Retrieves the time from the server and returns a Java Date * containing the time converted to the local timezone. *

* The server will have closed the connection at this point, so you should * call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * after calling this method. To retrieve another time, you must * initiate another connection with * {@link org.apache.commons.net.SocketClient#connect connect } * before calling getDate() again. *

* @return A Date value containing the time retrieved from the server * converted to the local timezone. * @exception IOException If an error occurs while fetching the time. ***/ public Date getDate() throws IOException { return new Date((getTime() - SECONDS_1900_TO_1970)*1000L); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/0000755000175000017500000000000011617452467023265 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPConnectionClosedException.java0000644000175000017500000000353710542533103031601 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.IOException; /*** * FTPConnectionClosedException is used to indicate the premature or * unexpected closing of an FTP connection resulting from a * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE } * response (FTP reply code 421) to a * failed FTP command. This exception is derived from IOException and * therefore may be caught either as an IOException or specifically as an * FTPConnectionClosedException. *

*

* @author Daniel F. Savarese * @see FTP * @see FTPClient ***/ public class FTPConnectionClosedException extends IOException { /*** Constructs a FTPConnectionClosedException with no message ***/ public FTPConnectionClosedException() { super(); } /*** * Constructs a FTPConnectionClosedException with a specified message. *

* @param message The message explaining the reason for the exception. ***/ public FTPConnectionClosedException(String message) { super(message); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPSTrustManager.java0000644000175000017500000000342011416066410027222 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; /** * Custom {@link TrustManager} implementation. * * @version $Id: FTPSTrustManager.java 962837 2010-07-10 12:52:24Z sebb $ * @since 2.0 */ public class FTPSTrustManager implements X509TrustManager { private static final X509Certificate[] EMPTY_X509CERTIFICATE_ARRAY = new X509Certificate[]{}; /** * No-op */ public void checkClientTrusted(X509Certificate[] certificates, String authType) { return; } public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException { for (int i = 0; i < certificates.length; ++i) { certificates[i].checkValidity(); } } public X509Certificate[] getAcceptedIssuers() { return EMPTY_X509CERTIFICATE_ARRAY; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/Configurable.java0000644000175000017500000000247611014664535026531 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; /** * This interface adds the aspect of configurability by means of * a supplied FTPClientConfig object to other classes in the * system, especially listing parsers. */ public interface Configurable { /** * @param config the object containing the configuration data * @throws IllegalArgumentException if the elements of the * config are somehow inadequate to configure the * Configurable object. */ public void configure(FTPClientConfig config); } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPFile.java0000644000175000017500000002360111352735312025350 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.Serializable; import java.util.Calendar; /*** * The FTPFile class is used to represent information about files stored * on an FTP server. *

*

* @author Daniel F. Savarese * @see FTPFileEntryParser * @see FTPClient#listFiles ***/ public class FTPFile implements Serializable { /** A constant indicating an FTPFile is a file. ***/ public static final int FILE_TYPE = 0; /** A constant indicating an FTPFile is a directory. ***/ public static final int DIRECTORY_TYPE = 1; /** A constant indicating an FTPFile is a symbolic link. ***/ public static final int SYMBOLIC_LINK_TYPE = 2; /** A constant indicating an FTPFile is of unknown type. ***/ public static final int UNKNOWN_TYPE = 3; /** A constant indicating user access permissions. ***/ public static final int USER_ACCESS = 0; /** A constant indicating group access permissions. ***/ public static final int GROUP_ACCESS = 1; /** A constant indicating world access permissions. ***/ public static final int WORLD_ACCESS = 2; /** A constant indicating file/directory read permission. ***/ public static final int READ_PERMISSION = 0; /** A constant indicating file/directory write permission. ***/ public static final int WRITE_PERMISSION = 1; /** * A constant indicating file execute permission or directory listing * permission. ***/ public static final int EXECUTE_PERMISSION = 2; int _type, _hardLinkCount; long _size; String _rawListing, _user, _group, _name, _link; Calendar _date; boolean[] _permissions[]; /*** Creates an empty FTPFile. ***/ public FTPFile() { _permissions = new boolean[3][3]; _rawListing = null; _type = UNKNOWN_TYPE; _hardLinkCount = 0; _size = 0; _user = null; _group = null; _date = null; _name = null; } /*** * Set the original FTP server raw listing from which the FTPFile was * created. *

* @param rawListing The raw FTP server listing. ***/ public void setRawListing(String rawListing) { _rawListing = rawListing; } /*** * Get the original FTP server raw listing used to initialize the FTPFile. *

* @return The original FTP server raw listing used to initialize the * FTPFile. ***/ public String getRawListing() { return _rawListing; } /*** * Determine if the file is a directory. *

* @return True if the file is of type DIRECTORY_TYPE, false if * not. ***/ public boolean isDirectory() { return (_type == DIRECTORY_TYPE); } /*** * Determine if the file is a regular file. *

* @return True if the file is of type FILE_TYPE, false if * not. ***/ public boolean isFile() { return (_type == FILE_TYPE); } /*** * Determine if the file is a symbolic link. *

* @return True if the file is of type UNKNOWN_TYPE, false if * not. ***/ public boolean isSymbolicLink() { return (_type == SYMBOLIC_LINK_TYPE); } /*** * Determine if the type of the file is unknown. *

* @return True if the file is of type UNKNOWN_TYPE, false if * not. ***/ public boolean isUnknown() { return (_type == UNKNOWN_TYPE); } /*** * Set the type of the file (DIRECTORY_TYPE, * FILE_TYPE, etc.). *

* @param type The integer code representing the type of the file. ***/ public void setType(int type) { _type = type; } /*** * Return the type of the file (one of the _TYPE constants), * e.g., if it is a directory, a regular file, or a symbolic link. *

* @return The type of the file. ***/ public int getType() { return _type; } /*** * Set the name of the file. *

* @param name The name of the file. ***/ public void setName(String name) { _name = name; } /*** * Return the name of the file. *

* @return The name of the file. ***/ public String getName() { return _name; } /** * Set the file size in bytes. * @param size The file size in bytes. */ public void setSize(long size) { _size = size; } /*** * Return the file size in bytes. *

* @return The file size in bytes. ***/ public long getSize() { return _size; } /*** * Set the number of hard links to this file. This is not to be * confused with symbolic links. *

* @param links The number of hard links to this file. ***/ public void setHardLinkCount(int links) { _hardLinkCount = links; } /*** * Return the number of hard links to this file. This is not to be * confused with symbolic links. *

* @return The number of hard links to this file. ***/ public int getHardLinkCount() { return _hardLinkCount; } /*** * Set the name of the group owning the file. This may be * a string representation of the group number. *

* @param group The name of the group owning the file. ***/ public void setGroup(String group) { _group = group; } /*** * Returns the name of the group owning the file. Sometimes this will be * a string representation of the group number. *

* @return The name of the group owning the file. ***/ public String getGroup() { return _group; } /*** * Set the name of the user owning the file. This may be * a string representation of the user number; *

* @param user The name of the user owning the file. ***/ public void setUser(String user) { _user = user; } /*** * Returns the name of the user owning the file. Sometimes this will be * a string representation of the user number. *

* @return The name of the user owning the file. ***/ public String getUser() { return _user; } /*** * If the FTPFile is a symbolic link, use this method to set the name of the * file being pointed to by the symbolic link. *

* @param link The file pointed to by the symbolic link. ***/ public void setLink(String link) { _link = link; } /*** * If the FTPFile is a symbolic link, this method returns the name of the * file being pointed to by the symbolic link. Otherwise it returns null. *

* @return The file pointed to by the symbolic link (null if the FTPFile * is not a symbolic link). ***/ public String getLink() { return _link; } /*** * Set the file timestamp. This usually the last modification time. * The parameter is not cloned, so do not alter its value after calling * this method. *

* @param date A Calendar instance representing the file timestamp. ***/ public void setTimestamp(Calendar date) { _date = date; } /*** * Returns the file timestamp. This usually the last modification time. *

* @return A Calendar instance representing the file timestamp. ***/ public Calendar getTimestamp() { return _date; } /*** * Set if the given access group (one of the _ACCESS * constants) has the given access permission (one of the * _PERMISSION constants) to the file. *

* @param access The access group (one of the _ACCESS * constants) * @param permission The access permission (one of the * _PERMISSION constants) * @param value True if permission is allowed, false if not. ***/ public void setPermission(int access, int permission, boolean value) { _permissions[access][permission] = value; } /*** * Determines if the given access group (one of the _ACCESS * constants) has the given access permission (one of the * _PERMISSION constants) to the file. *

* @param access The access group (one of the _ACCESS * constants) * @param permission The access permission (one of the * _PERMISSION constants) ***/ public boolean hasPermission(int access, int permission) { return _permissions[access][permission]; } /*** * Returns a string representation of the FTPFile information. This * will be the raw FTP server listing that was used to initialize the * FTPFile instance. *

* @return A string representation of the FTPFile information. ***/ @Override public String toString() { return _rawListing; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPSServerSocketFactory.java0000644000175000017500000000452111466231525030566 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import javax.net.ServerSocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; /** * Server socket factory for FTPS connections. * @since 2.2 */ public class FTPSServerSocketFactory extends ServerSocketFactory { /** Factory for secure socket factories */ private final SSLContext context; public FTPSServerSocketFactory(SSLContext context) { this.context = context; } @Override public ServerSocket createServerSocket(int port) throws IOException { return init(this.context.getServerSocketFactory().createServerSocket(port)); } @Override public ServerSocket createServerSocket(int port, int backlog) throws IOException { return init(this.context.getServerSocketFactory().createServerSocket(port, backlog)); } @Override public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException { return init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress)); } /** * Sets the socket so newly accepted connections will use SSL client mode. * * @param socket the SSLServerSocket to initialise * @return the socket * @throws ClassCastException if socket is not an instance of SSLServerSocket */ public ServerSocket init(ServerSocket socket) { ((SSLServerSocket) socket).setUseClientMode(true); return socket; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java0000644000175000017500000005551611351151237027044 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.text.DateFormatSymbols; import java.util.Collection; import java.util.Locale; import java.util.Map; import java.util.StringTokenizer; import java.util.TreeMap; /** *

* This class implements an alternate means of configuring the * {@link org.apache.commons.net.ftp.FTPClient FTPClient} object and * also subordinate objects which it uses. Any class implementing the * {@link org.apache.commons.net.ftp.Configurable Configurable } * interface can be configured by this object. *

* In particular this class was designed primarily to support configuration * of FTP servers which express file timestamps in formats and languages * other than those for the US locale, which although it is the most common * is not universal. Unfortunately, nothing in the FTP spec allows this to * be determined in an automated way, so manual configuration such as this * is necessary. *

* This functionality was designed to allow existing clients to work exactly * as before without requiring use of this component. This component should * only need to be explicitly invoked by the user of this package for problem * cases that previous implementations could not solve. *

*

Examples of use of FTPClientConfig

* Use cases: * You are trying to access a server that *
    *
  • lists files with timestamps that use month names in languages other * than English
  • *
  • lists files with timestamps that use date formats other * than the American English "standard" MM dd yyyy
  • *
  • is in different timezone and you need accurate timestamps for * dependency checking as in Ant
  • *
*

* Unpaged (whole list) access on a UNIX server that uses French month names * but uses the "standard" MMM d yyyy date formatting *

 *    FTPClient f=FTPClient();
 *    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
 *    conf.setServerLanguageCode("fr");
 *    f.configure(conf);
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = listFiles(directory);
 * 
*

*

* Paged access on a UNIX server that uses Danish month names * and "European" date formatting in Denmark's time zone, when you * are in some other time zone. *

 *    FTPClient f=FTPClient();
 *    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
 *    conf.setServerLanguageCode("da");
 *    conf.setDefaultDateFormat("d MMM yyyy");
 *    conf.setRecentDateFormat("d MMM HH:mm");
 *    conf.setTimeZoneId("Europe/Copenhagen");
 *    f.configure(conf);
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPListParseEngine engine =
 *       f.initiateListParsing("com.whatever.YourOwnParser", directory);
 *
 *    while (engine.hasNext()) {
 *       FTPFile[] files = engine.getNext(25);  // "page size" you want
 *       //do whatever you want with these files, display them, etc.
 *       //expensive FTPFile objects not created until needed.
 *    }
 * 
*

*

* Unpaged (whole list) access on a VMS server that uses month names * in a language not {@link #getSupportedLanguageCodes() supported} by the system. * but uses the "standard" MMM d yyyy date formatting *

 *    FTPClient f=FTPClient();
 *    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_VMS);
 *    conf.setShortMonthNames(
 *        "jan|feb|mar|apr|ma\u00ED|j\u00FAn|j\u00FAl|\u00e1g\u00FA|sep|okt|n\u00F3v|des");
 *    f.configure(conf);
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = listFiles(directory);
 * 
*

*

* Unpaged (whole list) access on a Windows-NT server in a different time zone. * (Note, since the NT Format uses numeric date formatting, language issues * are irrelevant here). *

 *    FTPClient f=FTPClient();
 *    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
 *    conf.setTimeZoneId("America/Denver");
 *    f.configure(conf);
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = listFiles(directory);
 * 
*

* Unpaged (whole list) access on a Windows-NT server in a different time zone * but which has been configured to use a unix-style listing format. *
 *    FTPClient f=FTPClient();
 *    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
 *    conf.setTimeZoneId("America/Denver");
 *    f.configure(conf);
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = listFiles(directory);
 * 
*

* @since 1.4 * @see org.apache.commons.net.ftp.Configurable * @see org.apache.commons.net.ftp.FTPClient * @see org.apache.commons.net.ftp.parser.FTPTimestampParserImpl#configure(FTPClientConfig) * @see org.apache.commons.net.ftp.parser.ConfigurableFTPFileEntryParserImpl */ public class FTPClientConfig { /** * Identifier by which a unix-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_UNIX = "UNIX"; /** * Identifier by which a vms-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_VMS = "VMS"; /** * Identifier by which a WindowsNT-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_NT = "WINDOWS"; /** * Identifier by which an OS/2-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_OS2 = "OS/2"; /** * Identifier by which an OS/400-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_OS400 = "OS/400"; /** * Identifier by which an AS/400-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_AS400 = "AS/400"; /** * Identifier by which an MVS-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_MVS = "MVS"; /** * Some servers return an "UNKNOWN Type: L8" message * in response to the SYST command. We set these to be a Unix-type system. * This may happen if the ftpd in question was compiled without system * information. * * NET-230 - Updated to be UPPERCASE so that the check done in * createFileEntryParser will succeed. * * @since 1.5 */ public static final String SYST_L8 = "TYPE: L8"; /** * Identifier by which an Netware-based ftp server is known throughout * the commons-net ftp system. * * @since 1.5 */ public static final String SYST_NETWARE = "NETWARE"; private final String serverSystemKey; private String defaultDateFormatStr = null; private String recentDateFormatStr = null; private boolean lenientFutureDates = false; private String serverLanguageCode = null; private String shortMonthNames = null; private String serverTimeZoneId = null; /** * The main constructor for an FTPClientConfig object * @param systemKey key representing system type of the server being * connected to. See {@link #getServerSystemKey() serverSystemKey} */ public FTPClientConfig(String systemKey) { this.serverSystemKey = systemKey; } /** * Convenience constructor mainly for use in testing. * Constructs a UNIX configuration. */ public FTPClientConfig() { this(SYST_UNIX); } /** * Constructor which allows setting of all member fields * @param systemKey key representing system type of the server being * connected to. See * {@link #getServerSystemKey() serverSystemKey} * @param defaultDateFormatStr See * {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} * @param recentDateFormatStr See * {@link #setRecentDateFormatStr(String) recentDateFormatStr} * @param serverLanguageCode See * {@link #setServerLanguageCode(String) serverLanguageCode} * @param shortMonthNames See * {@link #setShortMonthNames(String) shortMonthNames} * @param serverTimeZoneId See * {@link #setServerTimeZoneId(String) serverTimeZoneId} */ public FTPClientConfig(String systemKey, String defaultDateFormatStr, String recentDateFormatStr, String serverLanguageCode, String shortMonthNames, String serverTimeZoneId) { this(systemKey); this.defaultDateFormatStr = defaultDateFormatStr; this.recentDateFormatStr = recentDateFormatStr; this.serverLanguageCode = serverLanguageCode; this.shortMonthNames = shortMonthNames; this.serverTimeZoneId = serverTimeZoneId; } private static final Map LANGUAGE_CODE_MAP = new TreeMap(); static { // if there are other commonly used month name encodings which // correspond to particular locales, please add them here. // many locales code short names for months as all three letters // these we handle simply. LANGUAGE_CODE_MAP.put("en", Locale.ENGLISH); LANGUAGE_CODE_MAP.put("de",Locale.GERMAN); LANGUAGE_CODE_MAP.put("it",Locale.ITALIAN); LANGUAGE_CODE_MAP.put("es", new Locale("es", "", "")); // spanish LANGUAGE_CODE_MAP.put("pt", new Locale("pt", "", "")); // portuguese LANGUAGE_CODE_MAP.put("da", new Locale("da", "", "")); // danish LANGUAGE_CODE_MAP.put("sv", new Locale("sv", "", "")); // swedish LANGUAGE_CODE_MAP.put("no", new Locale("no", "", "")); // norwegian LANGUAGE_CODE_MAP.put("nl", new Locale("nl", "", "")); // dutch LANGUAGE_CODE_MAP.put("ro", new Locale("ro", "", "")); // romanian LANGUAGE_CODE_MAP.put("sq", new Locale("sq", "", "")); // albanian LANGUAGE_CODE_MAP.put("sh", new Locale("sh", "", "")); // serbo-croatian LANGUAGE_CODE_MAP.put("sk", new Locale("sk", "", "")); // slovak LANGUAGE_CODE_MAP.put("sl", new Locale("sl", "", "")); // slovenian // some don't LANGUAGE_CODE_MAP.put("fr", "jan|f\u00e9v|mar|avr|mai|jun|jui|ao\u00fb|sep|oct|nov|d\u00e9c"); //french } /** * Getter for the serverSystemKey property. This property * specifies the general type of server to which the client connects. * Should be either one of the FTPClientConfig.SYST_* codes * or else the fully qualified class name of a parser implementing both * the FTPFileEntryParser and Configurable * interfaces. * @return Returns the serverSystemKey property. */ public String getServerSystemKey() { return serverSystemKey; } /** * getter for the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} * property. * @return Returns the defaultDateFormatStr property. */ public String getDefaultDateFormatStr() { return defaultDateFormatStr; } /** * getter for the {@link #setRecentDateFormatStr(String) recentDateFormatStr} property. * @return Returns the recentDateFormatStr property. */ public String getRecentDateFormatStr() { return recentDateFormatStr; } /** * getter for the {@link #setServerTimeZoneId(String) serverTimeZoneId} property. * @return Returns the serverTimeZoneId property. */ public String getServerTimeZoneId() { return serverTimeZoneId; } /** *

* getter for the {@link #setShortMonthNames(String) shortMonthNames} * property. *

* @return Returns the shortMonthNames. */ public String getShortMonthNames() { return shortMonthNames; } /** *

* getter for the {@link #setServerLanguageCode(String) serverLanguageCode} property. *

* @return Returns the serverLanguageCode property. */ public String getServerLanguageCode() { return serverLanguageCode; } /** *

* getter for the {@link #setLenientFutureDates(boolean) lenientFutureDates} property. *

* @return Returns the lenientFutureDates. * @since 1.5 */ public boolean isLenientFutureDates() { return lenientFutureDates; } /** *

* setter for the defaultDateFormatStr property. This property * specifies the main date format that will be used by a parser configured * by this configuration to parse file timestamps. If this is not * specified, such a parser will use as a default value, the most commonly * used format which will be in as used in en_US locales. *

* This should be in the format described for * java.text.SimpleDateFormat. * property. *

* @param defaultDateFormatStr The defaultDateFormatStr to set. */ public void setDefaultDateFormatStr(String defaultDateFormatStr) { this.defaultDateFormatStr = defaultDateFormatStr; } /** *

* setter for the recentDateFormatStr property. This property * specifies a secondary date format that will be used by a parser * configured by this configuration to parse file timestamps, typically * those less than a year old. If this is not specified, such a parser * will not attempt to parse using an alternate format. *

* This is used primarily in unix-based systems. *

* This should be in the format described for * java.text.SimpleDateFormat. *

* @param recentDateFormatStr The recentDateFormatStr to set. */ public void setRecentDateFormatStr(String recentDateFormatStr) { this.recentDateFormatStr = recentDateFormatStr; } /** *

* setter for the lenientFutureDates property. This boolean property * (default: false) only has meaning when a * {@link #setRecentDateFormatStr(String) recentDateFormatStr} property * has been set. In that case, if this property is set true, then the * parser, when it encounters a listing parseable with the recent date * format, will only consider a date to belong to the previous year if * it is more than one day in the future. This will allow all * out-of-synch situations (whether based on "slop" - i.e. servers simply * out of synch with one another or because of time zone differences - * but in the latter case it is highly recommended to use the * {@link #setServerTimeZoneId(String) serverTimeZoneId} property * instead) to resolve correctly. *

* This is used primarily in unix-based systems. *

* @param lenientFutureDates set true to compensate for out-of-synch * conditions. */ public void setLenientFutureDates(boolean lenientFutureDates) { this.lenientFutureDates = lenientFutureDates; } /** *

* setter for the serverTimeZoneId property. This property * allows a time zone to be specified corresponding to that known to be * used by an FTP server in file listings. This might be particularly * useful to clients such as Ant that try to use these timestamps for * dependency checking. *

* This should be one of the identifiers used by * java.util.TimeZone to refer to time zones, for example, * America/Chicago or Asia/Rangoon. *

* @param serverTimeZoneId The serverTimeZoneId to set. */ public void setServerTimeZoneId(String serverTimeZoneId) { this.serverTimeZoneId = serverTimeZoneId; } /** *

* setter for the shortMonthNames property. * This property allows the user to specify a set of month names * used by the server that is different from those that may be * specified using the {@link #setServerLanguageCode(String) serverLanguageCode} * property. *

* This should be a string containing twelve strings each composed of * three characters, delimited by pipe (|) characters. Currently, * only 8-bit ASCII characters are known to be supported. For example, * a set of month names used by a hypothetical Icelandic FTP server might * conceivably be specified as * "jan|feb|mar|apr|maí|jún|júl|ágú|sep|okt|nóv|des". *

* @param shortMonthNames The value to set to the shortMonthNames property. */ public void setShortMonthNames(String shortMonthNames) { this.shortMonthNames = shortMonthNames; } /** *

* setter for the serverLanguageCode property. This property allows * user to specify a * * two-letter ISO-639 language code that will be used to * configure the set of month names used by the file timestamp parser. * If neither this nor the {@link #setShortMonthNames(String) shortMonthNames} * is specified, parsing will assume English month names, which may or * may not be significant, depending on whether the date format(s) * specified via {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} * and/or {@link #setRecentDateFormatStr(String) recentDateFormatStr} are using * numeric or alphabetic month names. *

*

If the code supplied is not supported here, en_US * month names will be used. We are supporting here those language * codes which, when a java.util.Locale is constucted * using it, and a java.text.SimpleDateFormat is * constructed using that Locale, the array returned by the * SimpleDateFormat's getShortMonths() method consists * solely of three 8-bit ASCII character strings. Additionally, * languages which do not meet this requirement are included if a * common alternative set of short month names is known to be used. * This means that users who can tell us of additional such encodings * may get them added to the list of supported languages by contacting * the Apache Commons Net team. *

*

* Please note that this attribute will NOT be used to determine a * locale-based date format for the language. * Experience has shown that many if not most FTP servers outside the * United States employ the standard en_US date format * orderings of MMM d yyyy and MMM d HH:mm * and attempting to deduce this automatically here would cause more * problems than it would solve. The date format must be changed * via the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} and/or * {@link #setRecentDateFormatStr(String) recentDateFormatStr} parameters. *

* @param serverLanguageCode The value to set to the serverLanguageCode property. */ public void setServerLanguageCode(String serverLanguageCode) { this.serverLanguageCode = serverLanguageCode; } /** * Looks up the supplied language code in the internally maintained table of * language codes. Returns a DateFormatSymbols object configured with * short month names corresponding to the code. If there is no corresponding * entry in the table, the object returned will be that for * Locale.US * @param languageCode See {@link #setServerLanguageCode(String) serverLanguageCode} * @return a DateFormatSymbols object configured with short month names * corresponding to the supplied code, or with month names for * Locale.US if there is no corresponding entry in the internal * table. */ public static DateFormatSymbols lookupDateFormatSymbols(String languageCode) { Object lang = LANGUAGE_CODE_MAP.get(languageCode); if (lang != null) { if (lang instanceof Locale) { return new DateFormatSymbols((Locale) lang); } else if (lang instanceof String){ return getDateFormatSymbols((String) lang); } } return new DateFormatSymbols(Locale.US); } /** * Returns a DateFormatSymbols object configured with short month names * as in the supplied string * @param shortmonths This should be as described in * {@link #setShortMonthNames(String) shortMonthNames} * @return a DateFormatSymbols object configured with short month names * as in the supplied string */ public static DateFormatSymbols getDateFormatSymbols(String shortmonths) { String[] months = splitShortMonthString(shortmonths); DateFormatSymbols dfs = new DateFormatSymbols(Locale.US); dfs.setShortMonths(months); return dfs; } private static String[] splitShortMonthString(String shortmonths) { StringTokenizer st = new StringTokenizer(shortmonths, "|"); int monthcnt = st.countTokens(); if (12 != monthcnt) { throw new IllegalArgumentException( "expecting a pipe-delimited string containing 12 tokens"); } String[] months = new String[13]; int pos = 0; while(st.hasMoreTokens()) { months[pos++] = st.nextToken(); } months[pos]=""; return months; } /** * Returns a Collection of all the language codes currently supported * by this class. See {@link #setServerLanguageCode(String) serverLanguageCode} * for a functional descrption of language codes within this system. * * @return a Collection of all the language codes currently supported * by this class */ public static Collection getSupportedLanguageCodes() { return LANGUAGE_CODE_MAP.keySet(); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParser.java0000644000175000017500000001345711151644177027564 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.util.List; /** * FTPFileEntryParser defines the interface for parsing a single FTP file * listing and converting that information into an * {@link org.apache.commons.net.ftp.FTPFile} instance. * Sometimes you will want to parse unusual listing formats, in which * case you would create your own implementation of FTPFileEntryParser and * if necessary, subclass FTPFile. *

* Here are some examples showing how to use one of the classes that * implement this interface. *

* The first example shows how to get an iterable list of files in which the * more expensive FTPFile objects are not created until needed. This * is suitable for paged displays. It requires that a parser object be created * beforehand: parser is an object (in the package * org.apache.commons.net.ftp.parser) * implementing this inteface. * *

 *    FTPClient f=FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFileList list = f.createFileList(directory, parser);
 *    FTPFileIterator iter = list.iterator();
 *
 *    while (iter.hasNext()) {
 *       FTPFile[] files = iter.getNext(25);  // "page size" you want
 *       //do whatever you want with these files, display them, etc.
 *       //expensive FTPFile objects not created until needed.
 *    }
 * 
* * The second example uses the revised FTPClient.listFiles() * API to pull the whole list from the subfolder subfolder in * one call, attempting to automatically detect the parser type. This * method, without a parserKey parameter, indicates that autodection should * be used. * *
 *    FTPClient f=FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = f.listFiles("subfolder");
 * 
* * The third example uses the revised FTPClient.listFiles()> * API to pull the whole list from the current working directory in one call, * but specifying by classname the parser to be used. For this particular * parser class, this approach is necessary since there is no way to * autodetect this server type. * *
 *    FTPClient f=FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = f.listFiles(
 *      "org.apache.commons.net.ftp.parser.EnterpriseUnixFTPFileEntryParser",
 *      ".");
 * 
* * The fourth example uses the revised FTPClient.listFiles() * API to pull a single file listing in an arbitrary directory in one call, * specifying by KEY the parser to be used, in this case, VMS. * *
 *    FTPClient f=FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = f.listFiles("VMS", "subfolder/foo.java");
 * 
* * @author Steve Cohen * @version $Id: FTPFileEntryParser.java 748376 2009-02-27 01:57:19Z sebb $ * @see org.apache.commons.net.ftp.FTPFile * @see org.apache.commons.net.ftp.FTPClient#listFiles() */ public interface FTPFileEntryParser { /** * Parses a line of an FTP server file listing and converts it into a usable * format in the form of an FTPFile instance. If the * file listing line doesn't describe a file, null should be * returned, otherwise a FTPFile instance representing the * files in the directory is returned. *

* @param listEntry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ FTPFile parseFTPEntry(String listEntry); /** * Reads the next entry using the supplied BufferedReader object up to * whatever delemits one entry from the next. Implementors must define * this for the particular ftp system being parsed. In many but not all * cases, this can be defined simply by calling BufferedReader.readLine(). * * @param reader The BufferedReader object from which entries are to be * read. * * @return A string representing the next ftp entry or null if none found. * @exception IOException thrown on any IO Error reading from the reader. */ String readNextEntry(BufferedReader reader) throws IOException; /** * This method is a hook for those implementors (such as * VMSVersioningFTPEntryParser, and possibly others) which need to * perform some action upon the FTPFileList after it has been created * from the server stream, but before any clients see the list. * * The default implementation can be a no-op. * * @param original Original list after it has been created from the server stream * * @return Original list as processed by this method. */ List preParse(List original); } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java0000644000175000017500000000667611466231525027414 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; /** * * Implementation of org.apache.commons.net.SocketFactory * * @since 2.0 */ public class FTPSSocketFactory extends SocketFactory { private final SSLContext context; public FTPSSocketFactory(SSLContext context) { this.context = context; } @Override public Socket createSocket(String address, int port) throws UnknownHostException, IOException { return this.context.getSocketFactory().createSocket(address, port); } @Override public Socket createSocket(InetAddress address, int port) throws IOException { return this.context.getSocketFactory().createSocket(address, port); } @Override public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws UnknownHostException, IOException { return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort); } /** @deprecated (2.2) use {@link FTPSServerSocketFactory#createServerSocket(int) instead} */ @Deprecated public ServerSocket createServerSocket(int port) throws IOException { return this.init(this.context.getServerSocketFactory().createServerSocket(port)); } /** @deprecated (2.2) use {@link FTPSServerSocketFactory#createServerSocket(int, int) instead} */ @Deprecated public ServerSocket createServerSocket(int port, int backlog) throws IOException { return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog)); } /** @deprecated (2.2) use {@link FTPSServerSocketFactory#createServerSocket(int, int, InetAddress) instead} */ @Deprecated public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException { return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress)); } /** @deprecated (2.2) use {@link FTPSServerSocketFactory#init(ServerSocket)} */ @SuppressWarnings("unused") @Deprecated public ServerSocket init(ServerSocket socket) throws IOException { ((SSLServerSocket) socket).setUseClientMode(true); return socket; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPCommand.java0000644000175000017500000001417311456023364026055 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; /*** * FTPCommand stores a set of constants for FTP command codes. To interpret * the meaning of the codes, familiarity with RFC 959 is assumed. * The mnemonic constant names are transcriptions from the code descriptions * of RFC 959. For those who think in terms of the actual FTP commands, * a set of constants such as {@link #USER USER } are provided * where the constant name is the same as the FTP command. *

*

* @author Daniel F. Savarese ***/ /** TODO replace this with an enum */ public final class FTPCommand { public static final int USER = 0; public static final int PASS = 1; public static final int ACCT = 2; public static final int CWD = 3; public static final int CDUP = 4; public static final int SMNT = 5; public static final int REIN = 6; public static final int QUIT = 7; public static final int PORT = 8; public static final int PASV = 9; public static final int TYPE = 10; public static final int STRU = 11; public static final int MODE = 12; public static final int RETR = 13; public static final int STOR = 14; public static final int STOU = 15; public static final int APPE = 16; public static final int ALLO = 17; public static final int REST = 18; public static final int RNFR = 19; public static final int RNTO = 20; public static final int ABOR = 21; public static final int DELE = 22; public static final int RMD = 23; public static final int MKD = 24; public static final int PWD = 25; public static final int LIST = 26; public static final int NLST = 27; public static final int SITE = 28; public static final int SYST = 29; public static final int STAT = 30; public static final int HELP = 31; public static final int NOOP = 32; /** @since 2.0 */ public static final int MDTM = 33; /** @since 2.2 */ public static final int FEAT = 34; /** @since 2.2 */ public static final int MFMT = 35; /** @since 2.2 */ public static final int EPSV = 36; /** @since 2.2 */ public static final int EPRT = 37; // Must agree with final entry above; used to check array size private static final int LAST = EPRT; public static final int USERNAME = USER; public static final int PASSWORD = PASS; public static final int ACCOUNT = ACCT; public static final int CHANGE_WORKING_DIRECTORY = CWD; public static final int CHANGE_TO_PARENT_DIRECTORY = CDUP; public static final int STRUCTURE_MOUNT = SMNT; public static final int REINITIALIZE = REIN; public static final int LOGOUT = QUIT; public static final int DATA_PORT = PORT; public static final int PASSIVE = PASV; public static final int REPRESENTATION_TYPE = TYPE; public static final int FILE_STRUCTURE = STRU; public static final int TRANSFER_MODE = MODE; public static final int RETRIEVE = RETR; public static final int STORE = STOR; public static final int STORE_UNIQUE = STOU; public static final int APPEND = APPE; public static final int ALLOCATE = ALLO; public static final int RESTART = REST; public static final int RENAME_FROM = RNFR; public static final int RENAME_TO = RNTO; public static final int ABORT = ABOR; public static final int DELETE = DELE; public static final int REMOVE_DIRECTORY = RMD; public static final int MAKE_DIRECTORY = MKD; public static final int PRINT_WORKING_DIRECTORY = PWD; // public static final int LIST = LIST; public static final int NAME_LIST = NLST; public static final int SITE_PARAMETERS = SITE; public static final int SYSTEM = SYST; public static final int STATUS = STAT; //public static final int HELP = HELP; //public static final int NOOP = NOOP; /** @since 2.0 */ public static final int MOD_TIME = MDTM; /** @since 2.2 */ public static final int FEATURES = FEAT; /** @since 2.2 */ public static final int GET_MOD_TIME = MDTM; /** @since 2.2 */ public static final int SET_MOD_TIME = MFMT; // Cannot be instantiated private FTPCommand() {} private static final String[] _commands = { "USER", "PASS", "ACCT", "CWD", "CDUP", "SMNT", "REIN", "QUIT", "PORT", "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO", "REST", "RNFR", "RNTO", "ABOR", "DELE", "RMD", "MKD", "PWD", "LIST", "NLST", "SITE", "SYST", "STAT", "HELP", "NOOP", "MDTM", "FEAT", "MFMT", "EPSV", "EPRT" }; // default access needed for Unit test static void checkArray(){ int expectedLength = LAST+1; if (_commands.length != expectedLength) { throw new RuntimeException("Incorrect _commands array. Should have length " +expectedLength+" found "+_commands.length); } } /** * Retrieve the FTP protocol command string corresponding to a specified * command code. *

* @param command The command code. * @return The FTP protcol command string corresponding to a specified * command code. */ public static final String getCommand(int command) { return _commands[command]; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPReply.java0000644000175000017500000002446711466231525025602 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; /*** * FTPReply stores a set of constants for FTP reply codes. To interpret * the meaning of the codes, familiarity with RFC 959 is assumed. * The mnemonic constant names are transcriptions from the code descriptions * of RFC 959. For those who think in terms of the actual reply code values, * a set of CODE_NUM constants are provided where NUM is the numerical value * of the code. *

*

* @author Daniel F. Savarese * TODO replace with an enum ***/ public final class FTPReply { public static final int CODE_110 = 110; public static final int CODE_120 = 120; public static final int CODE_125 = 125; public static final int CODE_150 = 150; public static final int CODE_200 = 200; public static final int CODE_202 = 202; public static final int CODE_211 = 211; public static final int CODE_212 = 212; public static final int CODE_213 = 213; public static final int CODE_214 = 214; public static final int CODE_215 = 215; public static final int CODE_220 = 220; public static final int CODE_221 = 221; public static final int CODE_225 = 225; public static final int CODE_226 = 226; public static final int CODE_227 = 227; /** @since 2.2 */ public static final int CODE_229 = 229; public static final int CODE_230 = 230; public static final int CODE_250 = 250; public static final int CODE_257 = 257; public static final int CODE_331 = 331; public static final int CODE_332 = 332; public static final int CODE_350 = 350; public static final int CODE_421 = 421; public static final int CODE_425 = 425; public static final int CODE_426 = 426; public static final int CODE_450 = 450; public static final int CODE_451 = 451; public static final int CODE_452 = 452; public static final int CODE_500 = 500; public static final int CODE_501 = 501; public static final int CODE_502 = 502; public static final int CODE_503 = 503; public static final int CODE_504 = 504; public static final int CODE_521 = 521; public static final int CODE_530 = 530; public static final int CODE_532 = 532; public static final int CODE_550 = 550; public static final int CODE_551 = 551; public static final int CODE_552 = 552; public static final int CODE_553 = 553; public static final int RESTART_MARKER = CODE_110; public static final int SERVICE_NOT_READY = CODE_120; public static final int DATA_CONNECTION_ALREADY_OPEN = CODE_125; public static final int FILE_STATUS_OK = CODE_150; public static final int COMMAND_OK = CODE_200; public static final int COMMAND_IS_SUPERFLUOUS = CODE_202; public static final int SYSTEM_STATUS = CODE_211; public static final int DIRECTORY_STATUS = CODE_212; public static final int FILE_STATUS = CODE_213; public static final int HELP_MESSAGE = CODE_214; public static final int NAME_SYSTEM_TYPE = CODE_215; public static final int SERVICE_READY = CODE_220; public static final int SERVICE_CLOSING_CONTROL_CONNECTION = CODE_221; public static final int DATA_CONNECTION_OPEN = CODE_225; public static final int CLOSING_DATA_CONNECTION = CODE_226; public static final int ENTERING_PASSIVE_MODE = CODE_227; /** @since 2.2 */ public static final int ENTERING_EPSV_MODE = CODE_229; public static final int USER_LOGGED_IN = CODE_230; public static final int FILE_ACTION_OK = CODE_250; public static final int PATHNAME_CREATED = CODE_257; public static final int NEED_PASSWORD = CODE_331; public static final int NEED_ACCOUNT = CODE_332; public static final int FILE_ACTION_PENDING = CODE_350; public static final int SERVICE_NOT_AVAILABLE = CODE_421; public static final int CANNOT_OPEN_DATA_CONNECTION = CODE_425; public static final int TRANSFER_ABORTED = CODE_426; public static final int FILE_ACTION_NOT_TAKEN = CODE_450; public static final int ACTION_ABORTED = CODE_451; public static final int INSUFFICIENT_STORAGE = CODE_452; public static final int UNRECOGNIZED_COMMAND = CODE_500; public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501; public static final int COMMAND_NOT_IMPLEMENTED = CODE_502; public static final int BAD_COMMAND_SEQUENCE = CODE_503; public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504; public static final int NOT_LOGGED_IN = CODE_530; public static final int NEED_ACCOUNT_FOR_STORING_FILES = CODE_532; public static final int FILE_UNAVAILABLE = CODE_550; public static final int PAGE_TYPE_UNKNOWN = CODE_551; public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552; public static final int FILE_NAME_NOT_ALLOWED = CODE_553; // FTPS Reply Codes /** @since 2.0 */ public static final int CODE_234 = 234; /** @since 2.0 */ public static final int CODE_235 = 235; /** @since 2.0 */ public static final int CODE_334 = 334; /** @since 2.0 */ public static final int CODE_335 = 335; /** @since 2.0 */ public static final int CODE_431 = 431; /** @since 2.2 */ public static final int CODE_522 = 522; /** @since 2.0 */ public static final int CODE_533 = 533; /** @since 2.0 */ public static final int CODE_534 = 534; /** @since 2.0 */ public static final int CODE_535 = 535; /** @since 2.0 */ public static final int CODE_536 = 536; /** @since 2.0 */ public static final int SECURITY_DATA_EXCHANGE_COMPLETE = CODE_234; /** @since 2.0 */ public static final int SECURITY_DATA_EXCHANGE_SUCCESSFULLY = CODE_235; /** @since 2.0 */ public static final int SECURITY_MECHANISM_IS_OK = CODE_334; /** @since 2.0 */ public static final int SECURITY_DATA_IS_ACCEPTABLE = CODE_335; /** @since 2.0 */ public static final int UNAVAILABLE_RESOURCE = CODE_431; /** @since 2.2 */ public static final int BAD_TLS_NEGOTIATION_OR_DATA_ENCRYPTION_REQUIRED = CODE_522; /** @since 2.0 */ public static final int DENIED_FOR_POLICY_REASONS = CODE_533; /** @since 2.0 */ public static final int REQUEST_DENIED = CODE_534; /** @since 2.0 */ public static final int FAILED_SECURITY_CHECK = CODE_535; /** @since 2.0 */ public static final int REQUESTED_PROT_LEVEL_NOT_SUPPORTED = CODE_536; // IPv6 error codes // Note this is also used as an FTPS error code reply /** @since 2.2 */ public static final int EXTENDED_PORT_FAILURE = CODE_522; // Cannot be instantiated private FTPReply() {} /*** * Determine if a reply code is a positive preliminary response. All * codes beginning with a 1 are positive preliminary responses. * Postitive preliminary responses are used to indicate tentative success. * No further commands can be issued to the FTP server after a positive * preliminary response until a follow up response is received from the * server. *

* @param reply The reply code to test. * @return True if a reply code is a postive preliminary response, false * if not. ***/ public static boolean isPositivePreliminary(int reply) { return (reply >= 100 && reply < 200); } /*** * Determine if a reply code is a positive completion response. All * codes beginning with a 2 are positive completion responses. * The FTP server will send a positive completion response on the final * successful completion of a command. *

* @param reply The reply code to test. * @return True if a reply code is a postive completion response, false * if not. ***/ public static boolean isPositiveCompletion(int reply) { return (reply >= 200 && reply < 300); } /*** * Determine if a reply code is a positive intermediate response. All * codes beginning with a 3 are positive intermediate responses. * The FTP server will send a positive intermediate response on the * successful completion of one part of a multi-part sequence of * commands. For example, after a successful USER command, a positive * intermediate response will be sent to indicate that the server is * ready for the PASS command. *

* @param reply The reply code to test. * @return True if a reply code is a postive intermediate response, false * if not. ***/ public static boolean isPositiveIntermediate(int reply) { return (reply >= 300 && reply < 400); } /*** * Determine if a reply code is a negative transient response. All * codes beginning with a 4 are negative transient responses. * The FTP server will send a negative transient response on the * failure of a command that can be reattempted with success. *

* @param reply The reply code to test. * @return True if a reply code is a negative transient response, false * if not. ***/ public static boolean isNegativeTransient(int reply) { return (reply >= 400 && reply < 500); } /*** * Determine if a reply code is a negative permanent response. All * codes beginning with a 5 are negative permanent responses. * The FTP server will send a negative permanent response on the * failure of a command that cannot be reattempted with success. *

* @param reply The reply code to test. * @return True if a reply code is a negative permanent response, false * if not. ***/ public static boolean isNegativePermanent(int reply) { return (reply >= 500 && reply < 600); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java0000644000175000017500000003016311466235516027535 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; /** * This class handles the entire process of parsing a listing of * file entries from the server. *

* This object defines a two-part parsing mechanism. *

* The first part is comprised of reading the raw input into an internal * list of strings. Every item in this list corresponds to an actual * file. All extraneous matter emitted by the server will have been * removed by the end of this phase. This is accomplished in conjunction * with the FTPFileEntryParser associated with this engine, by calling * its methods readNextEntry() - which handles the issue of * what delimits one entry from another, usually but not always a line * feed and preParse() - which handles removal of * extraneous matter such as the preliminary lines of a listing, removal * of duplicates on versioning systems, etc. *

* The second part is composed of the actual parsing, again in conjunction * with the particular parser used by this engine. This is controlled * by an iterator over the internal list of strings. This may be done * either in block mode, by calling the getNext() and * getPrevious() methods to provide "paged" output of less * than the whole list at one time, or by calling the * getFiles() method to return the entire list. *

* Examples: *

* Paged access: *

 *    FTPClient f=FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPListParseEngine engine = f.initiateListParsing(directory);
 *
 *    while (engine.hasNext()) {
 *       FTPFile[] files = engine.getNext(25);  // "page size" you want
 *       //do whatever you want with these files, display them, etc.
 *       //expensive FTPFile objects not created until needed.
 *    }
 * 
*

* For unpaged access, simply use FTPClient.listFiles(). That method * uses this class transparently. * @version $Id: FTPListParseEngine.java 1032954 2010-11-09 12:15:10Z sebb $ */ public class FTPListParseEngine { private List entries = new LinkedList(); private ListIterator _internalIterator = entries.listIterator(); private final FTPFileEntryParser parser; public FTPListParseEngine(FTPFileEntryParser parser) { this.parser = parser; } /** * handle the initial reading and preparsing of the list returned by * the server. After this method has completed, this object will contain * a list of unparsed entries (Strings) each referring to a unique file * on the server. * * @param stream input stream provided by the server socket. * * @exception IOException * thrown on any failure to read from the sever. */ public void readServerList(InputStream stream, String encoding) throws IOException { this.entries = new LinkedList(); readStream(stream, encoding); this.parser.preParse(this.entries); resetIterator(); } /** * handle the iniitial reading and preparsing of the list returned by * the server. After this method has completed, this object will contain * a list of unparsed entries (Strings) each referring to a unique file * on the server. * * @param stream input stream provided by the server socket. * * @exception IOException * thrown on any failure to read from the sever. * * @deprecated The version of this method which takes an encoding should be used. */ @Deprecated public void readServerList(InputStream stream) throws IOException { readServerList(stream, null); } /** * Internal method for reading the input into the entries list. * After this method has completed, entries will contain a * collection of entries (as defined by * FTPFileEntryParser.readNextEntry()), but this may contain * various non-entry preliminary lines from the server output, duplicates, * and other data that will not be part of the final listing. * * @param stream The socket stream on which the input will be read. * @param encoding The encoding to use. * * @exception IOException * thrown on any failure to read the stream */ private void readStream(InputStream stream, String encoding) throws IOException { BufferedReader reader; if (encoding == null) { reader = new BufferedReader(new InputStreamReader(stream)); } else { reader = new BufferedReader(new InputStreamReader(stream, encoding)); } String line = this.parser.readNextEntry(reader); while (line != null) { this.entries.add(line); line = this.parser.readNextEntry(reader); } reader.close(); } /** * Returns an array of at most quantityRequested FTPFile * objects starting at this object's internal iterator's current position. * If fewer than quantityRequested such * elements are available, the returned array will have a length equal * to the number of entries at and after after the current position. * If no such entries are found, this array will have a length of 0. * * After this method is called this object's internal iterator is advanced * by a number of positions equal to the size of the array returned. * * @param quantityRequested * the maximum number of entries we want to get. * * @return an array of at most quantityRequested FTPFile * objects starting at the current position of this iterator within its * list and at least the number of elements which exist in the list at * and after its current position. *

* NOTE: This array may contain null members if any of the * individual file listings failed to parse. The caller should * check each entry for null before referencing it. */ public FTPFile[] getNext(int quantityRequested) { List tmpResults = new LinkedList(); int count = quantityRequested; while (count > 0 && this._internalIterator.hasNext()) { String entry = this._internalIterator.next(); FTPFile temp = this.parser.parseFTPEntry(entry); tmpResults.add(temp); count--; } return tmpResults.toArray(new FTPFile[tmpResults.size()]); } /** * Returns an array of at most quantityRequested FTPFile * objects starting at this object's internal iterator's current position, * and working back toward the beginning. * * If fewer than quantityRequested such * elements are available, the returned array will have a length equal * to the number of entries at and after after the current position. * If no such entries are found, this array will have a length of 0. * * After this method is called this object's internal iterator is moved * back by a number of positions equal to the size of the array returned. * * @param quantityRequested * the maximum number of entries we want to get. * * @return an array of at most quantityRequested FTPFile * objects starting at the current position of this iterator within its * list and at least the number of elements which exist in the list at * and after its current position. This array will be in the same order * as the underlying list (not reversed). *

* NOTE: This array may contain null members if any of the * individual file listings failed to parse. The caller should * check each entry for null before referencing it. */ public FTPFile[] getPrevious(int quantityRequested) { List tmpResults = new LinkedList(); int count = quantityRequested; while (count > 0 && this._internalIterator.hasPrevious()) { String entry = this._internalIterator.previous(); FTPFile temp = this.parser.parseFTPEntry(entry); tmpResults.add(0,temp); count--; } return tmpResults.toArray(new FTPFile[tmpResults.size()]); } /** * Returns an array of FTPFile objects containing the whole list of * files returned by the server as read by this object's parser. * * @return an array of FTPFile objects containing the whole list of * files returned by the server as read by this object's parser. *

* NOTE: This array may contain null members if any of the * individual file listings failed to parse. The caller should * check each entry for null before referencing it. * @exception IOException */ public FTPFile[] getFiles() throws IOException { return getFiles(FTPFileFilters.ALL); } /** * Returns an array of FTPFile objects containing the whole list of * files returned by the server as read by this object's parser. * The files are filtered before being added to the array. * * @param filter FTPFileFilter, must not be null. * * @return an array of FTPFile objects containing the whole list of * files returned by the server as read by this object's parser. *

* NOTE: This array may contain null members if any of the * individual file listings failed to parse. The caller should * check each entry for null before referencing it, or use the * a filter such as {@link FTPFileFilters#NON_NULL} which does not * allow null entries. * @since 2.2 * @exception IOException */ public FTPFile[] getFiles(FTPFileFilter filter) throws IOException { List tmpResults = new ArrayList(); Iterator iter = this.entries.iterator(); while (iter.hasNext()) { String entry = iter.next(); FTPFile temp = this.parser.parseFTPEntry(entry); if (filter.accept(temp)){ tmpResults.add(temp); } } return tmpResults.toArray(new FTPFile[tmpResults.size()]); } /** * convenience method to allow clients to know whether this object's * internal iterator's current position is at the end of the list. * * @return true if internal iterator is not at end of list, false * otherwise. */ public boolean hasNext() { return _internalIterator.hasNext(); } /** * convenience method to allow clients to know whether this object's * internal iterator's current position is at the beginning of the list. * * @return true if internal iterator is not at beginning of list, false * otherwise. */ public boolean hasPrevious() { return _internalIterator.hasPrevious(); } /** * resets this object's internal iterator to the beginning of the list. */ public void resetIterator() { this._internalIterator = this.entries.listIterator(); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java0000644000175000017500000000566111051351373030374 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.util.Iterator; import java.util.List; /** * This abstract class implements both the older FTPFileListParser and * newer FTPFileEntryParser interfaces with default functionality. * All the classes in the parser subpackage inherit from this. * */ public abstract class FTPFileEntryParserImpl implements FTPFileEntryParser { /** * The constructor for a FTPFileEntryParserImpl object. */ public FTPFileEntryParserImpl() { } /** * Reads the next entry using the supplied BufferedReader object up to * whatever delemits one entry from the next. This default implementation * simply calls BufferedReader.readLine(). * * @param reader The BufferedReader object from which entries are to be * read. * * @return A string representing the next ftp entry or null if none found. * @exception java.io.IOException thrown on any IO Error reading from the reader. */ public String readNextEntry(BufferedReader reader) throws IOException { return reader.readLine(); } /** * This method is a hook for those implementors (such as * VMSVersioningFTPEntryParser, and possibly others) which need to * perform some action upon the FTPFileList after it has been created * from the server stream, but before any clients see the list. * * This default implementation removes entries that do not parse as files. * * @param original Original list after it has been created from the server stream * * @return original unmodified. */ public List preParse(List original) { Iterator it = original.iterator(); while (it.hasNext()){ String entry = it.next(); if (null == parseFTPEntry(entry)) { it.remove(); } } return original; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPClient.java0000644000175000017500000035002611466231525025716 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Inet6Address; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Random; import org.apache.commons.net.MalformedServerReplyException; import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory; import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory; import org.apache.commons.net.ftp.parser.ParserInitializationException; import org.apache.commons.net.io.CopyStreamEvent; import org.apache.commons.net.io.CopyStreamException; import org.apache.commons.net.io.FromNetASCIIInputStream; import org.apache.commons.net.io.ToNetASCIIOutputStream; import org.apache.commons.net.io.Util; /*** * FTPClient encapsulates all the functionality necessary to store and * retrieve files from an FTP server. This class takes care of all * low level details of interacting with an FTP server and provides * a convenient higher level interface. As with all classes derived * from {@link org.apache.commons.net.SocketClient}, * you must first connect to the server with * {@link org.apache.commons.net.SocketClient#connect connect } * before doing anything, and finally * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * after you're completely finished interacting with the server. * Then you need to check the FTP reply code to see if the connection * was successful. For example: *

 *    boolean error = false;
 *    try {
 *      int reply;
 *      ftp.connect("ftp.foobar.com");
 *      System.out.println("Connected to " + server + ".");
 *      System.out.print(ftp.getReplyString());
 *
 *      // After connection attempt, you should check the reply code to verify
 *      // success.
 *      reply = ftp.getReplyCode();
 *
 *      if(!FTPReply.isPositiveCompletion(reply)) {
 *        ftp.disconnect();
 *        System.err.println("FTP server refused connection.");
 *        System.exit(1);
 *      }
 *      ... // transfer files
 *      ftp.logout();
 *    } catch(IOException e) {
 *      error = true;
 *      e.printStackTrace();
 *    } finally {
 *      if(ftp.isConnected()) {
 *        try {
 *          ftp.disconnect();
 *        } catch(IOException ioe) {
 *          // do nothing
 *        }
 *      }
 *      System.exit(error ? 1 : 0);
 *    }
 * 
*

* Immediately after connecting is the only real time you need to check the * reply code (because connect is of type void). The convention for all the * FTP command methods in FTPClient is such that they either return a * boolean value or some other value. * The boolean methods return true on a successful completion reply from * the FTP server and false on a reply resulting in an error condition or * failure. The methods returning a value other than boolean return a value * containing the higher level data produced by the FTP command, or null if a * reply resulted in an error condition or failure. If you want to access * the exact FTP reply code causing a success or failure, you must call * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode } after * a success or failure. *

* The default settings for FTPClient are for it to use * FTP.ASCII_FILE_TYPE , * FTP.NON_PRINT_TEXT_FORMAT , * FTP.STREAM_TRANSFER_MODE , and * FTP.FILE_STRUCTURE . The only file types directly supported * are FTP.ASCII_FILE_TYPE and * FTP.BINARY_FILE_TYPE . Because there are at least 4 * different EBCDIC encodings, we have opted not to provide direct support * for EBCDIC. To transfer EBCDIC and other unsupported file types you * must create your own filter InputStreams and OutputStreams and wrap * them around the streams returned or required by the FTPClient methods. * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII} * filter streams to provide transparent handling of ASCII files. We will * consider incorporating EBCDIC support if there is enough demand. *

* FTP.NON_PRINT_TEXT_FORMAT , * FTP.STREAM_TRANSFER_MODE , and * FTP.FILE_STRUCTURE are the only supported formats, * transfer modes, and file structures. *

* Because the handling of sockets on different platforms can differ * significantly, the FTPClient automatically issues a new PORT (or EPRT) command * prior to every transfer requiring that the server connect to the client's * data port. This ensures identical problem-free behavior on Windows, Unix, * and Macintosh platforms. Additionally, it relieves programmers from * having to issue the PORT (or EPRT) command themselves and dealing with platform * dependent issues. *

* Additionally, for security purposes, all data connections to the * client are verified to ensure that they originated from the intended * party (host and port). If a data connection is initiated by an unexpected * party, the command will close the socket and throw an IOException. You * may disable this behavior with * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}. *

* You should keep in mind that the FTP server may choose to prematurely * close a connection if the client has been idle for longer than a * given time period (usually 900 seconds). The FTPClient class will detect a * premature FTP server connection closing when it receives a * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE } * response to a command. * When that occurs, the FTP class method encountering that reply will throw * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException} * . * FTPConnectionClosedException * is a subclass of IOException and therefore need not be * caught separately, but if you are going to catch it separately, its * catch block must appear before the more general IOException * catch block. When you encounter an * {@link org.apache.commons.net.ftp.FTPConnectionClosedException} * , you must disconnect the connection with * {@link #disconnect disconnect() } to properly clean up the * system resources used by FTPClient. Before disconnecting, you may check the * last reply code and text with * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode }, * {@link org.apache.commons.net.ftp.FTP#getReplyString getReplyString }, * and * {@link org.apache.commons.net.ftp.FTP#getReplyStrings getReplyStrings}. * You may avoid server disconnections while the client is idle by * periodically sending NOOP commands to the server. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

* Listing API Examples * Both paged and unpaged examples of directory listings are available, * as follows: *

* Unpaged (whole list) access, using a parser accessible by auto-detect: *

 *    FTPClient f = new FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPFile[] files = listFiles(directory);
 * 
*

* Paged access, using a parser not accessible by auto-detect. The class * defined in the first parameter of initateListParsing should be derived * from org.apache.commons.net.FTPFileEntryParser: *

 *    FTPClient f = new FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPListParseEngine engine =
 *       f.initiateListParsing("com.whatever.YourOwnParser", directory);
 *
 *    while (engine.hasNext()) {
 *       FTPFile[] files = engine.getNext(25);  // "page size" you want
 *       //do whatever you want with these files, display them, etc.
 *       //expensive FTPFile objects not created until needed.
 *    }
 * 
*

* Paged access, using a parser accessible by auto-detect: *

 *    FTPClient f = new FTPClient();
 *    f.connect(server);
 *    f.login(username, password);
 *    FTPListParseEngine engine = f.initiateListParsing(directory);
 *
 *    while (engine.hasNext()) {
 *       FTPFile[] files = engine.getNext(25);  // "page size" you want
 *       //do whatever you want with these files, display them, etc.
 *       //expensive FTPFile objects not created until needed.
 *    }
 * 
*

* For examples of using FTPClient on servers whose directory listings *

    *
  • use languages other than English
  • *
  • use date formats other than the American English "standard" MM d yyyy
  • *
  • are in different timezones and you need accurate timestamps for dependency checking * as in Ant
  • *
see {@link FTPClientConfig FTPClientConfig}. *

* @author Daniel F. Savarese * @author Rory Winston * @see FTP * @see FTPConnectionClosedException * @see FTPFileEntryParser * @see FTPFileEntryParserFactory * @see DefaultFTPFileEntryParserFactory * @see FTPClientConfig * * @see org.apache.commons.net.MalformedServerReplyException **/ public class FTPClient extends FTP implements Configurable { /*** * A constant indicating the FTP session is expecting all transfers * to occur between the client (local) and server and that the server * should connect to the client's data port to initiate a data transfer. * This is the default data connection mode when and FTPClient instance * is created. ***/ public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0; /*** * A constant indicating the FTP session is expecting all transfers * to occur between two remote servers and that the server * the client is connected to should connect to the other server's * data port to initiate a data transfer. ***/ public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1; /*** * A constant indicating the FTP session is expecting all transfers * to occur between the client (local) and server and that the server * is in passive mode, requiring the client to connect to the * server's data port to initiate a transfer. ***/ public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2; /*** * A constant indicating the FTP session is expecting all transfers * to occur between two remote servers and that the server * the client is connected to is in passive mode, requiring the other * server to connect to the first server's data port to initiate a data * transfer. ***/ public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3; private int __dataConnectionMode, __dataTimeout; private int __passivePort; private String __passiveHost; private final Random __random; private int __activeMinPort, __activeMaxPort; private InetAddress __activeExternalHost; private int __fileType; @SuppressWarnings("unused") // fields are written, but currently not read private int __fileFormat, __fileStructure, __fileTransferMode; private boolean __remoteVerificationEnabled; private long __restartOffset; private FTPFileEntryParserFactory __parserFactory; private int __bufferSize; private boolean __listHiddenFiles; private boolean __useEPSVwithIPv4; // whether to attempt EPSV with an IPv4 connection // __systemName is a cached value that should not be referenced directly // except when assigned in getSystemName and __initDefaults. private String __systemName; // __entryParser is a cached value that should not be referenced directly // except when assigned in listFiles(String, String) and __initDefaults. private FTPFileEntryParser __entryParser; // Key used to create the parser; necessary to ensure that the parser type is not ignored private String __entryParserKey; private FTPClientConfig __configuration; /** Pattern for PASV mode responses */ private static final String __parms = "\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}"; private static final java.util.regex.Pattern __parms_pat; static { __parms_pat = java.util.regex.Pattern.compile(__parms); } /*** * Default FTPClient constructor. Creates a new FTPClient instance * with the data connection mode set to * ACTIVE_LOCAL_DATA_CONNECTION_MODE , the file type * set to FTP.ASCII_FILE_TYPE , the * file format set to FTP.NON_PRINT_TEXT_FORMAT , * the file structure set to FTP.FILE_STRUCTURE , and * the transfer mode set to FTP.STREAM_TRANSFER_MODE . ***/ public FTPClient() { __initDefaults(); __dataTimeout = -1; __remoteVerificationEnabled = true; __parserFactory = new DefaultFTPFileEntryParserFactory(); __configuration = null; __listHiddenFiles = false; __useEPSVwithIPv4 = false; __random = new Random(); } private void __initDefaults() { __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE; __passiveHost = null; __passivePort = -1; __activeExternalHost = null; __activeMinPort = 0; __activeMaxPort = 0; __fileType = FTP.ASCII_FILE_TYPE; __fileStructure = FTP.FILE_STRUCTURE; __fileFormat = FTP.NON_PRINT_TEXT_FORMAT; __fileTransferMode = FTP.STREAM_TRANSFER_MODE; __restartOffset = 0; __systemName = null; __entryParser = null; __entryParserKey = ""; __bufferSize = Util.DEFAULT_COPY_BUFFER_SIZE; } private String __parsePathname(String reply) { int begin, end; begin = reply.indexOf('"') + 1; end = reply.indexOf('"', begin); return reply.substring(begin, end); } private void __parsePassiveModeReply(String reply) throws MalformedServerReplyException { java.util.regex.Matcher m = __parms_pat.matcher(reply); if (!m.find()) { throw new MalformedServerReplyException( "Could not parse passive host information.\nServer Reply: " + reply); } reply = m.group(); String parts[] = m.group().split(","); __passiveHost = parts[0] + '.' + parts[1] + '.' + parts[2] + '.' + parts[3]; try { int oct1 = Integer.parseInt(parts[4]); int oct2 = Integer.parseInt(parts[5]); __passivePort = (oct1 << 8) | oct2; } catch (NumberFormatException e) { throw new MalformedServerReplyException( "Could not parse passive host information.\nServer Reply: " + reply); } } private void __parseExtendedPassiveModeReply(String reply) throws MalformedServerReplyException { int port; reply = reply.substring(reply.indexOf('(') + 1, reply.indexOf(')')).trim(); char delim1, delim2, delim3, delim4; delim1 = reply.charAt(0); delim2 = reply.charAt(1); delim3 = reply.charAt(2); delim4 = reply.charAt(reply.length()-1); if (!(delim1 == delim2) || !(delim2 == delim3) || !(delim3 == delim4)) throw new MalformedServerReplyException( "Could not parse extended passive host information.\nServer Reply: " + reply); try { port = Integer.parseInt(reply.substring(3, reply.length()-1)); } catch (NumberFormatException e) { throw new MalformedServerReplyException( "Could not parse extended passive host information.\nServer Reply: " + reply); } // in EPSV mode, the passive host address is implicit __passiveHost = getRemoteAddress().getHostAddress(); __passivePort = port; } private boolean __storeFile(int command, String remote, InputStream local) throws IOException { OutputStream output; Socket socket; if ((socket = _openDataConnection_(command, remote)) == null) return false; output = new BufferedOutputStream(socket.getOutputStream(), getBufferSize() ); if (__fileType == ASCII_FILE_TYPE) output = new ToNetASCIIOutputStream(output); // Treat everything else as binary for now try { Util.copyStream(local, output, getBufferSize(), CopyStreamEvent.UNKNOWN_STREAM_SIZE, null, false); } catch (IOException e) { try { socket.close(); } catch (IOException f) {} throw e; } output.close(); socket.close(); return completePendingCommand(); } private OutputStream __storeFileStream(int command, String remote) throws IOException { OutputStream output; Socket socket; if ((socket = _openDataConnection_(command, remote)) == null) return null; output = socket.getOutputStream(); if (__fileType == ASCII_FILE_TYPE) { // We buffer ascii transfers because the buffering has to // be interposed between ToNetASCIIOutputSream and the underlying // socket output stream. We don't buffer binary transfers // because we don't want to impose a buffering policy on the // programmer if possible. Programmers can decide on their // own if they want to wrap the SocketOutputStream we return // for file types other than ASCII. output = new BufferedOutputStream(output, getBufferSize()); output = new ToNetASCIIOutputStream(output); } return new org.apache.commons.net.io.SocketOutputStream(socket, output); } /** * Establishes a data connection with the FTP server, returning * a Socket for the connection if successful. If a restart * offset has been set with {@link #setRestartOffset(long)}, * a REST command is issued to the server with the offset as * an argument before establishing the data connection. Active * mode connections also cause a local PORT command to be issued. *

* @param command The text representation of the FTP command to send. * @param arg The arguments to the FTP command. If this parameter is * set to null, then the command is sent with no argument. * @return A Socket corresponding to the established data connection. * Null is returned if an FTP protocol error is reported at * any point during the establishment and initialization of * the connection. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. */ protected Socket _openDataConnection_(int command, String arg) throws IOException { Socket socket; if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE && __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE) return null; final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address; if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE) { // if no activePortRange was set (correctly) -> getActivePort() = 0 // -> new ServerSocket(0) -> bind to any free local port ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress()); // Try EPRT only if remote server is over IPv6, if not use PORT, // because EPRT has no advantage over PORT on IPv4. // It could even have the disadvantage, // that EPRT will make the data connection fail, because // today's intelligent NAT Firewalls are able to // substitute IP addresses in the PORT command, // but might not be able to recognize the EPRT command. if (isInet6Address) { if (!FTPReply.isPositiveCompletion(eprt(getHostAddress(), server.getLocalPort()))) { server.close(); return null; } } else { if (!FTPReply.isPositiveCompletion(port(getHostAddress(), server.getLocalPort()))) { server.close(); return null; } } if ((__restartOffset > 0) && !restart(__restartOffset)) { server.close(); return null; } if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) { server.close(); return null; } // For now, let's just use the data timeout value for waiting for // the data connection. It may be desirable to let this be a // separately configurable value. In any case, we really want // to allow preventing the accept from blocking indefinitely. if (__dataTimeout >= 0) server.setSoTimeout(__dataTimeout); try { socket = server.accept(); } finally { server.close(); } } else { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE // Try EPSV command first on IPv6 - and IPv4 if enabled. // When using IPv4 with NAT it has the advantage // to work with more rare configurations. // E.g. if FTP server has a static PASV address (external network) // and the client is coming from another internal network. // In that case the data connection after PASV command would fail, // while EPSV would make the client succeed by taking just the port. boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address; if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE) { __parseExtendedPassiveModeReply(_replyLines.get(0)); } else { if (isInet6Address) { return null; // Must use EPSV for IPV6 } // If EPSV failed on IPV4, revert to PASV if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) { return null; } __parsePassiveModeReply(_replyLines.get(0)); } socket = _socketFactory_.createSocket(__passiveHost, __passivePort); if ((__restartOffset > 0) && !restart(__restartOffset)) { socket.close(); return null; } if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) { socket.close(); return null; } } if (__remoteVerificationEnabled && !verifyRemote(socket)) { InetAddress host1, host2; host1 = socket.getInetAddress(); host2 = getRemoteAddress(); socket.close(); throw new IOException( "Host attempting data connection " + host1.getHostAddress() + " is not same as server " + host2.getHostAddress()); } if (__dataTimeout >= 0) socket.setSoTimeout(__dataTimeout); return socket; } @Override protected void _connectAction_() throws IOException { super._connectAction_(); __initDefaults(); } /*** * Sets the timeout in milliseconds to use when reading from the * data connection. This timeout will be set immediately after * opening the data connection. *

* @param timeout The default timeout in milliseconds that is used when * opening a data connection socket. ***/ public void setDataTimeout(int timeout) { __dataTimeout = timeout; } /** * set the factory used for parser creation to the supplied factory object. * * @param parserFactory * factory object used to create FTPFileEntryParsers * * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory */ public void setParserFactory(FTPFileEntryParserFactory parserFactory) { __parserFactory = parserFactory; } /*** * Closes the connection to the FTP server and restores * connection parameters to the default values. *

* @exception IOException If an error occurs while disconnecting. ***/ @Override public void disconnect() throws IOException { super.disconnect(); __initDefaults(); } /*** * Enable or disable verification that the remote host taking part * of a data connection is the same as the host to which the control * connection is attached. The default is for verification to be * enabled. You may set this value at any time, whether the * FTPClient is currently connected or not. *

* @param enable True to enable verification, false to disable verification. ***/ public void setRemoteVerificationEnabled(boolean enable) { __remoteVerificationEnabled = enable; } /*** * Return whether or not verification of the remote host participating * in data connections is enabled. The default behavior is for * verification to be enabled. *

* @return True if verification is enabled, false if not. ***/ public boolean isRemoteVerificationEnabled() { return __remoteVerificationEnabled; } /*** * Login to the FTP server using the provided username and password. *

* @param username The username to login under. * @param password The password to use. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean login(String username, String password) throws IOException { user(username); if (FTPReply.isPositiveCompletion(_replyCode)) return true; // If we get here, we either have an error code, or an intermmediate // reply requesting password. if (!FTPReply.isPositiveIntermediate(_replyCode)) return false; return FTPReply.isPositiveCompletion(pass(password)); } /*** * Login to the FTP server using the provided username, password, * and account. If no account is required by the server, only * the username and password, the account information is not used. *

* @param username The username to login under. * @param password The password to use. * @param account The account to use. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean login(String username, String password, String account) throws IOException { user(username); if (FTPReply.isPositiveCompletion(_replyCode)) return true; // If we get here, we either have an error code, or an intermmediate // reply requesting password. if (!FTPReply.isPositiveIntermediate(_replyCode)) return false; pass(password); if (FTPReply.isPositiveCompletion(_replyCode)) return true; if (!FTPReply.isPositiveIntermediate(_replyCode)) return false; return FTPReply.isPositiveCompletion(acct(account)); } /*** * Logout of the FTP server by sending the QUIT command. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean logout() throws IOException { return FTPReply.isPositiveCompletion(quit()); } /*** * Change the current working directory of the FTP session. *

* @param pathname The new current working directory. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean changeWorkingDirectory(String pathname) throws IOException { return FTPReply.isPositiveCompletion(cwd(pathname)); } /*** * Change to the parent directory of the current working directory. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean changeToParentDirectory() throws IOException { return FTPReply.isPositiveCompletion(cdup()); } /*** * Issue the FTP SMNT command. *

* @param pathname The pathname to mount. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean structureMount(String pathname) throws IOException { return FTPReply.isPositiveCompletion(smnt(pathname)); } /*** * Reinitialize the FTP session. Not all FTP servers support this * command, which issues the FTP REIN command. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ boolean reinitialize() throws IOException { rein(); if (FTPReply.isPositiveCompletion(_replyCode) || (FTPReply.isPositivePreliminary(_replyCode) && FTPReply.isPositiveCompletion(getReply()))) { __initDefaults(); return true; } return false; } /*** * Set the current data connection mode to * ACTIVE_LOCAL_DATA_CONNECTION_MODE. No communication * with the FTP server is conducted, but this causes all future data * transfers to require the FTP server to connect to the client's * data port. Additionally, to accommodate differences between socket * implementations on different platforms, this method causes the * client to issue a PORT command before every data transfer. ***/ public void enterLocalActiveMode() { __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE; __passiveHost = null; __passivePort = -1; } /*** * Set the current data connection mode to * PASSIVE_LOCAL_DATA_CONNECTION_MODE . Use this * method only for data transfers between the client and server. * This method causes a PASV (or EPSV) command to be issued to the server * before the opening of every data connection, telling the server to * open a data port to which the client will connect to conduct * data transfers. The FTPClient will stay in * PASSIVE_LOCAL_DATA_CONNECTION_MODE until the * mode is changed by calling some other method such as * {@link #enterLocalActiveMode enterLocalActiveMode() } *

* N.B. currently calling any connect method will reset the mode to * ACTIVE_LOCAL_DATA_CONNECTION_MODE. ***/ public void enterLocalPassiveMode() { __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE; // These will be set when just before a data connection is opened // in _openDataConnection_() __passiveHost = null; __passivePort = -1; } /*** * Set the current data connection mode to * ACTIVE_REMOTE_DATA_CONNECTION . Use this method only * for server to server data transfers. This method issues a PORT * command to the server, indicating the other server and port to which * it should connect for data transfers. You must call this method * before EVERY server to server transfer attempt. The FTPClient will * NOT automatically continue to issue PORT commands. You also * must remember to call * {@link #enterLocalActiveMode enterLocalActiveMode() } if you * wish to return to the normal data connection mode. *

* @param host The passive mode server accepting connections for data * transfers. * @param port The passive mode server's data port. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean enterRemoteActiveMode(InetAddress host, int port) throws IOException { if (FTPReply.isPositiveCompletion(port(host, port))) { __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE; __passiveHost = null; __passivePort = -1; return true; } return false; } /*** * Set the current data connection mode to * PASSIVE_REMOTE_DATA_CONNECTION_MODE . Use this * method only for server to server data transfers. * This method issues a PASV command to the server, telling it to * open a data port to which the active server will connect to conduct * data transfers. You must call this method * before EVERY server to server transfer attempt. The FTPClient will * NOT automatically continue to issue PASV commands. You also * must remember to call * {@link #enterLocalActiveMode enterLocalActiveMode() } if you * wish to return to the normal data connection mode. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean enterRemotePassiveMode() throws IOException { if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) return false; __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE; __parsePassiveModeReply(_replyLines.get(0)); return true; } /*** * Returns the hostname or IP address (in the form of a string) returned * by the server when entering passive mode. If not in passive mode, * returns null. This method only returns a valid value AFTER a * data connection has been opened after a call to * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. * This is because FTPClient sends a PASV command to the server only * just before opening a data connection, and not when you call * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. *

* @return The passive host name if in passive mode, otherwise null. ***/ public String getPassiveHost() { return __passiveHost; } /*** * If in passive mode, returns the data port of the passive host. * This method only returns a valid value AFTER a * data connection has been opened after a call to * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. * This is because FTPClient sends a PASV command to the server only * just before opening a data connection, and not when you call * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. *

* @return The data port of the passive server. If not in passive * mode, undefined. ***/ public int getPassivePort() { return __passivePort; } /*** * Returns the current data connection mode (one of the * _DATA_CONNECTION_MODE constants. *

* @return The current data connection mode (one of the * _DATA_CONNECTION_MODE constants. ***/ public int getDataConnectionMode() { return __dataConnectionMode; } /** * Get the client port for active mode. *

* @return The client port for active mode. */ private int getActivePort() { if (__activeMinPort > 0 && __activeMaxPort >= __activeMinPort) { if (__activeMaxPort == __activeMinPort) return __activeMaxPort; // Get a random port between the min and max port range return __random.nextInt(__activeMaxPort - __activeMinPort + 1) + __activeMinPort; } else { // default port return 0; } } /** * Get the host address for active mode. *

* @return The host address for active mode. */ private InetAddress getHostAddress() { if (__activeExternalHost != null) { return __activeExternalHost; } else { // default local address return getLocalAddress(); } } /*** * Set the client side port range in active mode. *

* @param minPort The lowest available port (inclusive). * @param maxPort The highest available port (inclusive). * @since 2.2 ***/ public void setActivePortRange(int minPort, int maxPort) { this.__activeMinPort = minPort; this.__activeMaxPort = maxPort; } /*** * Set the external IP address in active mode. * Useful when there are multiple network cards. *

* @param ipAddress The external IP address of this machine. * @throws UnknownHostException * @since 2.2 ***/ public void setActiveExternalIPAddress(String ipAddress) throws UnknownHostException { this.__activeExternalHost = InetAddress.getByName(ipAddress); } /*** * Sets the file type to be transferred. This should be one of * FTP.ASCII_FILE_TYPE , FTP.BINARY_FILE_TYPE, * etc. The file type only needs to be set when you want to change the * type. After changing it, the new type stays in effect until you change * it again. The default file type is FTP.ASCII_FILE_TYPE * if this method is never called. *

* N.B. currently calling any connect method will reset the mode to * ACTIVE_LOCAL_DATA_CONNECTION_MODE. * @param fileType The _FILE_TYPE constant indcating the * type of file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean setFileType(int fileType) throws IOException { if (FTPReply.isPositiveCompletion(type(fileType))) { __fileType = fileType; __fileFormat = FTP.NON_PRINT_TEXT_FORMAT; return true; } return false; } /*** * Sets the file type to be transferred and the format. The type should be * one of FTP.ASCII_FILE_TYPE , * FTP.BINARY_FILE_TYPE , etc. The file type only needs to * be set when you want to change the type. After changing it, the new * type stays in effect until you change it again. The default file type * is FTP.ASCII_FILE_TYPE if this method is never called. * The format should be one of the FTP class TEXT_FORMAT * constants, or if the type is FTP.LOCAL_FILE_TYPE , the * format should be the byte size for that type. The default format * is FTP.NON_PRINT_TEXT_FORMAT if this method is never * called. *

* N.B. currently calling any connect method will reset the mode to * ACTIVE_LOCAL_DATA_CONNECTION_MODE. *

* @param fileType The _FILE_TYPE constant indcating the * type of file. * @param formatOrByteSize The format of the file (one of the * _FORMAT constants. In the case of * LOCAL_FILE_TYPE, the byte size. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean setFileType(int fileType, int formatOrByteSize) throws IOException { if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize))) { __fileType = fileType; __fileFormat = formatOrByteSize; return true; } return false; } /*** * Sets the file structure. The default structure is * FTP.FILE_STRUCTURE if this method is never called. *

* @param structure The structure of the file (one of the FTP class * _STRUCTURE constants). * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean setFileStructure(int structure) throws IOException { if (FTPReply.isPositiveCompletion(stru(structure))) { __fileStructure = structure; return true; } return false; } /*** * Sets the transfer mode. The default transfer mode * FTP.STREAM_TRANSFER_MODE if this method is never called. *

* @param mode The new transfer mode to use (one of the FTP class * _TRANSFER_MODE constants). * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean setFileTransferMode(int mode) throws IOException { if (FTPReply.isPositiveCompletion(mode(mode))) { __fileTransferMode = mode; return true; } return false; } /*** * Initiate a server to server file transfer. This method tells the * server to which the client is connected to retrieve a given file from * the other server. *

* @param filename The name of the file to retrieve. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean remoteRetrieve(String filename) throws IOException { if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) return FTPReply.isPositivePreliminary(retr(filename)); return false; } /*** * Initiate a server to server file transfer. This method tells the * server to which the client is connected to store a file on * the other server using the given filename. The other server must * have had a remoteRetrieve issued to it by another * FTPClient. *

* @param filename The name to call the file that is to be stored. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean remoteStore(String filename) throws IOException { if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) return FTPReply.isPositivePreliminary(stor(filename)); return false; } /*** * Initiate a server to server file transfer. This method tells the * server to which the client is connected to store a file on * the other server using a unique filename based on the given filename. * The other server must have had a remoteRetrieve issued * to it by another FTPClient. *

* @param filename The name on which to base the filename of the file * that is to be stored. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean remoteStoreUnique(String filename) throws IOException { if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) return FTPReply.isPositivePreliminary(stou(filename)); return false; } /*** * Initiate a server to server file transfer. This method tells the * server to which the client is connected to store a file on * the other server using a unique filename. * The other server must have had a remoteRetrieve issued * to it by another FTPClient. Many FTP servers require that a base * filename be given from which the unique filename can be derived. For * those servers use the other version of remoteStoreUnique *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean remoteStoreUnique() throws IOException { if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) return FTPReply.isPositivePreliminary(stou()); return false; } // For server to server transfers /*** * Initiate a server to server file transfer. This method tells the * server to which the client is connected to append to a given file on * the other server. The other server must have had a * remoteRetrieve issued to it by another FTPClient. *

* @param filename The name of the file to be appended to, or if the * file does not exist, the name to call the file being stored. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean remoteAppend(String filename) throws IOException { if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) return FTPReply.isPositivePreliminary(appe(filename)); return false; } /*** * There are a few FTPClient methods that do not complete the * entire sequence of FTP commands to complete a transaction. These * commands require some action by the programmer after the reception * of a positive intermediate command. After the programmer's code * completes its actions, it must call this method to receive * the completion reply from the server and verify the success of the * entire transaction. *

* For example, *

     * InputStream input;
     * OutputStream output;
     * input  = new FileInputStream("foobaz.txt");
     * output = ftp.storeFileStream("foobar.txt")
     * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
     *     input.close();
     *     output.close();
     *     ftp.logout();
     *     ftp.disconnect();
     *     System.err.println("File transfer failed.");
     *     System.exit(1);
     * }
     * Util.copyStream(input, output);
     * input.close();
     * output.close();
     * // Must call completePendingCommand() to finish command.
     * if(!ftp.completePendingCommand()) {
     *     ftp.logout();
     *     ftp.disconnect();
     *     System.err.println("File transfer failed.");
     *     System.exit(1);
     * }
     * 
*

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean completePendingCommand() throws IOException { return FTPReply.isPositiveCompletion(getReply()); } /*** * Retrieves a named file from the server and writes it to the given * OutputStream. This method does NOT close the given OutputStream. * If the current file type is ASCII, line separators in the file are * converted to the local representation. *

* Note: if you have used {@link #setRestartOffset(long)}, * the file data will start from the selected offset. * @param remote The name of the remote file. * @param local The local OutputStream to which to write the file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception CopyStreamException If an I/O error occurs while actually * transferring the file. The CopyStreamException allows you to * determine the number of bytes transferred and the IOException * causing the error. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean retrieveFile(String remote, OutputStream local) throws IOException { InputStream input; Socket socket; if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null) return false; input = new BufferedInputStream(socket.getInputStream(), getBufferSize()); if (__fileType == ASCII_FILE_TYPE) input = new FromNetASCIIInputStream(input); // Treat everything else as binary for now try { Util.copyStream(input, local, getBufferSize(), CopyStreamEvent.UNKNOWN_STREAM_SIZE, null, false); } catch (IOException e) { try { socket.close(); } catch (IOException f) {} throw e; } socket.close(); return completePendingCommand(); } /*** * Returns an InputStream from which a named file from the server * can be read. If the current file type is ASCII, the returned * InputStream will convert line separators in the file to * the local representation. You must close the InputStream when you * finish reading from it. The InputStream itself will take care of * closing the parent data connection socket upon being closed. To * finalize the file transfer you must call * {@link #completePendingCommand completePendingCommand } and * check its return value to verify success. *

* Note: if you have used {@link #setRestartOffset(long)}, * the file data will start from the selected offset. * * @param remote The name of the remote file. * @return An InputStream from which the remote file can be read. If * the data connection cannot be opened (e.g., the file does not * exist), null is returned (in which case you may check the reply * code to determine the exact reason for failure). * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public InputStream retrieveFileStream(String remote) throws IOException { InputStream input; Socket socket; if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null) return null; input = socket.getInputStream(); if (__fileType == ASCII_FILE_TYPE) { // We buffer ascii transfers because the buffering has to // be interposed between FromNetASCIIOutputSream and the underlying // socket input stream. We don't buffer binary transfers // because we don't want to impose a buffering policy on the // programmer if possible. Programmers can decide on their // own if they want to wrap the SocketInputStream we return // for file types other than ASCII. input = new BufferedInputStream(input, getBufferSize()); input = new FromNetASCIIInputStream(input); } return new org.apache.commons.net.io.SocketInputStream(socket, input); } /*** * Stores a file on the server using the given name and taking input * from the given InputStream. This method does NOT close the given * InputStream. If the current file type is ASCII, line separators in * the file are transparently converted to the NETASCII format (i.e., * you should not attempt to create a special InputStream to do this). *

* @param remote The name to give the remote file. * @param local The local InputStream from which to read the file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception CopyStreamException If an I/O error occurs while actually * transferring the file. The CopyStreamException allows you to * determine the number of bytes transferred and the IOException * causing the error. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean storeFile(String remote, InputStream local) throws IOException { return __storeFile(FTPCommand.STOR, remote, local); } /*** * Returns an OutputStream through which data can be written to store * a file on the server using the given name. If the current file type * is ASCII, the returned OutputStream will convert line separators in * the file to the NETASCII format (i.e., you should not attempt to * create a special OutputStream to do this). You must close the * OutputStream when you finish writing to it. The OutputStream itself * will take care of closing the parent data connection socket upon being * closed. To finalize the file transfer you must call * {@link #completePendingCommand completePendingCommand } and * check its return value to verify success. *

* @param remote The name to give the remote file. * @return An OutputStream through which the remote file can be written. If * the data connection cannot be opened (e.g., the file does not * exist), null is returned (in which case you may check the reply * code to determine the exact reason for failure). * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public OutputStream storeFileStream(String remote) throws IOException { return __storeFileStream(FTPCommand.STOR, remote); } /*** * Appends to a file on the server with the given name, taking input * from the given InputStream. This method does NOT close the given * InputStream. If the current file type is ASCII, line separators in * the file are transparently converted to the NETASCII format (i.e., * you should not attempt to create a special InputStream to do this). *

* @param remote The name of the remote file. * @param local The local InputStream from which to read the data to * be appended to the remote file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception CopyStreamException If an I/O error occurs while actually * transferring the file. The CopyStreamException allows you to * determine the number of bytes transferred and the IOException * causing the error. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean appendFile(String remote, InputStream local) throws IOException { return __storeFile(FTPCommand.APPE, remote, local); } /*** * Returns an OutputStream through which data can be written to append * to a file on the server with the given name. If the current file type * is ASCII, the returned OutputStream will convert line separators in * the file to the NETASCII format (i.e., you should not attempt to * create a special OutputStream to do this). You must close the * OutputStream when you finish writing to it. The OutputStream itself * will take care of closing the parent data connection socket upon being * closed. To finalize the file transfer you must call * {@link #completePendingCommand completePendingCommand } and * check its return value to verify success. *

* @param remote The name of the remote file. * @return An OutputStream through which the remote file can be appended. * If the data connection cannot be opened (e.g., the file does not * exist), null is returned (in which case you may check the reply * code to determine the exact reason for failure). * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public OutputStream appendFileStream(String remote) throws IOException { return __storeFileStream(FTPCommand.APPE, remote); } /*** * Stores a file on the server using a unique name derived from the * given name and taking input * from the given InputStream. This method does NOT close the given * InputStream. If the current file type is ASCII, line separators in * the file are transparently converted to the NETASCII format (i.e., * you should not attempt to create a special InputStream to do this). *

* @param remote The name on which to base the unique name given to * the remote file. * @param local The local InputStream from which to read the file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception CopyStreamException If an I/O error occurs while actually * transferring the file. The CopyStreamException allows you to * determine the number of bytes transferred and the IOException * causing the error. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean storeUniqueFile(String remote, InputStream local) throws IOException { return __storeFile(FTPCommand.STOU, remote, local); } /*** * Returns an OutputStream through which data can be written to store * a file on the server using a unique name derived from the given name. * If the current file type * is ASCII, the returned OutputStream will convert line separators in * the file to the NETASCII format (i.e., you should not attempt to * create a special OutputStream to do this). You must close the * OutputStream when you finish writing to it. The OutputStream itself * will take care of closing the parent data connection socket upon being * closed. To finalize the file transfer you must call * {@link #completePendingCommand completePendingCommand } and * check its return value to verify success. *

* @param remote The name on which to base the unique name given to * the remote file. * @return An OutputStream through which the remote file can be written. If * the data connection cannot be opened (e.g., the file does not * exist), null is returned (in which case you may check the reply * code to determine the exact reason for failure). * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public OutputStream storeUniqueFileStream(String remote) throws IOException { return __storeFileStream(FTPCommand.STOU, remote); } /** * Stores a file on the server using a unique name assigned by the * server and taking input from the given InputStream. This method does * NOT close the given * InputStream. If the current file type is ASCII, line separators in * the file are transparently converted to the NETASCII format (i.e., * you should not attempt to create a special InputStream to do this). *

* @param local The local InputStream from which to read the file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception CopyStreamException If an I/O error occurs while actually * transferring the file. The CopyStreamException allows you to * determine the number of bytes transferred and the IOException * causing the error. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. */ public boolean storeUniqueFile(InputStream local) throws IOException { return __storeFile(FTPCommand.STOU, null, local); } /** * Returns an OutputStream through which data can be written to store * a file on the server using a unique name assigned by the server. * If the current file type * is ASCII, the returned OutputStream will convert line separators in * the file to the NETASCII format (i.e., you should not attempt to * create a special OutputStream to do this). You must close the * OutputStream when you finish writing to it. The OutputStream itself * will take care of closing the parent data connection socket upon being * closed. To finalize the file transfer you must call * {@link #completePendingCommand completePendingCommand } and * check its return value to verify success. *

* @return An OutputStream through which the remote file can be written. If * the data connection cannot be opened (e.g., the file does not * exist), null is returned (in which case you may check the reply * code to determine the exact reason for failure). * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. */ public OutputStream storeUniqueFileStream() throws IOException { return __storeFileStream(FTPCommand.STOU, null); } /*** * Reserve a number of bytes on the server for the next file transfer. *

* @param bytes The number of bytes which the server should allocate. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean allocate(int bytes) throws IOException { return FTPReply.isPositiveCompletion(allo(bytes)); } /** * Query the server for supported features. The server may reply with a list of server-supported exensions. * For example, a typical client-server interaction might be (from RFC 2289): *

        C> feat
        S> 211-Extensions supported:
        S>  MLST size*;create;modify*;perm;media-type
        S>  SIZE
        S>  COMPRESSION
        S>  MDTM
        S> 211 END
     * 
* @see http://www.faqs.org/rfcs/rfc2389.html * @return True if successfully completed, false if not. * @throws IOException * @since 2.2 */ public boolean features() throws IOException { return FTPReply.isPositiveCompletion(feat()); } /** * Reserve space on the server for the next file transfer. *

* @param bytes The number of bytes which the server should allocate. * @param recordSize The size of a file record. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. */ public boolean allocate(int bytes, int recordSize) throws IOException { return FTPReply.isPositiveCompletion(allo(bytes, recordSize)); } /*** * Restart a STREAM_TRANSFER_MODE file transfer starting * from the given offset. This will only work on FTP servers supporting * the REST comand for the stream transfer mode. However, most FTP * servers support this. Any subsequent file transfer will start * reading or writing the remote file from the indicated offset. *

* @param offset The offset into the remote file at which to start the * next file transfer. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ private boolean restart(long offset) throws IOException { __restartOffset = 0; return FTPReply.isPositiveIntermediate(rest(Long.toString(offset))); } /*** * Sets the restart offset. The restart command is sent to the server * only before sending the file transfer command. When this is done, * the restart marker is reset to zero. *

* @param offset The offset into the remote file at which to start the * next file transfer. This must be a value greater than or * equal to zero. ***/ public void setRestartOffset(long offset) { if (offset >= 0) __restartOffset = offset; } /*** * Fetches the restart offset. *

* @return offset The offset into the remote file at which to start the * next file transfer. ***/ public long getRestartOffset() { return __restartOffset; } /*** * Renames a remote file. *

* @param from The name of the remote file to rename. * @param to The new name of the remote file. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean rename(String from, String to) throws IOException { if (!FTPReply.isPositiveIntermediate(rnfr(from))) return false; return FTPReply.isPositiveCompletion(rnto(to)); } /*** * Abort a transfer in progress. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean abort() throws IOException { return FTPReply.isPositiveCompletion(abor()); } /*** * Deletes a file on the FTP server. *

* @param pathname The pathname of the file to be deleted. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean deleteFile(String pathname) throws IOException { return FTPReply.isPositiveCompletion(dele(pathname)); } /*** * Removes a directory on the FTP server (if empty). *

* @param pathname The pathname of the directory to remove. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean removeDirectory(String pathname) throws IOException { return FTPReply.isPositiveCompletion(rmd(pathname)); } /*** * Creates a new subdirectory on the FTP server in the current directory * (if a relative pathname is given) or where specified (if an absolute * pathname is given). *

* @param pathname The pathname of the directory to create. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean makeDirectory(String pathname) throws IOException { return FTPReply.isPositiveCompletion(mkd(pathname)); } /*** * Returns the pathname of the current working directory. *

* @return The pathname of the current working directory. If it cannot * be obtained, returns null. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String printWorkingDirectory() throws IOException { if (pwd() != FTPReply.PATHNAME_CREATED) return null; return __parsePathname(_replyLines.get( _replyLines.size() - 1)); } /** * Send a site specific command. * @param arguments The site specific command and arguments. * @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. */ public boolean sendSiteCommand(String arguments) throws IOException { return FTPReply.isPositiveCompletion(site(arguments)); } /*** * Fetches the system type name from the server and returns the string. * This value is cached for the duration of the connection after the * first call to this method. In other words, only the first time * that you invoke this method will it issue a SYST command to the * FTP server. FTPClient will remember the value and return the * cached value until a call to disconnect. *

* @return The system type name obtained from the server. null if the * information could not be obtained. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. * @deprecated Use {@link #getSystemType()} - which does not return null. * Will be deleted in version 3.0 ***/ @Deprecated public String getSystemName() throws IOException { //if (syst() == FTPReply.NAME_SYSTEM_TYPE) // Technically, we should expect a NAME_SYSTEM_TYPE response, but // in practice FTP servers deviate, so we soften the condition to // a positive completion. if (__systemName == null && FTPReply.isPositiveCompletion(syst())) __systemName = _replyLines.get(_replyLines.size() - 1).substring(4); return __systemName; } /*** * Fetches the system type from the server and returns the string. * This value is cached for the duration of the connection after the * first call to this method. In other words, only the first time * that you invoke this method will it issue a SYST command to the * FTP server. FTPClient will remember the value and return the * cached value until a call to disconnect. *

* @return The system type obtained from the server. Never null. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. * @since 2.2 ***/ public String getSystemType() throws IOException { //if (syst() == FTPReply.NAME_SYSTEM_TYPE) // Technically, we should expect a NAME_SYSTEM_TYPE response, but // in practice FTP servers deviate, so we soften the condition to // a positive completion. if (__systemName == null){ if (FTPReply.isPositiveCompletion(syst())) { // Assume that response is not empty here (cannot be null) __systemName = _replyLines.get(_replyLines.size() - 1).substring(4); } else { throw new IOException("Unable to determine system type - response: " + getReplyString()); } } return __systemName; } /*** * Fetches the system help information from the server and returns the * full string. *

* @return The system help string obtained from the server. null if the * information could not be obtained. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String listHelp() throws IOException { if (FTPReply.isPositiveCompletion(help())) return getReplyString(); return null; } /** * Fetches the help information for a given command from the server and * returns the full string. * @param command The command on which to ask for help. * @return The command help string obtained from the server. null if the * information could not be obtained. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. */ public String listHelp(String command) throws IOException { if (FTPReply.isPositiveCompletion(help(command))) return getReplyString(); return null; } /*** * Sends a NOOP command to the FTP server. This is useful for preventing * server timeouts. *

* @return True if successfully completed, false if not. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public boolean sendNoOp() throws IOException { return FTPReply.isPositiveCompletion(noop()); } /*** * Obtain a list of filenames in a directory (or just the name of a given * file, which is not particularly useful). This information is obtained * through the NLST command. If the given pathname is a directory and * contains no files, a zero length array is returned only * if the FTP server returned a positive completion code, otherwise * null is returned (the FTP server returned a 550 error No files found.). * If the directory is not empty, an array of filenames in the directory is * returned. If the pathname corresponds * to a file, only that file will be listed. The server may or may not * expand glob expressions. *

* @param pathname The file or directory to list. * @return The list of filenames contained in the given path. null if * the list could not be obtained. If there are no filenames in * the directory, a zero-length array is returned. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String[] listNames(String pathname) throws IOException { String line; Socket socket; BufferedReader reader; ArrayList results; if ((socket = _openDataConnection_(FTPCommand.NLST, pathname)) == null) return null; reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding())); results = new ArrayList(); while ((line = reader.readLine()) != null) results.add(line); reader.close(); socket.close(); if (completePendingCommand()) { String[] names = new String[ results.size() ]; return results.toArray(names); } return null; } /*** * Obtain a list of filenames in the current working directory * This information is obtained through the NLST command. If the current * directory contains no files, a zero length array is returned only * if the FTP server returned a positive completion code, otherwise, * null is returned (the FTP server returned a 550 error No files found.). * If the directory is not empty, an array of filenames in the directory is * returned. *

* @return The list of filenames contained in the current working * directory. null if the list could not be obtained. * If there are no filenames in the directory, a zero-length array * is returned. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String[] listNames() throws IOException { return listNames(null); } /** * Using the default system autodetect mechanism, obtain a * list of file information for the current working directory * or for just a single file. *

* This information is obtained through the LIST command. The contents of * the returned array is determined by the FTPFileEntryParser * used. *

* @param pathname The file or directory to list. Since the server may * or may not expand glob expressions, using them here * is not recommended and may well cause this method to * fail. * * @return The list of file information contained in the given path in * the format determined by the autodetection mechanism * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection * as a result of the client being idle or some other * reason causing the server to send FTP reply code 421. * This exception may be caught either as an IOException * or independently as itself. * @exception IOException * If an I/O error occurs while either sending a * command to the server or receiving a reply * from the server. * @exception ParserInitializationException * Thrown if the parserKey parameter cannot be * resolved by the selected parser factory. * In the DefaultFTPEntryParserFactory, this will * happen when parserKey is neither * the fully qualified class name of a class * implementing the interface * org.apache.commons.net.ftp.FTPFileEntryParser * nor a string containing one of the recognized keys * mapping to such a parser or if class loader * security issues prevent its being loaded. * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory * @see org.apache.commons.net.ftp.FTPFileEntryParser */ public FTPFile[] listFiles(String pathname) throws IOException { String key = null; FTPListParseEngine engine = initiateListParsing(key, pathname); return engine.getFiles(); } /** * Using the default system autodetect mechanism, obtain a * list of file information for the current working directory. *

* This information is obtained through the LIST command. The contents of * the returned array is determined by the FTPFileEntryParser * used. *

* @return The list of file information contained in the current directory * in the format determined by the autodetection mechanism. *

* NOTE: This array may contain null members if any of the * individual file listings failed to parse. The caller should * check each entry for null before referencing it. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection * as a result of the client being idle or some other * reason causing the server to send FTP reply code 421. * This exception may be caught either as an IOException * or independently as itself. * @exception IOException * If an I/O error occurs while either sending a * command to the server or receiving a reply * from the server. * @exception ParserInitializationException * Thrown if the parserKey parameter cannot be * resolved by the selected parser factory. * In the DefaultFTPEntryParserFactory, this will * happen when parserKey is neither * the fully qualified class name of a class * implementing the interface * org.apache.commons.net.ftp.FTPFileEntryParser * nor a string containing one of the recognized keys * mapping to such a parser or if class loader * security issues prevent its being loaded. * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory * @see org.apache.commons.net.ftp.FTPFileEntryParser */ public FTPFile[] listFiles() throws IOException { return listFiles((String) null); } /** * Version of {@link #listFiles(String)} which allows a filter to be provided. * For example: listFiles("site", FTPFileFilters.DIRECTORY); * @param pathname the initial path, may be null * @param filter the filter, non-null * @return the list of FTPFile entries. * @throws IOException * @since 2.2 */ public FTPFile[] listFiles(String pathname, FTPFileFilter filter) throws IOException { FTPListParseEngine engine = initiateListParsing((String) null, pathname); return engine.getFiles(filter); } /** * Using the default autodetect mechanism, initialize an FTPListParseEngine * object containing a raw file information for the current working * directory on the server * This information is obtained through the LIST command. This object * is then capable of being iterated to return a sequence of FTPFile * objects with information filled in by the * FTPFileEntryParser used. *

* This method differs from using the listFiles() methods in that * expensive FTPFile objects are not created until needed which may be * an advantage on large lists. * * @return A FTPListParseEngine object that holds the raw information and * is capable of providing parsed FTPFile objects, one for each file * containing information contained in the given path in the format * determined by the parser parameter. Null will be * returned if a data connection cannot be opened. If the current working * directory contains no files, an empty array will be the return. * * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException * If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. * @exception ParserInitializationException * Thrown if the autodetect mechanism cannot * resolve the type of system we are connected with. * @see FTPListParseEngine */ public FTPListParseEngine initiateListParsing() throws IOException { return initiateListParsing((String) null); } /** * Using the default autodetect mechanism, initialize an FTPListParseEngine * object containing a raw file information for the supplied directory. * This information is obtained through the LIST command. This object * is then capable of being iterated to return a sequence of FTPFile * objects with information filled in by the * FTPFileEntryParser used. *

* The server may or may not expand glob expressions. You should avoid * using glob expressions because the return format for glob listings * differs from server to server and will likely cause this method to fail. *

* This method differs from using the listFiles() methods in that * expensive FTPFile objects are not created until needed which may be * an advantage on large lists. *

*

     *    FTPClient f=FTPClient();
     *    f.connect(server);
     *    f.login(username, password);
     *    FTPListParseEngine engine = f.initiateListParsing(directory);
     *
     *    while (engine.hasNext()) {
     *       FTPFile[] files = engine.getNext(25);  // "page size" you want
     *       //do whatever you want with these files, display them, etc.
     *       //expensive FTPFile objects not created until needed.
     *    }
     * 
* * @return A FTPListParseEngine object that holds the raw information and * is capable of providing parsed FTPFile objects, one for each file * containing information contained in the given path in the format * determined by the parser parameter. Null will be * returned if a data connection cannot be opened. If the current working * directory contains no files, an empty array will be the return. * * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException * If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. * @exception ParserInitializationException * Thrown if the autodetect mechanism cannot * resolve the type of system we are connected with. * @see FTPListParseEngine */ public FTPListParseEngine initiateListParsing( String pathname) throws IOException { String key = null; return initiateListParsing(key, pathname); } /** * Using the supplied parser key, initialize an FTPListParseEngine * object containing a raw file information for the supplied directory. * This information is obtained through the LIST command. This object * is then capable of being iterated to return a sequence of FTPFile * objects with information filled in by the * FTPFileEntryParser used. *

* The server may or may not expand glob expressions. You should avoid * using glob expressions because the return format for glob listings * differs from server to server and will likely cause this method to fail. *

* This method differs from using the listFiles() methods in that * expensive FTPFile objects are not created until needed which may be * an advantage on large lists. * * @param parserKey A string representing a designated code or fully-qualified * class name of an FTPFileEntryParser that should be * used to parse each server file listing. * * @return A FTPListParseEngine object that holds the raw information and * is capable of providing parsed FTPFile objects, one for each file * containing information contained in the given path in the format * determined by the parser parameter. Null will be * returned if a data connection cannot be opened. If the current working * directory contains no files, an empty array will be the return. * * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException * If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. * @exception ParserInitializationException * Thrown if the parserKey parameter cannot be * resolved by the selected parser factory. * In the DefaultFTPEntryParserFactory, this will * happen when parserKey is neither * the fully qualified class name of a class * implementing the interface * org.apache.commons.net.ftp.FTPFileEntryParser * nor a string containing one of the recognized keys * mapping to such a parser or if class loader * security issues prevent its being loaded. * @see FTPListParseEngine */ public FTPListParseEngine initiateListParsing( String parserKey, String pathname) throws IOException { // We cache the value to avoid creation of a new object every // time a file listing is generated. if(__entryParser == null || ! __entryParserKey.equals(parserKey)) { if (null != parserKey) { // if a parser key was supplied in the parameters, // use that to create the parser __entryParser = __parserFactory.createFileEntryParser(parserKey); __entryParserKey = parserKey; } else { // if no parserKey was supplied, check for a configuration // in the params, and if non-null, use that. if (null != __configuration) { __entryParser = __parserFactory.createFileEntryParser(__configuration); __entryParserKey = __configuration.getServerSystemKey(); } else { // if a parserKey hasn't been supplied, and a configuration // hasn't been supplied, then autodetect by calling // the SYST command and use that to choose the parser. final String systemType = getSystemType(); // cannot be null __entryParser = __parserFactory.createFileEntryParser(systemType); __entryParserKey = systemType; } } } return initiateListParsing(__entryParser, pathname); } /** * private method through which all listFiles() and * initiateListParsing methods pass once a parser is determined. * * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException * If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. * @see FTPListParseEngine */ private FTPListParseEngine initiateListParsing( FTPFileEntryParser parser, String pathname) throws IOException { Socket socket; FTPListParseEngine engine = new FTPListParseEngine(parser); if ((socket = _openDataConnection_(FTPCommand.LIST, getListArguments(pathname))) == null) { return engine; } try { engine.readServerList(socket.getInputStream(), getControlEncoding()); } finally { socket.close(); } completePendingCommand(); return engine; } /** * @since 2.0 */ protected String getListArguments(String pathname) { if (getListHiddenFiles()) { if (pathname != null) { StringBuilder sb = new StringBuilder(pathname.length() + 3); sb.append("-a "); sb.append(pathname); return sb.toString(); } else { return "-a"; } } return pathname; } /*** * Issue the FTP STAT command to the server. *

* @return The status information returned by the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String getStatus() throws IOException { if (FTPReply.isPositiveCompletion(stat())) return getReplyString(); return null; } /*** * Issue the FTP STAT command to the server for a given pathname. This * should produce a listing of the file or directory. *

* @return The status information returned by the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a * command to the server or receiving a reply from the server. ***/ public String getStatus(String pathname) throws IOException { if (FTPReply.isPositiveCompletion(stat(pathname))) return getReplyString(); return null; } /** * Issue the FTP MDTM command (not supported by all servers to retrieve the last * modification time of a file. The modification string should be in the * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in * GMT, but not all FTP servers honour this. * * @param pathname The file path to query. * @return A string representing the last file modification time in YYYYMMDDhhmmss format. * @throws IOException if an I/O error occurs. * @since 2.0 */ public String getModificationTime(String pathname) throws IOException { if (FTPReply.isPositiveCompletion(mdtm(pathname))) return getReplyString(); return null; } /** * Issue the FTP MFMT command (not supported by all servers) which sets the last * modified time of a file. * * The timestamp should be in the form YYYYMMDDhhmmss. It should also * be in GMT, but not all servers honour this. * * An FTP server would indicate its support of this feature by including "MFMT" * in its response to the FEAT command, which may be retrieved by FTPClient.features() * * @param pathname The file path for which last modified time is to be changed. * @param timeval The timestamp to set to, in YYYYMMDDhhmmss format. * @return true if successfully set, false if not * @throws IOException if an I/O error occurs. * @since 2.2 * @see http://tools.ietf.org/html/draft-somers-ftp-mfxx-04 */ public boolean setModificationTime(String pathname, String timeval) throws IOException { return (FTPReply.isPositiveCompletion(mfmt(pathname, timeval))); } /** * Set the internal buffer size. * * @param bufSize The size of the buffer */ public void setBufferSize(int bufSize) { __bufferSize = bufSize; } /** * Retrieve the current internal buffer size. * @return The current buffer size. */ public int getBufferSize() { return __bufferSize; } /** * Implementation of the {@link Configurable Configurable} interface. * In the case of this class, configuring merely makes the config object available for the * factory methods that construct parsers. * @param config {@link FTPClientConfig FTPClientConfig} object used to * provide non-standard configurations to the parser. * @since 1.4 */ public void configure(FTPClientConfig config) { this.__configuration = config; } /** * You can set this to true if you would like to get hidden files when {@link #listFiles} too. * A LIST -a will be issued to the ftp server. * It depends on your ftp server if you need to call this method, also dont expect to get rid * of hidden files if you call this method with "false". * * @param listHiddenFiles true if hidden files should be listed * @since 2.0 */ public void setListHiddenFiles(boolean listHiddenFiles) { this.__listHiddenFiles = listHiddenFiles; } /** * @see #setListHiddenFiles(boolean) * @return the current state * @since 2.0 */ public boolean getListHiddenFiles() { return this.__listHiddenFiles; } /** * Whether should attempt to use EPSV with IPv4. * Default (if not set) is false * @return true if should attempt EPS * @since 2.2 */ public boolean isUseEPSVwithIPv4() { return __useEPSVwithIPv4; } /** * Set whether to use EPSV with IPv4. * Might be worth enabling in some circumstances. * * For example, when using IPv4 with NAT it * may work with some rare configurations. * E.g. if FTP server has a static PASV address (external network) * and the client is coming from another internal network. * In that case the data connection after PASV command would fail, * while EPSV would make the client succeed by taking just the port. * * @param selected value to set. * @since 2.2 */ public void setUseEPSVwithIPv4(boolean selected) { this.__useEPSVwithIPv4 = selected; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTP.java0000644000175000017500000020407111466235516024561 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.util.ArrayList; import org.apache.commons.net.MalformedServerReplyException; import org.apache.commons.net.ProtocolCommandListener; import org.apache.commons.net.ProtocolCommandSupport; import org.apache.commons.net.SocketClient; /*** * FTP provides the basic the functionality necessary to implement your * own FTP client. It extends org.apache.commons.net.SocketClient since * extending TelnetClient was causing unwanted behavior (like connections * that did not time out properly). *

* To derive the full benefits of the FTP class requires some knowledge * of the FTP protocol defined in RFC 959. However, there is no reason * why you should have to use the FTP class. The * {@link org.apache.commons.net.ftp.FTPClient} class, * derived from FTP, * implements all the functionality required of an FTP client. The * FTP class is made public to provide access to various FTP constants * and to make it easier for adventurous programmers (or those with * special needs) to interact with the FTP protocol and implement their * own clients. A set of methods with names corresponding to the FTP * command names are provided to facilitate this interaction. *

* You should keep in mind that the FTP server may choose to prematurely * close a connection if the client has been idle for longer than a * given time period (usually 900 seconds). The FTP class will detect a * premature FTP server connection closing when it receives a * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE } * response to a command. * When that occurs, the FTP class method encountering that reply will throw * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException} * . FTPConectionClosedException * is a subclass of IOException and therefore need not be * caught separately, but if you are going to catch it separately, its * catch block must appear before the more general IOException * catch block. When you encounter an * {@link org.apache.commons.net.ftp.FTPConnectionClosedException} * , you must disconnect the connection with * {@link #disconnect disconnect() } to properly clean up the * system resources used by FTP. Before disconnecting, you may check the * last reply code and text with * {@link #getReplyCode getReplyCode }, * {@link #getReplyString getReplyString }, * and {@link #getReplyStrings getReplyStrings}. * You may avoid server disconnections while the client is idle by * periodicaly sending NOOP commands to the server. *

* Rather than list it separately for each method, we mention here that * every method communicating with the server and throwing an IOException * can also throw a * {@link org.apache.commons.net.MalformedServerReplyException} * , which is a subclass * of IOException. A MalformedServerReplyException will be thrown when * the reply received from the server deviates enough from the protocol * specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. *

*

* @author Daniel F. Savarese * @author Rory Winston * @author Joseph Hindsley * @see FTPClient * @see FTPConnectionClosedException * @see org.apache.commons.net.MalformedServerReplyException * @version $Id: FTP.java 1032954 2010-11-09 12:15:10Z sebb $ ***/ public class FTP extends SocketClient { /*** The default FTP data port (20). ***/ public static final int DEFAULT_DATA_PORT = 20; /*** The default FTP control port (21). ***/ public static final int DEFAULT_PORT = 21; /*** * A constant used to indicate the file(s) being transfered should * be treated as ASCII. This is the default file type. All constants * ending in FILE_TYPE are used to indicate file types. ***/ public static final int ASCII_FILE_TYPE = 0; /*** * A constant used to indicate the file(s) being transfered should * be treated as EBCDIC. Note however that there are several different * EBCDIC formats. All constants ending in FILE_TYPE * are used to indicate file types. ***/ public static final int EBCDIC_FILE_TYPE = 1; /*** * A constant used to indicate the file(s) being transfered should * be treated as a binary image, i.e., no translations should be * performed. All constants ending in FILE_TYPE are used to * indicate file types. ***/ public static final int BINARY_FILE_TYPE = 2; /*** * A constant used to indicate the file(s) being transfered should * be treated as a local type. All constants ending in * FILE_TYPE are used to indicate file types. ***/ public static final int LOCAL_FILE_TYPE = 3; /*** * A constant used for text files to indicate a non-print text format. * This is the default format. * All constants ending in TEXT_FORMAT are used to indicate * text formatting for text transfers (both ASCII and EBCDIC). ***/ public static final int NON_PRINT_TEXT_FORMAT = 4; /*** * A constant used to indicate a text file contains format vertical format * control characters. * All constants ending in TEXT_FORMAT are used to indicate * text formatting for text transfers (both ASCII and EBCDIC). ***/ public static final int TELNET_TEXT_FORMAT = 5; /*** * A constant used to indicate a text file contains ASA vertical format * control characters. * All constants ending in TEXT_FORMAT are used to indicate * text formatting for text transfers (both ASCII and EBCDIC). ***/ public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6; /*** * A constant used to indicate a file is to be treated as a continuous * sequence of bytes. This is the default structure. All constants ending * in _STRUCTURE are used to indicate file structure for * file transfers. ***/ public static final int FILE_STRUCTURE = 7; /*** * A constant used to indicate a file is to be treated as a sequence * of records. All constants ending in _STRUCTURE * are used to indicate file structure for file transfers. ***/ public static final int RECORD_STRUCTURE = 8; /*** * A constant used to indicate a file is to be treated as a set of * independent indexed pages. All constants ending in * _STRUCTURE are used to indicate file structure for file * transfers. ***/ public static final int PAGE_STRUCTURE = 9; /*** * A constant used to indicate a file is to be transfered as a stream * of bytes. This is the default transfer mode. All constants ending * in TRANSFER_MODE are used to indicate file transfer * modes. ***/ public static final int STREAM_TRANSFER_MODE = 10; /*** * A constant used to indicate a file is to be transfered as a series * of blocks. All constants ending in TRANSFER_MODE are used * to indicate file transfer modes. ***/ public static final int BLOCK_TRANSFER_MODE = 11; /*** * A constant used to indicate a file is to be transfered as FTP * compressed data. All constants ending in TRANSFER_MODE * are used to indicate file transfer modes. ***/ public static final int COMPRESSED_TRANSFER_MODE = 12; // We have to ensure that the protocol communication is in ASCII // but we use ISO-8859-1 just in case 8-bit characters cross // the wire. /** * The default character encoding used for communicating over an * FTP control connection. The default encoding is an * ASCII-compatible encoding. Some FTP servers expect other * encodings. You can change the encoding used by an FTP instance * with {@link #setControlEncoding setControlEncoding}. */ public static final String DEFAULT_CONTROL_ENCODING = "ISO-8859-1"; private static final String __modes = "AEILNTCFRPSBC"; private final StringBuilder __commandBuffer = new StringBuilder(); protected int _replyCode; protected ArrayList _replyLines; protected boolean _newReplyString; protected String _replyString; protected String _controlEncoding; /** * This is used to signal whether a block of multiline responses beginning * with xxx must be terminated by the same numeric code xxx * See section 4.2 of RFC 959 for details. */ protected boolean strictMultilineParsing = false; /** * Wraps SocketClient._input_ to facilitate the writing of text * to the FTP control connection. Do not access the control * connection via SocketClient._input_. This member starts * with a null value, is initialized in {@link #_connectAction_}, * and set to null in {@link #disconnect}. */ protected BufferedReader _controlInput_; /** * Wraps SocketClient._output_ to facilitate the reading of text * from the FTP control connection. Do not access the control * connection via SocketClient._output_. This member starts * with a null value, is initialized in {@link #_connectAction_}, * and set to null in {@link #disconnect}. */ protected BufferedWriter _controlOutput_; /*** * A ProtocolCommandSupport object used to manage the registering of * ProtocolCommandListeners and te firing of ProtocolCommandEvents. ***/ protected ProtocolCommandSupport _commandSupport_; /*** * The default FTP constructor. Sets the default port to * DEFAULT_PORT and initializes internal data structures * for saving FTP reply information. ***/ public FTP() { super(); setDefaultPort(DEFAULT_PORT); _replyLines = new ArrayList(); _newReplyString = false; _replyString = null; _commandSupport_ = new ProtocolCommandSupport(this); _controlEncoding = DEFAULT_CONTROL_ENCODING; } // The RFC-compliant multiline termination check private boolean __strictCheck(String line, String code) { return (!(line.startsWith(code) && line.charAt(3) == ' ')); } // The strict check is too strong a condition because of non-conforming ftp // servers like ftp.funet.fi which sent 226 as the last line of a // 426 multi-line reply in response to ls /. We relax the condition to // test that the line starts with a digit rather than starting with // the code. private boolean __lenientCheck(String line) { return (!(line.length() >= 4 && line.charAt(3) != '-' && Character.isDigit(line.charAt(0)))); } private void __getReply() throws IOException { int length; _newReplyString = true; _replyLines.clear(); String line = _controlInput_.readLine(); if (line == null) throw new FTPConnectionClosedException( "Connection closed without indication."); // In case we run into an anomaly we don't want fatal index exceptions // to be thrown. length = line.length(); if (length < 3) throw new MalformedServerReplyException( "Truncated server reply: " + line); String code = null; try { code = line.substring(0, 3); _replyCode = Integer.parseInt(code); } catch (NumberFormatException e) { throw new MalformedServerReplyException( "Could not parse response code.\nServer Reply: " + line); } _replyLines.add(line); // Get extra lines if message continues. if (length > 3 && line.charAt(3) == '-') { do { line = _controlInput_.readLine(); if (line == null) throw new FTPConnectionClosedException( "Connection closed without indication."); _replyLines.add(line); // The length() check handles problems that could arise from readLine() // returning too soon after encountering a naked CR or some other // anomaly. } while ( isStrictMultilineParsing() ? __strictCheck(line, code) : __lenientCheck(line)); } if (_commandSupport_.getListenerCount() > 0) { _commandSupport_.fireReplyReceived(_replyCode, getReplyString()); } if (_replyCode == FTPReply.SERVICE_NOT_AVAILABLE) { throw new FTPConnectionClosedException("FTP response 421 received. Server closed connection."); } } /** * Initiates control connections and gets initial reply. * Initializes {@link #_controlInput_} and {@link #_controlOutput_}. */ @Override protected void _connectAction_() throws IOException { super._connectAction_(); _controlInput_ = new BufferedReader(new InputStreamReader(_socket_.getInputStream(), getControlEncoding())); _controlOutput_ = new BufferedWriter(new OutputStreamWriter(_socket_.getOutputStream(), getControlEncoding())); __getReply(); // If we received code 120, we have to fetch completion reply. if (FTPReply.isPositivePreliminary(_replyCode)) __getReply(); } /** * Sets the character encoding used by the FTP control connection. * Some FTP servers require that commands be issued in a non-ASCII * encoding like UTF-8 so that filenames with multi-byte character * representations (e.g, Big 8) can be specified. * * @param encoding The new character encoding for the control connection. */ public void setControlEncoding(String encoding) { _controlEncoding = encoding; } /** * @return The character encoding used to communicate over the * control connection. */ public String getControlEncoding() { return _controlEncoding; } /*** * Adds a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to add. ***/ public void addProtocolCommandListener(ProtocolCommandListener listener) { _commandSupport_.addProtocolCommandListener(listener); } /*** * Removes a ProtocolCommandListener. Delegates this task to * {@link #_commandSupport_ _commandSupport_ }. *

* @param listener The ProtocolCommandListener to remove. ***/ public void removeProtocolCommandListener(ProtocolCommandListener listener) { _commandSupport_.removeProtocolCommandListener(listener); } /*** * Closes the control connection to the FTP server and sets to null * some internal data so that the memory may be reclaimed by the * garbage collector. The reply text and code information from the * last command is voided so that the memory it used may be reclaimed. * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null. *

* @exception IOException If an error occurs while disconnecting. ***/ @Override public void disconnect() throws IOException { super.disconnect(); _controlInput_ = null; _controlOutput_ = null; _newReplyString = false; _replyString = null; } /*** * Sends an FTP command to the server, waits for a reply and returns the * numerical response code. After invocation, for more detailed * information, the actual reply text can be accessed by calling * {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The text representation of the FTP command to send. * @param args The arguments to the FTP command. If this parameter is * set to null, then the command is sent with no argument. * @return The integer value of the FTP reply code returned by the server * in response to the command. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(String command, String args) throws IOException { String message; __commandBuffer.setLength(0); __commandBuffer.append(command); if (args != null) { __commandBuffer.append(' '); __commandBuffer.append(args); } __commandBuffer.append(SocketClient.NETASCII_EOL); if (_controlOutput_ == null){ throw new IOException("Connection is not open"); } try{ _controlOutput_.write(message = __commandBuffer.toString()); _controlOutput_.flush(); } catch (SocketException e) { if (!isConnected() || !socketIsConnected(_socket_)) { throw new FTPConnectionClosedException("Connection unexpectedly closed."); } else { throw e; } } if (_commandSupport_.getListenerCount() > 0) _commandSupport_.fireCommandSent(command, message); __getReply(); return _replyCode; } /** * Checks if the socket is connected * * @param socket * @return true if connected */ private boolean socketIsConnected(Socket socket) { if (socket == null) { return false; } return socket.isConnected(); } /*** * Sends an FTP command to the server, waits for a reply and returns the * numerical response code. After invocation, for more detailed * information, the actual reply text can be accessed by calling * {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The FTPCommand constant corresponding to the FTP command * to send. * @param args The arguments to the FTP command. If this parameter is * set to null, then the command is sent with no argument. * @return The integer value of the FTP reply code returned by the server * in response to the command. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(int command, String args) throws IOException { return sendCommand(FTPCommand.getCommand(command), args); } /*** * Sends an FTP command with no arguments to the server, waits for a * reply and returns the numerical response code. After invocation, for * more detailed information, the actual reply text can be accessed by * calling {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The text representation of the FTP command to send. * @return The integer value of the FTP reply code returned by the server * in response to the command. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(String command) throws IOException { return sendCommand(command, null); } /*** * Sends an FTP command with no arguments to the server, waits for a * reply and returns the numerical response code. After invocation, for * more detailed information, the actual reply text can be accessed by * calling {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. *

* @param command The FTPCommand constant corresponding to the FTP command * to send. * @return The integer value of the FTP reply code returned by the server * in response to the command. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int sendCommand(int command) throws IOException { return sendCommand(command, null); } /*** * Returns the integer value of the reply code of the last FTP reply. * You will usually only use this method after you connect to the * FTP server to check that the connection was successful since * connect is of type void. *

* @return The integer value of the reply code of the last FTP reply. ***/ public int getReplyCode() { return _replyCode; } /*** * Fetches a reply from the FTP server and returns the integer reply * code. After calling this method, the actual reply text can be accessed * from either calling {@link #getReplyString getReplyString } or * {@link #getReplyStrings getReplyStrings }. Only use this * method if you are implementing your own FTP client or if you need to * fetch a secondary response from the FTP server. *

* @return The integer value of the reply code of the fetched FTP reply. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while receiving the * server reply. ***/ public int getReply() throws IOException { __getReply(); return _replyCode; } /*** * Returns the lines of text from the last FTP server response as an array * of strings, one entry per line. The end of line markers of each are * stripped from each line. *

* @return The lines of text from the last FTP response as an array. ***/ public String[] getReplyStrings() { return _replyLines.toArray(new String[_replyLines.size()]); } /*** * Returns the entire text of the last FTP server response exactly * as it was received, including all end of line markers in NETASCII * format. *

* @return The entire text from the last FTP response as a String. ***/ public String getReplyString() { StringBuilder buffer; if (!_newReplyString) { return _replyString; } buffer = new StringBuilder(256); for (String line : _replyLines) { buffer.append(line); buffer.append(SocketClient.NETASCII_EOL); } _newReplyString = false; return (_replyString = buffer.toString()); } /*** * A convenience method to send the FTP USER command to the server, * receive the reply, and return the reply code. *

* @param username The username to login under. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int user(String username) throws IOException { return sendCommand(FTPCommand.USER, username); } /** * A convenience method to send the FTP PASS command to the server, * receive the reply, and return the reply code. * @param password The plain text password of the username being logged into. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. */ public int pass(String password) throws IOException { return sendCommand(FTPCommand.PASS, password); } /*** * A convenience method to send the FTP ACCT command to the server, * receive the reply, and return the reply code. *

* @param account The account name to access. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int acct(String account) throws IOException { return sendCommand(FTPCommand.ACCT, account); } /*** * A convenience method to send the FTP ABOR command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int abor() throws IOException { return sendCommand(FTPCommand.ABOR); } /*** * A convenience method to send the FTP CWD command to the server, * receive the reply, and return the reply code. *

* @param directory The new working directory. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int cwd(String directory) throws IOException { return sendCommand(FTPCommand.CWD, directory); } /*** * A convenience method to send the FTP CDUP command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int cdup() throws IOException { return sendCommand(FTPCommand.CDUP); } /*** * A convenience method to send the FTP QUIT command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int quit() throws IOException { return sendCommand(FTPCommand.QUIT); } /*** * A convenience method to send the FTP REIN command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rein() throws IOException { return sendCommand(FTPCommand.REIN); } /*** * A convenience method to send the FTP SMNT command to the server, * receive the reply, and return the reply code. *

* @param dir The directory name. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int smnt(String dir) throws IOException { return sendCommand(FTPCommand.SMNT, dir); } /*** * A convenience method to send the FTP PORT command to the server, * receive the reply, and return the reply code. *

* @param host The host owning the port. * @param port The new port. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int port(InetAddress host, int port) throws IOException { int num; StringBuilder info = new StringBuilder(24); info.append(host.getHostAddress().replace('.', ',')); num = port >>> 8; info.append(','); info.append(num); info.append(','); num = port & 0xff; info.append(num); return sendCommand(FTPCommand.PORT, info.toString()); } /*** * A convenience method to send the FTP EPRT command to the server, * receive the reply, and return the reply code. * * Examples: * *

    *
  • EPRT |1|132.235.1.2|6275|
  • *
  • EPRT |2|1080::8:800:200C:417A|5282|
  • *
* *

* @see "http://www.faqs.org/rfcs/rfc2428.html" * * @param host The host owning the port. * @param port The new port. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. * @since 2.2 ***/ public int eprt(InetAddress host, int port) throws IOException { int num; StringBuilder info = new StringBuilder(); String h; // If IPv6, trim the zone index h = host.getHostAddress(); num = h.indexOf("%"); if (num > 0) h = h.substring(0, num); info.append("|"); if (host instanceof Inet4Address) info.append("1"); else if (host instanceof Inet6Address) info.append("2"); info.append("|"); info.append(h); info.append("|"); info.append(port); info.append("|"); return sendCommand(FTPCommand.EPRT, info.toString()); } /*** * A convenience method to send the FTP PASV command to the server, * receive the reply, and return the reply code. Remember, it's up * to you to interpret the reply string containing the host/port * information. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int pasv() throws IOException { return sendCommand(FTPCommand.PASV); } /*** * A convenience method to send the FTP EPSV command to the server, * receive the reply, and return the reply code. Remember, it's up * to you to interpret the reply string containing the host/port * information. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. * @since 2.2 ***/ public int epsv() throws IOException { return sendCommand(FTPCommand.EPSV); } /** * A convenience method to send the FTP TYPE command for text files * to the server, receive the reply, and return the reply code. * @param fileType The type of the file (one of the FILE_TYPE * constants). * @param formatOrByteSize The format of the file (one of the * _FORMAT constants. In the case of * LOCAL_FILE_TYPE, the byte size. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. */ public int type(int fileType, int formatOrByteSize) throws IOException { StringBuilder arg = new StringBuilder(); arg.append(__modes.charAt(fileType)); arg.append(' '); if (fileType == LOCAL_FILE_TYPE) arg.append(formatOrByteSize); else arg.append(__modes.charAt(formatOrByteSize)); return sendCommand(FTPCommand.TYPE, arg.toString()); } /** * A convenience method to send the FTP TYPE command to the server, * receive the reply, and return the reply code. *

* @param fileType The type of the file (one of the FILE_TYPE * constants). * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. */ public int type(int fileType) throws IOException { return sendCommand(FTPCommand.TYPE, __modes.substring(fileType, fileType + 1)); } /*** * A convenience method to send the FTP STRU command to the server, * receive the reply, and return the reply code. *

* @param structure The structure of the file (one of the * _STRUCTURE constants). * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stru(int structure) throws IOException { return sendCommand(FTPCommand.STRU, __modes.substring(structure, structure + 1)); } /*** * A convenience method to send the FTP MODE command to the server, * receive the reply, and return the reply code. *

* @param mode The transfer mode to use (one of the * TRANSFER_MODE constants). * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int mode(int mode) throws IOException { return sendCommand(FTPCommand.MODE, __modes.substring(mode, mode + 1)); } /*** * A convenience method to send the FTP RETR command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @param pathname The pathname of the file to retrieve. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int retr(String pathname) throws IOException { return sendCommand(FTPCommand.RETR, pathname); } /*** * A convenience method to send the FTP STOR command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @param pathname The pathname to use for the file when stored at * the remote end of the transfer. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stor(String pathname) throws IOException { return sendCommand(FTPCommand.STOR, pathname); } /*** * A convenience method to send the FTP STOU command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stou() throws IOException { return sendCommand(FTPCommand.STOU); } /*** * A convenience method to send the FTP STOU command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. * @param pathname The base pathname to use for the file when stored at * the remote end of the transfer. Some FTP servers * require this. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. */ public int stou(String pathname) throws IOException { return sendCommand(FTPCommand.STOU, pathname); } /*** * A convenience method to send the FTP APPE command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @param pathname The pathname to use for the file when stored at * the remote end of the transfer. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int appe(String pathname) throws IOException { return sendCommand(FTPCommand.APPE, pathname); } /*** * A convenience method to send the FTP ALLO command to the server, * receive the reply, and return the reply code. *

* @param bytes The number of bytes to allocate. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int allo(int bytes) throws IOException { return sendCommand(FTPCommand.ALLO, Integer.toString(bytes)); } /** * A convenience method to send the FTP FEAT command to the server, receive the reply, * and return the reply code. * @return The reply code received by the server * @throws IOException If an I/O error occurs while either sending the * command or receiving the server reply. * @since 2.2 */ public int feat() throws IOException { return sendCommand(FTPCommand.FEAT); } /*** * A convenience method to send the FTP ALLO command to the server, * receive the reply, and return the reply code. *

* @param bytes The number of bytes to allocate. * @param recordSize The size of a record. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int allo(int bytes, int recordSize) throws IOException { return sendCommand(FTPCommand.ALLO, Integer.toString(bytes) + " R " + Integer.toString(recordSize)); } /*** * A convenience method to send the FTP REST command to the server, * receive the reply, and return the reply code. *

* @param marker The marker at which to restart a transfer. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rest(String marker) throws IOException { return sendCommand(FTPCommand.REST, marker); } /** * @since 2.0 **/ public int mdtm(String file) throws IOException { return sendCommand(FTPCommand.MDTM, file); } /** * A convenience method to send the FTP MFMT command to the server, * receive the reply, and return the reply code. *

* @param pathname The pathname for which mtime is to be changed * @param timeval Timestamp in YYYYMMDDhhmmss format * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. * @since 2.2 * @see http://tools.ietf.org/html/draft-somers-ftp-mfxx-04 **/ public int mfmt(String pathname, String timeval) throws IOException { return sendCommand(FTPCommand.MFMT, timeval + " " + pathname); } /*** * A convenience method to send the FTP RNFR command to the server, * receive the reply, and return the reply code. *

* @param pathname The pathname to rename from. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rnfr(String pathname) throws IOException { return sendCommand(FTPCommand.RNFR, pathname); } /*** * A convenience method to send the FTP RNTO command to the server, * receive the reply, and return the reply code. *

* @param pathname The pathname to rename to * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rnto(String pathname) throws IOException { return sendCommand(FTPCommand.RNTO, pathname); } /*** * A convenience method to send the FTP DELE command to the server, * receive the reply, and return the reply code. *

* @param pathname The pathname to delete. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int dele(String pathname) throws IOException { return sendCommand(FTPCommand.DELE, pathname); } /*** * A convenience method to send the FTP RMD command to the server, * receive the reply, and return the reply code. *

* @param pathname The pathname of the directory to remove. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int rmd(String pathname) throws IOException { return sendCommand(FTPCommand.RMD, pathname); } /*** * A convenience method to send the FTP MKD command to the server, * receive the reply, and return the reply code. *

* @param pathname The pathname of the new directory to create. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int mkd(String pathname) throws IOException { return sendCommand(FTPCommand.MKD, pathname); } /*** * A convenience method to send the FTP PWD command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int pwd() throws IOException { return sendCommand(FTPCommand.PWD); } /*** * A convenience method to send the FTP LIST command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int list() throws IOException { return sendCommand(FTPCommand.LIST); } /*** * A convenience method to send the FTP LIST command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @param pathname The pathname to list. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int list(String pathname) throws IOException { return sendCommand(FTPCommand.LIST, pathname); } /*** * A convenience method to send the FTP NLST command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int nlst() throws IOException { return sendCommand(FTPCommand.NLST); } /*** * A convenience method to send the FTP NLST command to the server, * receive the reply, and return the reply code. Remember, it is up * to you to manage the data connection. If you don't need this low * level of access, use {@link org.apache.commons.net.ftp.FTPClient} * , which will handle all low level details for you. *

* @param pathname The pathname to list. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int nlst(String pathname) throws IOException { return sendCommand(FTPCommand.NLST, pathname); } /*** * A convenience method to send the FTP SITE command to the server, * receive the reply, and return the reply code. *

* @param parameters The site parameters to send. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int site(String parameters) throws IOException { return sendCommand(FTPCommand.SITE, parameters); } /*** * A convenience method to send the FTP SYST command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int syst() throws IOException { return sendCommand(FTPCommand.SYST); } /*** * A convenience method to send the FTP STAT command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stat() throws IOException { return sendCommand(FTPCommand.STAT); } /*** * A convenience method to send the FTP STAT command to the server, * receive the reply, and return the reply code. *

* @param pathname A pathname to list. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int stat(String pathname) throws IOException { return sendCommand(FTPCommand.STAT, pathname); } /*** * A convenience method to send the FTP HELP command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int help() throws IOException { return sendCommand(FTPCommand.HELP); } /*** * A convenience method to send the FTP HELP command to the server, * receive the reply, and return the reply code. *

* @param command The command name on which to request help. * @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int help(String command) throws IOException { return sendCommand(FTPCommand.HELP, command); } /*** * A convenience method to send the FTP NOOP command to the server, * receive the reply, and return the reply code. *

* @return The reply code received from the server. * @exception FTPConnectionClosedException * If the FTP server prematurely closes the connection as a result * of the client being idle or some other reason causing the server * to send FTP reply code 421. This exception may be caught either * as an IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending the * command or receiving the server reply. ***/ public int noop() throws IOException { return sendCommand(FTPCommand.NOOP); } /** * Return whether strict multiline parsing is enabled, as per RFC 959, section 4.2. * @return True if strict, false if lenient * @since 2.0 */ public boolean isStrictMultilineParsing() { return strictMultilineParsing; } /** * Set strict multiline parsing. * @param strictMultilineParsing * @since 2.0 */ public void setStrictMultilineParsing(boolean strictMultilineParsing) { this.strictMultilineParsing = strictMultilineParsing; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPSClient.java0000644000175000017500000004751011446141442026036 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; /** * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to * see wire-level SSL details. * * @version $Id: FTPSClient.java 999437 2010-09-21 14:37:22Z sebb $ * @since 2.0 */ public class FTPSClient extends FTPClient { /** @deprecated - not used - will be removed in next major release */ @Deprecated public static String KEYSTORE_ALGORITHM; /** @deprecated - not used - will be removed in next major release */ @Deprecated public static String TRUSTSTORE_ALGORITHM; /** @deprecated - not used - will be removed in next major release */ @Deprecated public static String PROVIDER; /** @deprecated - not used - will be removed in next major release */ @Deprecated public static String STORE_TYPE; /** The value that I can set in PROT command (C = Clear, P = Protected) */ private static final String[] PROT_COMMAND_VALUE = {"C","E","S","P"}; /** Default PROT Command */ private static final String DEFAULT_PROT = "C"; /** Default secure socket protocol name, i.e. TLS */ private static final String DEFAULT_PROTOCOL = "TLS"; /** The security mode. (True - Implicit Mode / False - Explicit Mode) */ private final boolean isImplicit; /** The secure socket protocol to be used, e.g. SSL/TLS. */ private final String protocol; /** The AUTH Command value */ private String auth = DEFAULT_PROTOCOL; /** The context object. */ private SSLContext context; /** The socket object. */ private Socket plainSocket; /** The established socket flag. */ private boolean isCreation = true; /** The use client mode flag. */ private boolean isClientMode = true; /** The need client auth flag. */ private boolean isNeedClientAuth = false; /** The want client auth flag. */ private boolean isWantClientAuth = false; /** The cipher suites */ private String[] suites = null; /** The protocol versions */ private String[] protocols = null; /** The FTPS {@link TrustManager} implementation. */ private TrustManager trustManager = new FTPSTrustManager(); /** The {@link KeyManager} */ private KeyManager keyManager; /** * Constructor for FTPSClient. * Sets security mode to explicit (isImplicit = false) * @throws NoSuchAlgorithmException A requested cryptographic algorithm * is not available in the environment. */ public FTPSClient() throws NoSuchAlgorithmException { this.protocol = DEFAULT_PROTOCOL; this.isImplicit = false; } /** * Constructor for FTPSClient. * @param isImplicit The security mode (Implicit/Explicit). * @throws NoSuchAlgorithmException A requested cryptographic algorithm * is not available in the environment. */ public FTPSClient(boolean isImplicit) throws NoSuchAlgorithmException { this.protocol = DEFAULT_PROTOCOL; this.isImplicit = isImplicit; } /** * Constructor for FTPSClient. * @param protocol the protocol * @throws NoSuchAlgorithmException A requested cryptographic algorithm * is not available in the environment. */ public FTPSClient(String protocol) throws NoSuchAlgorithmException { this.protocol = protocol; this.isImplicit = false; } /** * Constructor for FTPSClient. * @param protocol the protocol * @param isImplicit The security mode(Implicit/Explicit). * @throws NoSuchAlgorithmException A requested cryptographic algorithm * is not available in the environment. */ public FTPSClient(String protocol, boolean isImplicit) throws NoSuchAlgorithmException { this.protocol = protocol; this.isImplicit = isImplicit; } /** * Constructor for FTPSClient. * @param isImplicit The security mode(Implicit/Explicit). * @param context A pre-configured SSL Context */ public FTPSClient(boolean isImplicit, SSLContext context) { this.isImplicit = isImplicit; this.context = context; this.protocol = DEFAULT_PROTOCOL; } /** * Constructor for FTPSClient. * @param context A pre-configured SSL Context */ public FTPSClient(SSLContext context) { this(false, context); } /** * Set AUTH command use value. * This processing is done before connected processing. * @param auth AUTH command use value. */ public void setAuthValue(String auth) { this.auth = auth; } /** * Return AUTH command use value. * @return AUTH command use value. */ public String getAuthValue() { return this.auth; } /** * Because there are so many connect() methods, * the _connectAction_() method is provided as a means of performing * some action immediately after establishing a connection, * rather than reimplementing all of the connect() methods. * @throws IOException If it throw by _connectAction_. * @see org.apache.commons.net.SocketClient#_connectAction_() */ @Override protected void _connectAction_() throws IOException { // Implicit mode. if (isImplicit) sslNegotiation(); super._connectAction_(); // Explicit mode. if (!isImplicit) { execAUTH(); sslNegotiation(); } } /** * AUTH command. * @throws SSLException If it server reply code not equal "234" and "334". * @throws IOException If an I/O error occurs while either sending * the command. */ private void execAUTH() throws SSLException, IOException { int replyCode = sendCommand( FTPSCommand._commands[FTPSCommand.AUTH], auth); if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) { // replyCode = 334 // I carry out an ADAT command. } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) { throw new SSLException(getReplyString()); } } /** * Performs a lazy init of the SSL context * @throws IOException */ private void initSslContext() throws IOException { if(context == null) { try { context = SSLContext.getInstance(protocol); context.init(new KeyManager[] { getKeyManager() } , new TrustManager[] { getTrustManager() } , null); } catch (KeyManagementException e) { IOException ioe = new IOException("Could not initialize SSL context"); ioe.initCause(e); throw ioe; } catch (NoSuchAlgorithmException e) { IOException ioe = new IOException("Could not initialize SSL context"); ioe.initCause(e); throw ioe; } } } /** * SSL/TLS negotiation. Acquires an SSL socket of a control * connection and carries out handshake processing. * @throws IOException If server negotiation fails */ private void sslNegotiation() throws IOException { plainSocket = _socket_; initSslContext(); SSLSocketFactory ssf = context.getSocketFactory(); String ip = _socket_.getInetAddress().getHostAddress(); int port = _socket_.getPort(); SSLSocket socket = (SSLSocket) ssf.createSocket(_socket_, ip, port, true); socket.setEnableSessionCreation(isCreation); socket.setUseClientMode(isClientMode); // server mode if (!isClientMode) { socket.setNeedClientAuth(isNeedClientAuth); socket.setWantClientAuth(isWantClientAuth); } if (protocols != null) socket.setEnabledProtocols(protocols); if (suites != null) socket.setEnabledCipherSuites(suites); socket.startHandshake(); _socket_ = socket; _controlInput_ = new BufferedReader(new InputStreamReader( socket .getInputStream(), getControlEncoding())); _controlOutput_ = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(), getControlEncoding())); } /** * Get the {@link KeyManager} instance. * @return The {@link KeyManager} instance */ private KeyManager getKeyManager() { return keyManager; } /** * Set a {@link KeyManager} to use * * @param keyManager The KeyManager implementation to set. */ public void setKeyManager(KeyManager keyManager) { this.keyManager = keyManager; } /** * Controls whether new a SSL session may be established by this socket. * @param isCreation The established socket flag. */ public void setEnabledSessionCreation(boolean isCreation) { this.isCreation = isCreation; } /** * Returns true if new SSL sessions may be established by this socket. * When the underlying {@link Socket} instance is not SSL-enabled (i.e. an * instance of {@link SSLSocket} with {@link SSLSocket}{@link #getEnableSessionCreation()}) enabled, * this returns False. * @return true - Indicates that sessions may be created; * this is the default. * false - indicates that an existing session must be resumed. */ public boolean getEnableSessionCreation() { if (_socket_ instanceof SSLSocket) return ((SSLSocket)_socket_).getEnableSessionCreation(); return false; } /** * Configures the socket to require client authentication. * @param isNeedClientAuth The need client auth flag. */ public void setNeedClientAuth(boolean isNeedClientAuth) { this.isNeedClientAuth = isNeedClientAuth; } /** * Returns true if the socket will require client authentication. * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false. * @return true - If the server mode socket should request * that the client authenticate itself. */ public boolean getNeedClientAuth() { if (_socket_ instanceof SSLSocket) return ((SSLSocket)_socket_).getNeedClientAuth(); return false; } /** * Configures the socket to request client authentication, * but only if such a request is appropriate to the cipher * suite negotiated. * @param isWantClientAuth The want client auth flag. */ public void setWantClientAuth(boolean isWantClientAuth) { this.isWantClientAuth = isWantClientAuth; } /** * Returns true if the socket will request client authentication. * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false. * @return true - If the server mode socket should request * that the client authenticate itself. */ public boolean getWantClientAuth() { if (_socket_ instanceof SSLSocket) return ((SSLSocket)_socket_).getWantClientAuth(); return false; } /** * Configures the socket to use client (or server) mode in its first * handshake. * @param isClientMode The use client mode flag. */ public void setUseClientMode(boolean isClientMode) { this.isClientMode = isClientMode; } /** * Returns true if the socket is set to use client mode * in its first handshake. * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false. * @return true - If the socket should start its first handshake * in "client" mode. */ public boolean getUseClientMode() { if (_socket_ instanceof SSLSocket) return ((SSLSocket)_socket_).getUseClientMode(); return false; } /** * Controls which particular cipher suites are enabled for use on this * connection. Called before server negotiation. * @param cipherSuites The cipher suites. */ public void setEnabledCipherSuites(String[] cipherSuites) { suites = new String[cipherSuites.length]; System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length); } /** * Returns the names of the cipher suites which could be enabled * for use on this connection. * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null. * @return An array of cipher suite names, or null */ public String[] getEnabledCipherSuites() { if (_socket_ instanceof SSLSocket) return ((SSLSocket)_socket_).getEnabledCipherSuites(); return null; } /** * Controls which particular protocol versions are enabled for use on this * connection. I perform setting before a server negotiation. * @param protocolVersions The protocol versions. */ public void setEnabledProtocols(String[] protocolVersions) { protocols = new String[protocolVersions.length]; System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length); } /** * Returns the names of the protocol versions which are currently * enabled for use on this connection. * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null. * @return An array of protocols, or null */ public String[] getEnabledProtocols() { if (_socket_ instanceof SSLSocket) return ((SSLSocket)_socket_).getEnabledProtocols(); return null; } /** * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer. * @param pbsz Protection Buffer Size. * @throws SSLException If the server reply code does not equal "200". * @throws IOException If an I/O error occurs while sending * the command. */ public void execPBSZ(long pbsz) throws SSLException, IOException { if (pbsz < 0 || 4294967295L < pbsz) throw new IllegalArgumentException(); if (FTPReply.COMMAND_OK != sendCommand( FTPSCommand._commands[FTPSCommand.PBSZ],String.valueOf(pbsz))) throw new SSLException(getReplyString()); } /** * PROT command.
* C - Clear
* S - Safe(SSL protocol only)
* E - Confidential(SSL protocol only)
* P - Private * @param prot Data Channel Protection Level. * @throws SSLException If the server reply code does not equal "200". * @throws IOException If an I/O error occurs while sending * the command. */ public void execPROT(String prot) throws SSLException, IOException { if (prot == null) prot = DEFAULT_PROT; if (!checkPROTValue(prot)) throw new IllegalArgumentException(); if (FTPReply.COMMAND_OK != sendCommand( FTPSCommand._commands[FTPSCommand.PROT], prot)) throw new SSLException(getReplyString()); if (DEFAULT_PROT.equals(prot)) { setSocketFactory(null); setServerSocketFactory(null); } else { setSocketFactory(new FTPSSocketFactory(context)); setServerSocketFactory(new FTPSServerSocketFactory(context)); initSslContext(); } } /** * Check the value that can be set in PROT Command value. * @param prot Data Channel Protection Level. * @return True - A set point is right / False - A set point is not right */ private boolean checkPROTValue(String prot) { for (int p = 0; p < PROT_COMMAND_VALUE.length; p++) { if (PROT_COMMAND_VALUE[p].equals(prot)) return true; } return false; } /** * Send an FTP command. * The CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned * to a plain {@link Socket} instances * @param command The FTP command. * @return server reply. * @throws IOException If an I/O error occurs while sending * the command. * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String) */ @Override public int sendCommand(String command, String args) throws IOException { int repCode = super.sendCommand(command, args); /* If CCC is issued, restore socket i/o streams to unsecured versions */ if (FTPSCommand._commands[FTPSCommand.CCC].equals(command)) { if (FTPReply.COMMAND_OK == repCode) { _socket_ = plainSocket; _controlInput_ = new BufferedReader( new InputStreamReader( _socket_ .getInputStream(), getControlEncoding())); _controlOutput_ = new BufferedWriter( new OutputStreamWriter( _socket_.getOutputStream(), getControlEncoding())); setSocketFactory(null); } else { throw new SSLException(getReplyString()); } } return repCode; } /** * Returns a socket of the data connection. * Wrapped as an {@link SSLSocket}, which carries out handshake processing. * @param command The textual representation of the FTP command to send. * @param arg The arguments to the FTP command. * If this parameter is set to null, then the command is sent with * no arguments. * @return corresponding to the established data connection. * Null is returned if an FTP protocol error is reported at any point * during the establishment and initialization of the connection. * @throws IOException If there is any problem with the connection. * @see FTPClient#_openDataConnection_(int, String) */ @Override protected Socket _openDataConnection_(int command, String arg) throws IOException { Socket socket = super._openDataConnection_(command, arg); if (socket != null && socket instanceof SSLSocket) { SSLSocket sslSocket = (SSLSocket)socket; sslSocket.setUseClientMode(isClientMode); sslSocket.setEnableSessionCreation(isCreation); // server mode if (!isClientMode) { sslSocket.setNeedClientAuth(isNeedClientAuth); sslSocket.setWantClientAuth(isWantClientAuth); } if (suites != null) sslSocket.setEnabledCipherSuites(suites); if (protocols != null) sslSocket.setEnabledProtocols(protocols); sslSocket.startHandshake(); } return socket; } /** * Get the currently configured {@link TrustManager}. * * @return A TrustManager instance. */ public TrustManager getTrustManager() { return trustManager; } /** * Override the default {@link TrustManager} to use. * * @param trustManager The TrustManager implementation to set. */ public void setTrustManager(TrustManager trustManager) { this.trustManager = trustManager; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPSCommand.java0000644000175000017500000000347511143265407026202 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; /** * FTPS-specific command * @since 2.0 */ public final class FTPSCommand { public static final int AUTH = 0; public static final int ADAT = 1; public static final int PBSZ = 2; public static final int PROT = 3; public static final int CCC = 4; public static final int AUTHENTICATION_SECURITY_MECHANISM = AUTH; public static final int AUTHENTICATION_SECURITY_DATA = ADAT; public static final int PROTECTION_BUFFER_SIZE = PBSZ; public static final int DATA_CHANNEL_PROTECTION_LEVEL = PROT; public static final int CLEAR_COMMAND_CHANNEL = CCC; static final String[] _commands = {"AUTH","ADAT","PBSZ","PROT","CCC"}; /** * Retrieve the FTPS command string corresponding to a specified * command code. *

* @param command The command code. * @return The FTPS command string corresponding to a specified * command code. */ public static final String getCommand(int command) { return _commands[command]; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPHTTPClient.java0000644000175000017500000001156711466231525026422 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.net.SocketException; import java.util.ArrayList; import java.util.List; import org.apache.commons.net.util.Base64; /** * Experimental attempt at FTP client that tunnels over an HTTP proxy connection. * * @author rory * @since 2.2 */ public class FTPHTTPClient extends FTPClient { private final String proxyHost; private final int proxyPort; private final String proxyUsername; private final String proxyPassword; private String host; private int port; private final byte[] CRLF; private final Base64 base64 = new Base64(); public FTPHTTPClient(String proxyHost, int proxyPort, String proxyUser, String proxyPass) { this.proxyHost = proxyHost; this.proxyPort = proxyPort; this.proxyUsername = proxyUser; this.proxyPassword = proxyPass; try { CRLF = "\r\n".getBytes(getControlEncoding()); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public FTPHTTPClient(String proxyHost, int proxyPort) { this(proxyHost, proxyPort, null, null); } @Override protected Socket _openDataConnection_(int command, String arg) throws IOException { Socket socket = new Socket(host, port); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); tunnelHandshake(host, port, is, os); return socket; } @Override public void connect(String host, int port) throws SocketException, IOException { this.host = host; this.port = port; _socket_ = new Socket(proxyHost, proxyPort); _input_ = _socket_.getInputStream(); _output_ = _socket_.getOutputStream(); try { tunnelHandshake(host, port, _input_, _output_); } catch (Exception e) { IOException ioe = new IOException("Could not connect to " + host); ioe.initCause(e); throw ioe; } } private void tunnelHandshake(String host, int port, InputStream input, OutputStream output) throws IOException, UnsupportedEncodingException { final String connectString = "CONNECT " + host + ":" + port + " HTTP/1.1"; _output_.write(connectString.getBytes(getControlEncoding())); _output_.write(CRLF); if (proxyUsername != null && proxyPassword != null) { final String header = "Proxy-Authorization: Basic " + base64.encode(proxyUsername + ":" + proxyPassword) + "\r\n"; _output_.write(header.getBytes("UTF-8")); _output_.write(CRLF); List response = new ArrayList(); BufferedReader reader = new BufferedReader( new InputStreamReader(_input_)); for (String line = reader.readLine(); line != null && line.length() > 0; line = reader.readLine()) { response.add(line); } int size = response.size(); if (size == 0) { throw new IOException("No response from proxy"); } String code = null; String resp = response.get(0); if (resp.startsWith("HTTP/") && resp.length() >= 12) { code = resp.substring(9, 12); } else { throw new IOException("Invalid response from proxy: " + resp); } if (!"200".equals(code)) { StringBuilder msg = new StringBuilder(); msg.append("HTTPTunnelConnector: connection failed\r\n"); msg.append("Response received from the proxy:\r\n"); for (String line : response) { msg.append(line); msg.append("\r\n"); } throw new IOException(msg.toString()); } } } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/0000755000175000017500000000000011617452467024561 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java0000644000175000017500000003001611014673543031727 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.apache.commons.net.ftp.Configurable; import org.apache.commons.net.ftp.FTPClientConfig; /** * Default implementation of the {@link FTPTimestampParser FTPTimestampParser} * interface also implements the {@link org.apache.commons.net.ftp.Configurable Configurable} * interface to allow the parsing to be configured from the outside. * * @see ConfigurableFTPFileEntryParserImpl * @since 1.4 */ public class FTPTimestampParserImpl implements FTPTimestampParser, Configurable { private SimpleDateFormat defaultDateFormat; private SimpleDateFormat recentDateFormat; private boolean lenientFutureDates = false; /** * The only constructor for this class. */ public FTPTimestampParserImpl() { setDefaultDateFormat(DEFAULT_SDF); setRecentDateFormat(DEFAULT_RECENT_SDF); } /** * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method} * in the {@link FTPTimestampParser FTPTimestampParser} interface * according to this algorithm: * * If the recentDateFormat member has been defined, try to parse the * supplied string with that. If that parse fails, or if the recentDateFormat * member has not been defined, attempt to parse with the defaultDateFormat * member. If that fails, throw a ParseException. * * This method allows a {@link Calendar} instance to be passed in which represents the * current (system) time. * * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String) * * @param timestampStr The timestamp to be parsed */ public Calendar parseTimestamp(String timestampStr) throws ParseException { Calendar now = Calendar.getInstance(); return parseTimestamp(timestampStr, now); } /** * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method} * in the {@link FTPTimestampParser FTPTimestampParser} interface * according to this algorithm: * * If the recentDateFormat member has been defined, try to parse the * supplied string with that. If that parse fails, or if the recentDateFormat * member has not been defined, attempt to parse with the defaultDateFormat * member. If that fails, throw a ParseException. * * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String) * @param timestampStr The timestamp to be parsed * @param serverTime The current time for the server * @since 1.5 */ public Calendar parseTimestamp(String timestampStr, Calendar serverTime) throws ParseException { Calendar now = (Calendar) serverTime.clone();// Copy this, because we may change it now.setTimeZone(this.getServerTimeZone()); Calendar working = (Calendar) now.clone(); working.setTimeZone(getServerTimeZone()); ParsePosition pp = new ParsePosition(0); Date parsed = null; if (recentDateFormat != null) { if (lenientFutureDates) { // add a day to "now" so that "slop" doesn't cause a date // slightly in the future to roll back a full year. (Bug 35181) now.add(Calendar.DATE, 1); } parsed = recentDateFormat.parse(timestampStr, pp); } if (parsed != null && pp.getIndex() == timestampStr.length()) { working.setTime(parsed); working.set(Calendar.YEAR, now.get(Calendar.YEAR)); if (working.after(now)) { working.add(Calendar.YEAR, -1); } } else { // Temporarily add the current year to the short date time // to cope with short-date leap year strings. // e.g. Java's DateFormatter will assume that "Feb 29 12:00" refers to // Feb 29 1970 (an invalid date) rather than a potentially valid leap year date. // This is pretty bad hack to work around the deficiencies of the JDK date/time classes. if (recentDateFormat != null) { pp = new ParsePosition(0); int year = now.get(Calendar.YEAR); String timeStampStrPlusYear = timestampStr + " " + year; SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy", recentDateFormat.getDateFormatSymbols()); hackFormatter.setLenient(false); hackFormatter.setTimeZone(recentDateFormat.getTimeZone()); parsed = hackFormatter.parse(timeStampStrPlusYear, pp); } if (parsed != null && pp.getIndex() == timestampStr.length() + 5) { working.setTime(parsed); } else { pp = new ParsePosition(0); parsed = defaultDateFormat.parse(timestampStr, pp); // note, length checks are mandatory for us since // SimpleDateFormat methods will succeed if less than // full string is matched. They will also accept, // despite "leniency" setting, a two-digit number as // a valid year (e.g. 22:04 will parse as 22 A.D.) // so could mistakenly confuse an hour with a year, // if we don't insist on full length parsing. if (parsed != null && pp.getIndex() == timestampStr.length()) { working.setTime(parsed); } else { throw new ParseException( "Timestamp could not be parsed with older or recent DateFormat", pp.getIndex()); } } } return working; } /** * @return Returns the defaultDateFormat. */ public SimpleDateFormat getDefaultDateFormat() { return defaultDateFormat; } /** * @return Returns the defaultDateFormat pattern string. */ public String getDefaultDateFormatString() { return defaultDateFormat.toPattern(); } /** * @param defaultDateFormat The defaultDateFormat to be set. */ private void setDefaultDateFormat(String format) { if (format != null) { this.defaultDateFormat = new SimpleDateFormat(format); this.defaultDateFormat.setLenient(false); } } /** * @return Returns the recentDateFormat. */ public SimpleDateFormat getRecentDateFormat() { return recentDateFormat; } /** * @return Returns the recentDateFormat. */ public String getRecentDateFormatString() { return recentDateFormat.toPattern(); } /** * @param recentDateFormat The recentDateFormat to set. */ private void setRecentDateFormat(String format) { if (format != null) { this.recentDateFormat = new SimpleDateFormat(format); this.recentDateFormat.setLenient(false); } } /** * @return returns an array of 12 strings representing the short * month names used by this parse. */ public String[] getShortMonths() { return defaultDateFormat.getDateFormatSymbols().getShortMonths(); } /** * @return Returns the serverTimeZone used by this parser. */ public TimeZone getServerTimeZone() { return this.defaultDateFormat.getTimeZone(); } /** * sets a TimeZone represented by the supplied ID string into all * of the parsers used by this server. * @param serverTimeZone Time Id java.util.TimeZone id used by * the ftp server. If null the client's local time zone is assumed. */ private void setServerTimeZone(String serverTimeZoneId) { TimeZone serverTimeZone = TimeZone.getDefault(); if (serverTimeZoneId != null) { serverTimeZone = TimeZone.getTimeZone(serverTimeZoneId); } this.defaultDateFormat.setTimeZone(serverTimeZone); if (this.recentDateFormat != null) { this.recentDateFormat.setTimeZone(serverTimeZone); } } /** * Implementation of the {@link Configurable Configurable} * interface. Configures this FTPTimestampParser according * to the following logic: *

* Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat} * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat} * to values supplied in the config based on month names configured as follows: *

    *
  • If a {@link FTPClientConfig#setShortMonthNames(String) shortMonthString} * has been supplied in the config, use that to parse parse timestamps.
  • *
  • Otherwise, if a {@link FTPClientConfig#setServerLanguageCode(String) serverLanguageCode} * has been supplied in the config, use the month names represented * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language} * to parse timestamps.
  • *
  • otherwise use default English month names
  • *

* Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId} * has been supplied via the config, set that into all date formats that have * been configured. *

*/ public void configure(FTPClientConfig config) { DateFormatSymbols dfs = null; String languageCode = config.getServerLanguageCode(); String shortmonths = config.getShortMonthNames(); if (shortmonths != null) { dfs = FTPClientConfig.getDateFormatSymbols(shortmonths); } else if (languageCode != null) { dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode); } else { dfs = FTPClientConfig.lookupDateFormatSymbols("en"); } String recentFormatString = config.getRecentDateFormatStr(); if (recentFormatString == null) { this.recentDateFormat = null; } else { this.recentDateFormat = new SimpleDateFormat(recentFormatString, dfs); this.recentDateFormat.setLenient(false); } String defaultFormatString = config.getDefaultDateFormatStr(); if (defaultFormatString == null) { throw new IllegalArgumentException("defaultFormatString cannot be null"); } this.defaultDateFormat = new SimpleDateFormat(defaultFormatString, dfs); this.defaultDateFormat.setLenient(false); setServerTimeZone(config.getServerTimeZoneId()); this.lenientFutureDates = config.isLenientFutureDates(); } /** * @return Returns the lenientFutureDates. */ boolean isLenientFutureDates() { return lenientFutureDates; } /** * @param lenientFutureDates The lenientFutureDates to set. */ void setLenientFutureDates(boolean lenientFutureDates) { this.lenientFutureDates = lenientFutureDates; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java0000644000175000017500000001437511446377267032724 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.commons.net.ftp.FTPClientConfig; /** * Special implementation VMSFTPEntryParser with versioning turned on. * This parser removes all duplicates and only leaves the version with the highest * version number for each filename. * * This is a sample of VMS LIST output * * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", *

* * @author Winston Ojeda * @author Stephane ESTE-GRACIAS * @version $Id: VMSVersioningFTPEntryParser.java 999923 2010-09-22 13:03:51Z sebb $ * * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser { private final Pattern _preparse_pattern_; private static final String PRE_PARSE_REGEX = "(.*);([0-9]+)\\s*.*"; /** * Constructor for a VMSFTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public VMSVersioningFTPEntryParser() { this(null); } /** * This constructor allows the creation of a VMSVersioningFTPEntryParser * object with something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public VMSVersioningFTPEntryParser(FTPClientConfig config) { super(); configure(config); try { //_preparse_matcher_ = new Perl5Matcher(); _preparse_pattern_ = Pattern.compile(PRE_PARSE_REGEX); } catch (PatternSyntaxException pse) { throw new IllegalArgumentException ( "Unparseable regex supplied: " + PRE_PARSE_REGEX); } } /** * Implement hook provided for those implementers (such as * VMSVersioningFTPEntryParser, and possibly others) which return * multiple files with the same name to remove the duplicates .. * * @param original Original list * * @return Original list purged of duplicates */ @Override public List preParse(List original) { original = super.preParse(original); HashMap existingEntries = new HashMap(); ListIterator iter = original.listIterator(); while (iter.hasNext()) { String entry = iter.next().trim(); MatchResult result = null; Matcher _preparse_matcher_ = _preparse_pattern_.matcher(entry); if (_preparse_matcher_.matches()) { result = _preparse_matcher_.toMatchResult(); String name = result.group(1); String version = result.group(2); Integer nv = Integer.valueOf(version); Integer existing = existingEntries.get(name); if (null != existing) { if (nv.intValue() < existing.intValue()) { iter.remove(); // removes older version from original list. continue; } } existingEntries.put(name, nv); } } // we've now removed all entries less than with less than the largest // version number for each name that were listed after the largest. // we now must remove those with smaller than the largest version number // for each name that were found before the largest while (iter.hasPrevious()) { String entry = iter.previous().trim(); MatchResult result = null; Matcher _preparse_matcher_ = _preparse_pattern_.matcher(entry); if (_preparse_matcher_.matches()) { result = _preparse_matcher_.toMatchResult(); String name = result.group(1); String version = result.group(2); Integer nv = Integer.valueOf(version); Integer existing = existingEntries.get(name); if (null != existing) { if (nv.intValue() < existing.intValue()) { iter.remove(); // removes older version from original list. } } } } return original; } @Override protected boolean isVersioning() { return true; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java0000644000175000017500000002443011253305656031114 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * Implementation FTPFileEntryParser and FTPFileListParser for standard * Unix Systems. * * This class is based on the logic of Daniel Savarese's * DefaultFTPListParser, but adapted to use regular expressions and to fit the * new FTPFileEntryParser interface. * @version $Id: UnixFTPEntryParser.java 814446 2009-09-14 00:17:50Z sebb $ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { static final String DEFAULT_DATE_FORMAT = "MMM d yyyy"; //Nov 9 2001 static final String DEFAULT_RECENT_DATE_FORMAT = "MMM d HH:mm"; //Nov 9 20:06 static final String NUMERIC_DATE_FORMAT = "yyyy-MM-dd HH:mm"; //2001-11-09 20:06 /** * Some Linux distributions are now shipping an FTP server which formats * file listing dates in an all-numeric format: * "yyyy-MM-dd HH:mm. * This is a very welcome development, and hopefully it will soon become * the standard. However, since it is so new, for now, and possibly * forever, we merely accomodate it, but do not make it the default. *

* For now end users may specify this format only via * UnixFTPEntryParser(FTPClientConfig). * Steve Cohen - 2005-04-17 */ public static final FTPClientConfig NUMERIC_DATE_CONFIG = new FTPClientConfig( FTPClientConfig.SYST_UNIX, NUMERIC_DATE_FORMAT, null, null, null, null); /** * this is the regular expression used by this parser. * * Permissions: * r the file is readable * w the file is writable * x the file is executable * - the indicated permission is not granted * L mandatory locking occurs during access (the set-group-ID bit is * on and the group execution bit is off) * s the set-user-ID or set-group-ID bit is on, and the corresponding * user or group execution bit is also on * S undefined bit-state (the set-user-ID bit is on and the user * execution bit is off) * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and * execution is on * T the 1000 bit is turned on, and execution is off (undefined bit- * state) * e z/OS external link bit */ private static final String REGEX = "([bcdelfmpSs-])" +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s*" + "(\\d+)\\s+" // link count + "(?:(\\S+(?:\\s\\S+)*?)\\s+)?" // owner name (optional spaces) + "(?:(\\S+(?:\\s\\S+)*)\\s+)?" // group name (optional spaces) + "(\\d+(?:,\\s*\\d+)?)\\s+" // size or n,m /* * numeric or standard format date: * yyyy-mm-dd (expecting hh:mm to follow) * MMMM [d]d * [d]d MMM */ + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:[a-zA-Z]{3}\\s+\\d{1,2})|(?:\\d{1,2}\\s+[a-zA-Z]{3}))\\s+" /* year (for non-recent standard format) - yyyy or time (for numeric or recent standard format) [h]h:mm */ + "(\\d+(?::\\d+)?)\\s+" + "(\\S*)(\\s*.*)"; // the rest /** * The default constructor for a UnixFTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public UnixFTPEntryParser() { this(null); } /** * This constructor allows the creation of a UnixFTPEntryParser object with * something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public UnixFTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); } /** * Parses a line of a unix (standard) FTP server file listing and converts * it into a usable format in the form of an FTPFile * instance. If the file listing line doesn't describe a file, * null is returned, otherwise a FTPFile * instance representing the files in the directory is returned. *

* @param entry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { FTPFile file = new FTPFile(); file.setRawListing(entry); int type; boolean isDevice = false; if (matches(entry)) { String typeStr = group(1); String hardLinkCount = group(15); String usr = group(16); String grp = group(17); String filesize = group(18); String datestr = group(19) + " " + group(20); String name = group(21); String endtoken = group(22); try { file.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // intentionally do nothing } // bcdlfmpSs- switch (typeStr.charAt(0)) { case 'd': type = FTPFile.DIRECTORY_TYPE; break; case 'e': type = FTPFile.SYMBOLIC_LINK_TYPE; break; case 'l': type = FTPFile.SYMBOLIC_LINK_TYPE; break; case 'b': case 'c': isDevice = true; // break; - fall through //$FALL-THROUGH$ TODO change this if DEVICE_TYPE implemented case 'f': case '-': type = FTPFile.FILE_TYPE; break; default: type = FTPFile.UNKNOWN_TYPE; } file.setType(type); int g = 4; for (int access = 0; access < 3; access++, g += 4) { // Use != '-' to avoid having to check for suid and sticky bits file.setPermission(access, FTPFile.READ_PERMISSION, (!group(g).equals("-"))); file.setPermission(access, FTPFile.WRITE_PERMISSION, (!group(g + 1).equals("-"))); String execPerm = group(g + 2); if (!execPerm.equals("-") && !Character.isUpperCase(execPerm.charAt(0))) { file.setPermission(access, FTPFile.EXECUTE_PERMISSION, true); } else { file.setPermission(access, FTPFile.EXECUTE_PERMISSION, false); } } if (!isDevice) { try { file.setHardLinkCount(Integer.parseInt(hardLinkCount)); } catch (NumberFormatException e) { // intentionally do nothing } } file.setUser(usr); file.setGroup(grp); try { file.setSize(Long.parseLong(filesize)); } catch (NumberFormatException e) { // intentionally do nothing } if (null == endtoken) { file.setName(name); } else { // oddball cases like symbolic links, file names // with spaces in them. name += endtoken; if (type == FTPFile.SYMBOLIC_LINK_TYPE) { int end = name.indexOf(" -> "); // Give up if no link indicator is present if (end == -1) { file.setName(name); } else { file.setName(name.substring(0, end)); file.setLink(name.substring(end + 4)); } } else { file.setName(name); } } return file; } return null; } /** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */ @Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_UNIX, DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null, null); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java0000644000175000017500000001144111014672436030570 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * Implementation of FTPFileEntryParser and FTPFileListParser for OS2 Systems. * * @author Winston Ojeda * @author Steve Cohen * @version $Id: OS2FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl { private static final String DEFAULT_DATE_FORMAT = "MM-dd-yy HH:mm"; //11-09-01 12:30 /** * this is the regular expression used by this parser. */ private static final String REGEX = "\\s*([0-9]+)\\s*" + "(\\s+|[A-Z]+)\\s*" + "(DIR|\\s+)\\s*" + "(\\S+)\\s+(\\S+)\\s+" /* date stuff */ + "(\\S.*)"; /** * The default constructor for a OS2FTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public OS2FTPEntryParser() { this(null); } /** * This constructor allows the creation of an OS2FTPEntryParser object * with something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public OS2FTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); } /** * Parses a line of an OS2 FTP server file listing and converts it into a * usable format in the form of an FTPFile instance. If the * file listing line doesn't describe a file, null is * returned, otherwise a FTPFile instance representing the * files in the directory is returned. *

* @param entry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { FTPFile f = new FTPFile(); if (matches(entry)) { String size = group(1); String attrib = group(2); String dirString = group(3); String datestr = group(4)+" "+group(5); String name = group(6); try { f.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // intentionally do nothing } //is it a DIR or a file if (dirString.trim().equals("DIR") || attrib.trim().equals("DIR")) { f.setType(FTPFile.DIRECTORY_TYPE); } else { f.setType(FTPFile.FILE_TYPE); } //set the name f.setName(name.trim()); //set the size f.setSize(Long.parseLong(size.trim())); return (f); } return null; } /** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */ @Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_OS2, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParser.java0000644000175000017500000000365511014672436031116 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import java.util.Calendar; /** * This interface specifies the concept of parsing an FTP server's * timestamp. * @since 1.4 */ public interface FTPTimestampParser { /** * the default default date format. */ public static final String DEFAULT_SDF = UnixFTPEntryParser.DEFAULT_DATE_FORMAT; /** * the default recent date format. */ public static final String DEFAULT_RECENT_SDF = UnixFTPEntryParser.DEFAULT_RECENT_DATE_FORMAT; /** * Parses the supplied datestamp parameter. This parameter typically would * have been pulled from a longer FTP listing via the regular expression * mechanism * @param timestampStr - the timestamp portion of the FTP directory listing * to be parsed * @return a java.util.Calendar object initialized to the date * parsed by the parser * @throws ParseException if none of the parser mechanisms belonging to * the implementor can parse the input. */ public Calendar parseTimestamp(String timestampStr) throws ParseException; } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java0000644000175000017500000001324011014672436033150 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.Calendar; import org.apache.commons.net.ftp.FTPFile; /** * Parser for the Connect Enterprise Unix FTP Server From Sterling Commerce. * Here is a sample of the sort of output line this parser processes: * "-C--E-----FTP B QUA1I1 18128 41 Aug 12 13:56 QUADTEST" *

* Note: EnterpriseUnixFTPEntryParser can only be instantiated through the * DefaultFTPParserFactory by classname. It will not be chosen * by the autodetection scheme. * * @version $Id: EnterpriseUnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $ * @author Winston Ojeda * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory */ public class EnterpriseUnixFTPEntryParser extends RegexFTPFileEntryParserImpl { /** * months abbreviations looked for by this parser. Also used * to determine which month has been matched by the parser. */ private static final String MONTHS = "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"; /** * this is the regular expression used by this parser. */ private static final String REGEX = "(([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])" + "([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z]))" + "(\\S*)\\s*" + "(\\S+)\\s*" + "(\\S*)\\s*" + "(\\d*)\\s*" + "(\\d*)\\s*" + MONTHS + "\\s*" + "((?:[012]\\d*)|(?:3[01]))\\s*" + "((\\d\\d\\d\\d)|((?:[01]\\d)|(?:2[0123])):([012345]\\d))\\s" + "(\\S*)(\\s*.*)"; /** * The sole constructor for a EnterpriseUnixFTPEntryParser object. * */ public EnterpriseUnixFTPEntryParser() { super(REGEX); } /** * Parses a line of a unix FTP server file listing and converts it into a * usable format in the form of an FTPFile instance. If * the file listing line doesn't describe a file, null is * returned, otherwise a FTPFile instance representing the * files in the directory is returned. * * @param entry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { FTPFile file = new FTPFile(); file.setRawListing(entry); if (matches(entry)) { String usr = group(14); String grp = group(15); String filesize = group(16); String mo = group(17); String da = group(18); String yr = group(20); String hr = group(21); String min = group(22); String name = group(23); file.setType(FTPFile.FILE_TYPE); file.setUser(usr); file.setGroup(grp); try { file.setSize(Long.parseLong(filesize)); } catch (NumberFormatException e) { // intentionally do nothing } Calendar cal = Calendar.getInstance(); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.HOUR_OF_DAY, 0); try { int pos = MONTHS.indexOf(mo); int month = pos / 4; if (yr != null) { // it's a year cal.set(Calendar.YEAR, Integer.parseInt(yr)); } else { // it must be hour/minute or we wouldn't have matched int year = cal.get(Calendar.YEAR); // if the month we're reading is greater than now, it must // be last year if (cal.get(Calendar.MONTH) < month) { year--; } cal.set(Calendar.YEAR, year); cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hr)); cal.set(Calendar.MINUTE, Integer.parseInt(min)); } cal.set(Calendar.MONTH, month); cal.set(Calendar.DATE, Integer.parseInt(da)); file.setTimestamp(cal); } catch (NumberFormatException e) { // do nothing, date will be uninitialized } file.setName(name); return file; } return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java0000644000175000017500000001345511456020116030505 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import org.apache.commons.net.ftp.Configurable; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * Implementation of FTPFileEntryParser and FTPFileListParser for NT Systems. * * @author Winston Ojeda * @author Steve Cohen * @version $Id: NTFTPEntryParser.java 1022867 2010-10-15 09:35:10Z sebb $ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class NTFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { private static final String DEFAULT_DATE_FORMAT = "MM-dd-yy hh:mma"; //11-09-01 12:30PM private static final String DEFAULT_DATE_FORMAT2 = "MM-dd-yy kk:mm"; //11-09-01 18:30 private FTPTimestampParser timestampParser; /** * this is the regular expression used by this parser. */ private static final String REGEX = "(\\S+)\\s+(\\S+)\\s+" // MM-dd-yy whitespace hh:mma|kk:mm; swallow trailing spaces + "(?:(

)|([0-9]+))\\s+" // or ddddd; swallow trailing spaces + "(\\S.*)"; // First non-space followed by rest of line (name) /** * The sole constructor for an NTFTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public NTFTPEntryParser() { this(null); } /** * This constructor allows the creation of an NTFTPEntryParser object * with something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public NTFTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); FTPClientConfig config2 = new FTPClientConfig( FTPClientConfig.SYST_NT, DEFAULT_DATE_FORMAT2, null, null, null, null); config2.setDefaultDateFormatStr(DEFAULT_DATE_FORMAT2); this.timestampParser = new FTPTimestampParserImpl(); ((Configurable)this.timestampParser).configure(config2); } /** * Parses a line of an NT FTP server file listing and converts it into a * usable format in the form of an FTPFile instance. If the * file listing line doesn't describe a file, null is * returned, otherwise a FTPFile instance representing the * files in the directory is returned. *

* @param entry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { FTPFile f = new FTPFile(); f.setRawListing(entry); if (matches(entry)) { String datestr = group(1)+" "+group(2); String dirString = group(3); String size = group(4); String name = group(5); try { f.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // parsing fails, try the other date format try { f.setTimestamp(timestampParser.parseTimestamp(datestr)); } catch (ParseException e2) { // intentionally do nothing } } if (null == name || name.equals(".") || name.equals("..")) { return (null); } f.setName(name); if ("

".equals(dirString)) { f.setType(FTPFile.DIRECTORY_TYPE); f.setSize(0); } else { f.setType(FTPFile.FILE_TYPE); if (null != size) { f.setSize(Long.parseLong(size)); } } return (f); } return null; } /** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */ @Override public FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_NT, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/ParserInitializationException.java0000644000175000017500000000405010542533103033425 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; /** * This class encapsulates all errors that may be thrown by * the process of an FTPFileEntryParserFactory creating and * instantiating an FTPFileEntryParser. */ public class ParserInitializationException extends RuntimeException { /** * Root exception that caused this to be thrown */ private final Throwable rootCause; /** * Constucts a ParserInitializationException with just a message * * @param message Exception message */ public ParserInitializationException(String message) { super(message); this.rootCause = null; } /** * Constucts a ParserInitializationException with a message * and a root cause. * * @param message Exception message * @param rootCause root cause throwable that caused * this to be thrown */ public ParserInitializationException(String message, Throwable rootCause) { super(message); this.rootCause = rootCause; } /** * returns the root cause of this exception or null * if no root cause was specified. * * @return the root cause of this exception being thrown */ public Throwable getRootCause() { return this.rootCause; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java0000644000175000017500000001154711354512541032665 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.commons.net.ftp.FTPFileEntryParserImpl; /** * This abstract class implements both the older FTPFileListParser and * newer FTPFileEntryParser interfaces with default functionality. * All the classes in the parser subpackage inherit from this. * * This is the base for all regular based FTPFileEntryParser * * @author Steve Cohen */ public abstract class RegexFTPFileEntryParserImpl extends FTPFileEntryParserImpl { /** * internal pattern the matcher tries to match, representing a file * entry */ private Pattern pattern = null; /** * internal match result used by the parser */ private MatchResult result = null; /** * Internal PatternMatcher object used by the parser. It has protected * scope in case subclasses want to make use of it for their own purposes. */ protected Matcher _matcher_ = null; /** * The constructor for a RegexFTPFileEntryParserImpl object. * * @param regex The regular expression with which this object is * initialized. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen in * normal conditions. It it is seen, this is a sign that a subclass has * been created with a bad regular expression. Since the parser must be * created before use, this means that any bad parser subclasses created * from this will bomb very quickly, leading to easy detection. */ public RegexFTPFileEntryParserImpl(String regex) { super(); setRegex(regex); } /** * Convenience method delegates to the internal MatchResult's matches() * method. * * @param s the String to be matched * @return true if s matches this object's regular expression. */ public boolean matches(String s) { this.result = null; _matcher_ = pattern.matcher(s); if (_matcher_.matches()) { this.result = _matcher_.toMatchResult(); } return null != this.result; } /** * Convenience method * * @return the number of groups() in the internal MatchResult. */ public int getGroupCnt() { if (this.result == null) { return 0; } return this.result.groupCount(); } /** * Convenience method delegates to the internal MatchResult's group() * method. * * @param matchnum match group number to be retrieved * * @return the content of the matchnum'th group of the internal * match or null if this method is called without a match having * been made. */ public String group(int matchnum) { if (this.result == null) { return null; } return this.result.group(matchnum); } /** * For debugging purposes - returns a string shows each match group by * number. * * @return a string shows each match group by number. */ public String getGroupsAsString() { StringBuilder b = new StringBuilder(); for (int i = 1; i <= this.result.groupCount(); i++) { b.append(i).append(") ").append(this.result.group(i)).append( System.getProperty("line.separator")); } return b.toString(); } /** * Alter the current regular expression being utilised for entry parsing * and create a new {@link Pattern} instance. * @param regex The new regular expression * @return true if the compiled pattern is not null * @since 2.0 */ public boolean setRegex(String regex) { try { pattern = Pattern.compile(regex); } catch (PatternSyntaxException pse) { throw new IllegalArgumentException("Unparseable regex supplied: " + regex); } return (pattern != null); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java0000644000175000017500000004543311014673543030642 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import java.util.List; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * Implementation of FTPFileEntryParser and FTPFileListParser for IBM zOS/MVS * Systems. * * @author Henrik Sorensen * @author Jeff Nadler * @author William Noto * * @version $Id: MVSFTPEntryParser.java 658520 2008-05-21 01:14:11Z sebb $ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for * usage instructions) */ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { static final int UNKNOWN_LIST_TYPE = -1; static final int FILE_LIST_TYPE = 0; static final int MEMBER_LIST_TYPE = 1; static final int UNIX_LIST_TYPE = 2; static final int JES_LEVEL_1_LIST_TYPE = 3; static final int JES_LEVEL_2_LIST_TYPE = 4; private int isType = UNKNOWN_LIST_TYPE; /** * Fallback parser for Unix-style listings */ private UnixFTPEntryParser unixFTPEntryParser; /** * Dates are ignored for file lists, but are used for member lists where * possible */ static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd HH:mm"; // 2001/09/18 // 13:52 /** * Matches these entries: Volume Unit Referred Ext Used Recfm Lrecl BlkSz * Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80 80 PS MDI.OKL.WORK * */ static final String FILE_LIST_REGEX = "\\S+\\s+" + // volume // ignored "\\S+\\s+" + // unit - ignored "\\S+\\s+" + // access date - ignored "\\S+\\s+" + // extents -ignored "\\S+\\s+" + // used - ignored "[FV]\\S*\\s+" + // recfm - must start with F or V "\\S+\\s+" + // logical record length -ignored "\\S+\\s+" + // block size - ignored "(PS|PO|PO-E)\\s+" + // Dataset organisation. Many exist // but only support: PS, PO, PO-E "(\\S+)\\s*"; // Dataset Name (file name) /** * Matches these entries: Name VV.MM Created Changed Size Init Mod Id * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001 */ static final String MEMBER_LIST_REGEX = "(\\S+)\\s+" + // name "\\S+\\s+" + // version, modification (ignored) "\\S+\\s+" + // create date (ignored) "(\\S+)\\s+" + // modification date "(\\S+)\\s+" + // modification time "\\S+\\s+" + // size in lines (ignored) "\\S+\\s+" + // size in lines at creation(ignored) "\\S+\\s+" + // lines modified (ignored) "\\S+\\s*"; // id of user who modified (ignored) /** * Matches these entries, note: no header: IBMUSER1 JOB01906 OUTPUT 3 Spool * Files 012345678901234567890123456789012345678901234 1 2 3 4 */ static final String JES_LEVEL_1_LIST_REGEX = "(\\S+)\\s+" + // job // name // ignored "(\\S+)\\s+" + // job number "(\\S+)\\s+" + // job status (OUTPUT,INPUT,ACTIVE) "(\\S+)\\s+" + // number of spool files "(\\S+)\\s+" + // Text "Spool" ignored "(\\S+)\\s*" // Text "Files" ignored ; /** * JES INTERFACE LEVEL 2 parser Matches these entries: JOBNAME JOBID OWNER * STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool files * IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files * 012345678901234567890123456789012345678901234 1 2 3 4 * 012345678901234567890123456789012345678901234567890 */ static final String JES_LEVEL_2_LIST_REGEX = "(\\S+)\\s+" + // job // name // ignored "(\\S+)\\s+" + // job number "(\\S+)\\s+" + // owner ignored "(\\S+)\\s+" + // job status (OUTPUT,INPUT,ACTIVE) ignored "(\\S+)\\s+" + // job class ignored "(\\S+).*" // rest ignored ; /* * --------------------------------------------------------------------- * Very brief and incomplete description of the zOS/MVS-filesystem. (Note: * "zOS" is the operating system on the mainframe, and is the new name for * MVS) * * The filesystem on the mainframe does not have hierarchal structure as for * example the unix filesystem. For a more comprehensive description, please * refer to the IBM manuals * * @LINK: * http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/dgt2d440/CONTENTS * * * Dataset names ============= * * A dataset name consist of a number of qualifiers separated by '.', each * qualifier can be at most 8 characters, and the total length of a dataset * can be max 44 characters including the dots. * * * Dataset organisation ==================== * * A dataset represents a piece of storage allocated on one or more disks. * The structure of the storage is described with the field dataset * organinsation (DSORG). There are a number of dataset organisations, but * only two are usable for FTP transfer. * * DSORG: PS: sequential, or flat file PO: partitioned dataset PO-E: * extended partitioned dataset * * The PS file is just a flat file, as you would find it on the unix file * system. * * The PO and PO-E files, can be compared to a single level directory * structure. A PO file consist of a number of dataset members, or files if * you will. It is possible to CD into the file, and to retrieve the * individual members. * * * Dataset record format ===================== * * The physical layout of the dataset is described on the dataset itself. * There are a number of record formats (RECFM), but just a few is relavant * for the FTP transfer. * * Any one beginning with either F or V can safely used by FTP transfer. All * others should only be used with great care, so this version will just * ignore the other record formats. F means a fixed number of records per * allocated storage, and V means a variable number of records. * * * Other notes =========== * * The file system supports automatically backup and retrieval of datasets. * If a file is backed up, the ftp LIST command will return: ARCIVE Not * Direct Access Device KJ.IOP998.ERROR.PL.UNITTEST * * * Implementation notes ==================== * * Only datasets that have dsorg PS, PO or PO-E and have recfm beginning * with F or V, is fully parsed. * * The following fields in FTPFile is used: FTPFile.Rawlisting: Always set. * FTPFile.Type: DIRECTORY_TYPE or FILE_TYPE or UNKNOWN FTPFile.Name: name * FTPFile.Timestamp: change time or null * * * * Additional information ====================== * * The MVS ftp server supports a number of features via the FTP interface. * The features are controlled with the FTP command quote site filetype= * SEQ is the default and used for normal file transfer JES is used to * interact with the Job Entry Subsystem (JES) similar to a job scheduler * DB2 is used to interact with a DB2 subsystem * * This parser supports SEQ and JES. * * * * * * */ /** * The sole constructor for a MVSFTPEntryParser object. * */ public MVSFTPEntryParser() { super(""); // note the regex is set in preParse. super.configure(null); // configure parser with default configurations } /** * Parses a line of an z/OS - MVS FTP server file listing and converts it * into a usable format in the form of an FTPFile instance. * If the file listing line doesn't describe a file, then * null is returned. Otherwise a FTPFile * instance representing the file is returned. * * @param entry * A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { boolean isParsed = false; FTPFile f = new FTPFile(); if (isType == FILE_LIST_TYPE) isParsed = parseFileList(f, entry); else if (isType == MEMBER_LIST_TYPE) { isParsed = parseMemberList(f, entry); if (!isParsed) isParsed = parseSimpleEntry(f, entry); } else if (isType == UNIX_LIST_TYPE) { isParsed = parseUnixList(f, entry); } else if (isType == JES_LEVEL_1_LIST_TYPE) { isParsed = parseJeslevel1List(f, entry); } else if (isType == JES_LEVEL_2_LIST_TYPE) { isParsed = parseJeslevel2List(f, entry); } if (!isParsed) f = null; return f; } /** * Parse entries representing a dataset list. Only datasets with DSORG PS or * PO or PO-E and with RECFM F* or V* will be parsed. * * Format of ZOS/MVS file list: 1 2 3 4 5 6 7 8 9 10 Volume Unit Referred * Ext Used Recfm Lrecl BlkSz Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80 * 80 PS MDI.OKL.WORK ARCIVE Not Direct Access Device * KJ.IOP998.ERROR.PL.UNITTEST B1N231 3390 2006/03/20 1 15 VB 256 27998 PO * PLU B1N231 3390 2006/03/20 1 15 VB 256 27998 PO-E PLB * * ----------------------------------- Group within Regex [1] Volume [2] * Unit [3] Referred [4] Ext: number of extents [5] Used [6] Recfm: Record * format [7] Lrecl: Logical record length [8] BlkSz: Block size [9] Dsorg: * Dataset organisation. Many exists but only support: PS, PO, PO-E [10] * Dsname: Dataset name * * Note: When volume is ARCIVE, it means the dataset is stored somewhere in * a tape archive. These entries is currently not supported by this parser. * A null value is returned. * * @param file * will be updated with Name, Type, Timestamp if parsed. * @param entry zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseFileList(FTPFile file, String entry) { if (matches(entry)) { file.setRawListing(entry); String name = group(2); String dsorg = group(1); file.setName(name); // DSORG if ("PS".equals(dsorg)) { file.setType(FTPFile.FILE_TYPE); } else if ("PO".equals(dsorg) || "PO-E".equals(dsorg)) { // regex already ruled out anything other than PO or PO-E file.setType(FTPFile.DIRECTORY_TYPE); } else { return false; } return true; } return false; } /** * Parse entries within a partitioned dataset. * * Format of a memberlist within a PDS: 1 2 3 4 5 6 7 8 9 Name VV.MM Created * Changed Size Init Mod Id TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 * 0 KIL001 TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001 * * ------------------------------------------- [1] Name [2] VV.MM: Version . * modification [3] Created: yyyy / MM / dd [4,5] Changed: yyyy / MM / dd * HH:mm [6] Size: number of lines [7] Init: number of lines when first * created [8] Mod: number of modified lines a last save [9] Id: User id for * last update * * * @param file * will be updated with Name, Type and Timestamp if parsed. * @param entry zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseMemberList(FTPFile file, String entry) { if (matches(entry)) { file.setRawListing(entry); String name = group(1); String datestr = group(2) + " " + group(3); file.setName(name); file.setType(FTPFile.FILE_TYPE); try { file.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { e.printStackTrace(); // just ignore parsing errors. // TODO check this is ok return false; // this is a parsing failure too. } return true; } return false; } /** * Assigns the name to the first word of the entry. Only to be used from a * safe context, for example from a memberlist, where the regex for some * reason fails. Then just assign the name field of FTPFile. * * @param file * @param entry * @return */ private boolean parseSimpleEntry(FTPFile file, String entry) { if (entry != null && entry.length() > 0) { file.setRawListing(entry); String name = entry.split(" ")[0]; file.setName(name); file.setType(FTPFile.FILE_TYPE); return true; } return false; } /** * Parse the entry as a standard unix file. Using the UnixFTPEntryParser. * * @param file * @param entry * @return true: entry is parsed, false: entry could not be parsed. */ private boolean parseUnixList(FTPFile file, String entry) { file = unixFTPEntryParser.parseFTPEntry(entry); if (file == null) return false; return true; } /** * Matches these entries, note: no header: [1] [2] [3] [4] [5] IBMUSER1 * JOB01906 OUTPUT 3 Spool Files * 012345678901234567890123456789012345678901234 1 2 3 4 * ------------------------------------------- Group in regex [1] Job name * [2] Job number [3] Job status (INPUT,ACTIVE,OUTPUT) [4] Number of sysout * files [5] The string "Spool Files" * * * @param file * will be updated with Name, Type and Timestamp if parsed. * @param entry zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseJeslevel1List(FTPFile file, String entry) { if (matches(entry)) { if (group(3).equalsIgnoreCase("OUTPUT")) { file.setRawListing(entry); String name = group(2); /* Job Number, used by GET */ file.setName(name); file.setType(FTPFile.FILE_TYPE); return true; } } return false; } /** * Matches these entries, note: no header: [1] [2] [3] [4] [5] JOBNAME JOBID * OWNER STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool * files IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files * 012345678901234567890123456789012345678901234 1 2 3 4 * ------------------------------------------- Group in regex [1] Job name * [2] Job number [3] Owner [4] Job status (INPUT,ACTIVE,OUTPUT) [5] Job * Class [6] The rest * * * @param file * will be updated with Name, Type and Timestamp if parsed. * @param entry zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseJeslevel2List(FTPFile file, String entry) { if (matches(entry)) { if (group(4).equalsIgnoreCase("OUTPUT")) { file.setRawListing(entry); String name = group(2); /* Job Number, used by GET */ file.setName(name); file.setType(FTPFile.FILE_TYPE); return true; } } return false; } /** * preParse is called as part of the interface. Per definition is is called * before the parsing takes place. Three kind of lists is recognize: * z/OS-MVS File lists z/OS-MVS Member lists unix file lists * @since 2.0 */ @Override public List preParse(List orig) { // simply remove the header line. Composite logic will take care of the // two different types of // list in short order. if (orig != null && orig.size() > 0) { String header = orig.get(0); if (header.indexOf("Volume") >= 0 && header.indexOf("Dsname") >= 0) { setType(FILE_LIST_TYPE); super.setRegex(FILE_LIST_REGEX); } else if (header.indexOf("Name") >= 0 && header.indexOf("Id") >= 0) { setType(MEMBER_LIST_TYPE); super.setRegex(MEMBER_LIST_REGEX); } else if (header.indexOf("total") == 0) { setType(UNIX_LIST_TYPE); unixFTPEntryParser = new UnixFTPEntryParser(); } else if (header.indexOf("Spool Files") >= 30) { setType(JES_LEVEL_1_LIST_TYPE); super.setRegex(JES_LEVEL_1_LIST_REGEX); } else if (header.indexOf("JOBNAME") == 0 && header.indexOf("JOBID") > 8) {// header contains JOBNAME JOBID OWNER // STATUS CLASS setType(JES_LEVEL_2_LIST_TYPE); super.setRegex(JES_LEVEL_2_LIST_REGEX); } else { setType(UNKNOWN_LIST_TYPE); } if (isType != JES_LEVEL_1_LIST_TYPE) { // remove header is necessary orig.remove(0); } } return orig; } /** * Explicitly set the type of listing being processed. * @param type The listing type. */ void setType(int type) { isType = type; } /* * @return */ @Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig(FTPClientConfig.SYST_MVS, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java0000644000175000017500000001113611014672436030733 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * @version $Id: OS400FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $ */ public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl { private static final String DEFAULT_DATE_FORMAT = "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24 private static final String REGEX = "(\\S+)\\s+" // user + "(\\d+)\\s+" // size + "(\\S+)\\s+(\\S+)\\s+" // date stuff + "(\\*\\S+)\\s+" // *STMF/*DIR + "(\\S+/?)\\s*"; // filename /** * The default constructor for a OS400FTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public OS400FTPEntryParser() { this(null); } /** * This constructor allows the creation of an OS400FTPEntryParser object * with something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public OS400FTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); } public FTPFile parseFTPEntry(String entry) { FTPFile file = new FTPFile(); file.setRawListing(entry); int type; if (matches(entry)) { String usr = group(1); String filesize = group(2); String datestr = group(3)+" "+group(4); String typeStr = group(5); String name = group(6); try { file.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // intentionally do nothing } if (typeStr.equalsIgnoreCase("*STMF")) { type = FTPFile.FILE_TYPE; } else if (typeStr.equalsIgnoreCase("*DIR")) { type = FTPFile.DIRECTORY_TYPE; } else { type = FTPFile.UNKNOWN_TYPE; } file.setType(type); file.setUser(usr); try { file.setSize(Long.parseLong(filesize)); } catch (NumberFormatException e) { // intentionally do nothing } if (name.endsWith("/")) { name = name.substring(0, name.length() - 1); } int pos = name.lastIndexOf('/'); if (pos > -1) { name = name.substring(pos + 1); } file.setName(name); return file; } return null; } /** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */ @Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_OS400, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java0000644000175000017500000001566411014673543031605 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * Implementation of FTPFileEntryParser and FTPFileListParser for Netware Systems. Note that some of the proprietary * extensions for Novell-specific operations are not supported. See * http://www.novell.com/documentation/nw65/index.html?page=/documentation/nw65/ftp_enu/data/fbhbgcfa.html * for more details. * * @author Rory Winston * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) * @version $Id: NetwareFTPEntryParser.java 658520 2008-05-21 01:14:11Z sebb $ * @since 1.5 */ public class NetwareFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { /** * Default date format is e.g. Feb 22 2006 */ private static final String DEFAULT_DATE_FORMAT = "MMM dd yyyy"; /** * Default recent date format is e.g. Feb 22 17:32 */ private static final String DEFAULT_RECENT_DATE_FORMAT = "MMM dd HH:mm"; /** * this is the regular expression used by this parser. * Example: d [-W---F--] SCION_VOL2 512 Apr 13 23:12 VOL2 */ private static final String REGEX = "(d|-){1}\\s+" // Directory/file flag + "\\[(.*)\\]\\s+" // Attributes + "(\\S+)\\s+" + "(\\d+)\\s+" // Owner and size + "(\\S+\\s+\\S+\\s+((\\d+:\\d+)|(\\d{4})))" // Long/short date format + "\\s+(.*)"; // Filename (incl. spaces) /** * The default constructor for a NetwareFTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public NetwareFTPEntryParser() { this(null); } /** * This constructor allows the creation of an NetwareFTPEntryParser object * with something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public NetwareFTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); } /** * Parses a line of an NetwareFTP server file listing and converts it into a * usable format in the form of an FTPFile instance. If the * file listing line doesn't describe a file, null is * returned, otherwise a FTPFile instance representing the * files in the directory is returned. *

*

* Netware file permissions are in the following format: RWCEAFMS, and are explained as follows: *

    *
  • S - Supervisor; All rights. *
  • R - Read; Right to open and read or execute. *
  • W - Write; Right to open and modify. *
  • C - Create; Right to create; when assigned to a file, allows a deleted file to be recovered. *
  • E - Erase; Right to delete. *
  • M - Modify; Right to rename a file and to change attributes. *
  • F - File Scan; Right to see directory or file listings. *
  • A - Access Control; Right to modify trustee assignments and the Inherited Rights Mask. *
* * See here * for more details * * @param entry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { FTPFile f = new FTPFile(); if (matches(entry)) { String dirString = group(1); String attrib = group(2); String user = group(3); String size = group(4); String datestr = group(5); String name = group(9); try { f.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // intentionally do nothing } //is it a DIR or a file if (dirString.trim().equals("d")) { f.setType(FTPFile.DIRECTORY_TYPE); } else // Should be "-" { f.setType(FTPFile.FILE_TYPE); } f.setUser(user); //set the name f.setName(name.trim()); //set the size f.setSize(Long.parseLong(size.trim())); // Now set the permissions (or at least a subset thereof - full permissions would probably require // subclassing FTPFile and adding extra metainformation there) if (attrib.indexOf("R") != -1) { f.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION, true); } if (attrib.indexOf("W") != -1) { f.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION, true); } return (f); } return null; } /** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */ @Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig(FTPClientConfig.SYST_NETWARE, DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null, null); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootcommons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.javacommons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.j0000644000175000017500000001064511330134135033512 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.ParseException; import java.util.Calendar; import org.apache.commons.net.ftp.Configurable; import org.apache.commons.net.ftp.FTPClientConfig; /** *

* This abstract class implements the common timestamp parsing * algorithm for all the concrete parsers. Classes derived from * this one will parse file listings via a supplied regular expression * that pulls out the date portion as a separate string which is * passed to the underlying {@link FTPTimestampParser delegate} to * handle parsing of the file timestamp. *

* This class also implements the {@link Configurable Configurable} * interface to allow the parser to be configured from the outside. *

* @since 1.4 */ /** * To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates - Comments */ public abstract class ConfigurableFTPFileEntryParserImpl extends RegexFTPFileEntryParserImpl implements Configurable { private final FTPTimestampParser timestampParser; /** * Only constructor for this abstract class. * @param regex Regular expression used main parsing of the * file listing. */ public ConfigurableFTPFileEntryParserImpl(String regex) { super(regex); this.timestampParser = new FTPTimestampParserImpl(); } /** * This method is called by the concrete parsers to delegate * timestamp parsing to the timestamp parser. *

* @param timestampStr the timestamp string pulled from the * file listing by the regular expression parser, to be submitted * to the timestampParser for extracting the timestamp. * @return a java.util.Calendar containing results of the * timestamp parse. */ public Calendar parseTimestamp(String timestampStr) throws ParseException { return this.timestampParser.parseTimestamp(timestampStr); } /** * Implementation of the {@link Configurable Configurable} * interface. Configures this parser by delegating to the * underlying Configurable FTPTimestampParser implementation, ' * passing it the supplied {@link FTPClientConfig FTPClientConfig} * if that is non-null or a default configuration defined by * each concrete subclass. *

* @param config the configuration to be used to configure this parser. * If it is null, a default configuration defined by * each concrete subclass is used instead. */ public void configure(FTPClientConfig config) { if (this.timestampParser instanceof Configurable) { FTPClientConfig defaultCfg = getDefaultConfiguration(); if (config != null) { if (null == config.getDefaultDateFormatStr()) { config.setDefaultDateFormatStr(defaultCfg.getDefaultDateFormatStr()); } if (null == config.getRecentDateFormatStr()) { config.setRecentDateFormatStr(defaultCfg.getRecentDateFormatStr()); } ((Configurable)this.timestampParser).configure(config); } else { ((Configurable)this.timestampParser).configure(defaultCfg); } } } /** * Each concrete subclass must define this member to create * a default configuration to be used when that subclass is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for the subclass. */ protected abstract FTPClientConfig getDefaultConfiguration(); } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java0000644000175000017500000000502510542533103032346 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.apache.commons.net.ftp.FTPFileEntryParserImpl; /** * This implementation allows to pack some FileEntryParsers together * and handle the case where to returned dirstyle isnt clearly defined. * The matching parser will be cached. * If the cached parser wont match due to the server changed the dirstyle, * a new matching parser will be searched. * * @author Mario Ivankovits */ public class CompositeFileEntryParser extends FTPFileEntryParserImpl { private final FTPFileEntryParser[] ftpFileEntryParsers; private FTPFileEntryParser cachedFtpFileEntryParser; public CompositeFileEntryParser(FTPFileEntryParser[] ftpFileEntryParsers) { super(); this.cachedFtpFileEntryParser = null; this.ftpFileEntryParsers = ftpFileEntryParsers; } public FTPFile parseFTPEntry(String listEntry) { if (cachedFtpFileEntryParser != null) { FTPFile matched = cachedFtpFileEntryParser.parseFTPEntry(listEntry); if (matched != null) { return matched; } } else { for (int iterParser=0; iterParser < ftpFileEntryParsers.length; iterParser++) { FTPFileEntryParser ftpFileEntryParser = ftpFileEntryParsers[iterParser]; FTPFile matched = ftpFileEntryParser.parseFTPEntry(listEntry); if (matched != null) { cachedFtpFileEntryParser = ftpFileEntryParser; return matched; } } } return null; } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java0000644000175000017500000002447011466231525030641 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.text.ParseException; import java.util.StringTokenizer; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPListParseEngine; /** * Implementation FTPFileEntryParser and FTPFileListParser for VMS Systems. * This is a sample of VMS LIST output * * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", *

* Note: VMSFTPEntryParser can only be instantiated through the * DefaultFTPParserFactory by classname. It will not be chosen * by the autodetection scheme. * *

* * @author Winston Ojeda * @author Steve Cohen * @author Stephane ESTE-GRACIAS * @version $Id: VMSFTPEntryParser.java 1032938 2010-11-09 11:41:09Z sebb $ * * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory */ public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { private static final String DEFAULT_DATE_FORMAT = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24 /** * this is the regular expression used by this parser. */ private static final String REGEX = "(.*;[0-9]+)\\s*" //1 file and version + "(\\d+)/\\d+\\s*" //2 size/allocated +"(\\S+)\\s+(\\S+)\\s+" //3+4 date and time + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)"; //9,10,11 Permissions (O,G,W) // TODO - perhaps restrict permissions to [RWED]* ? /** * Constructor for a VMSFTPEntryParser object. * * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. */ public VMSFTPEntryParser() { this(null); } /** * This constructor allows the creation of a VMSFTPEntryParser object with * something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @exception IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * REGEX is not a valid regular expression. * @since 1.4 */ public VMSFTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); } /*** * Parses an FTP server file listing and converts it into a usable format * in the form of an array of FTPFile instances. If the * file list contains no files, null should be * returned, otherwise an array of FTPFile instances * representing the files in the directory is returned. *

* @param listStream The InputStream from which the file list should be * read. * @return The list of file information contained in the given path. null * if the list could not be obtained or if there are no files in * the directory. * @exception IOException If an I/O error occurs reading the listStream. * @deprecated (2.2) No other FTPFileEntryParser implementations have this method. * Not currently used by NET code. To be removed in 3.0 ***/ @Deprecated public FTPFile[] parseFileList(InputStream listStream) throws IOException { FTPListParseEngine engine = new FTPListParseEngine(this); engine.readServerList(listStream, null); return engine.getFiles(); } /** * Parses a line of a VMS FTP server file listing and converts it into a * usable format in the form of an FTPFile instance. If the * file listing line doesn't describe a file, null is * returned, otherwise a FTPFile instance representing the * files in the directory is returned. *

* @param entry A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { //one block in VMS equals 512 bytes long longBlock = 512; if (matches(entry)) { FTPFile f = new FTPFile(); f.setRawListing(entry); String name = group(1); String size = group(2); String datestr = group(3)+" "+group(4); String owner = group(5); String permissions[] = new String[3]; permissions[0]= group(9); permissions[1]= group(10); permissions[2]= group(11); try { f.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // intentionally do nothing } String grp; String user; StringTokenizer t = new StringTokenizer(owner, ","); switch (t.countTokens()) { case 1: grp = null; user = t.nextToken(); break; case 2: grp = t.nextToken(); user = t.nextToken(); break; default: grp = null; user = null; } if (name.lastIndexOf(".DIR") != -1) { f.setType(FTPFile.DIRECTORY_TYPE); } else { f.setType(FTPFile.FILE_TYPE); } //set FTPFile name //Check also for versions to be returned or not if (isVersioning()) { f.setName(name); } else { name = name.substring(0, name.lastIndexOf(";")); f.setName(name); } //size is retreived in blocks and needs to be put in bytes //for us humans and added to the FTPFile array long sizeInBytes = Long.parseLong(size) * longBlock; f.setSize(sizeInBytes); f.setGroup(grp); f.setUser(user); //set group and owner //Set file permission. //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain //R (read) W (write) E (execute) D (delete) //iterate for OWNER GROUP WORLD permissions for (int access = 0; access < 3; access++) { String permission = permissions[access]; f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0); f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0); f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0); } return f; } return null; } /** * Reads the next entry using the supplied BufferedReader object up to * whatever delemits one entry from the next. This parser cannot use * the default implementation of simply calling BufferedReader.readLine(), * because one entry may span multiple lines. * * @param reader The BufferedReader object from which entries are to be * read. * * @return A string representing the next ftp entry or null if none found. * @exception IOException thrown on any IO Error reading from the reader. */ @Override public String readNextEntry(BufferedReader reader) throws IOException { String line = reader.readLine(); StringBuilder entry = new StringBuilder(); while (line != null) { if (line.startsWith("Directory") || line.startsWith("Total")) { line = reader.readLine(); continue; } entry.append(line); if (line.trim().endsWith(")")) { break; } line = reader.readLine(); } return (entry.length() == 0 ? null : entry.toString()); } protected boolean isVersioning() { return false; } /** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */ @Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_VMS, DEFAULT_DATE_FORMAT, null, null, null, null); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java0000644000175000017500000000524411014672436032400 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * The interface describes a factory for creating FTPFileEntryParsers. * @since 1.2 */ public interface FTPFileEntryParserFactory { /** * Implementation should be a method that decodes the * supplied key and creates an object implementing the * interface FTPFileEntryParser. * * @param key A string that somehow identifies an * FTPFileEntryParser to be created. * * @return the FTPFileEntryParser created. * @exception ParserInitializationException * Thrown on any exception in instantiation */ public FTPFileEntryParser createFileEntryParser(String key) throws ParserInitializationException; /** *

* Implementation should be a method that extracts * a key from the supplied {@link FTPClientConfig FTPClientConfig} * parameter and creates an object implementing the * interface FTPFileEntryParser and uses the supplied configuration * to configure it. *

* Note that this method will generally not be called in scenarios * that call for autodetection of parser type but rather, for situations * where the user knows that the server uses a non-default configuration * and knows what that configuration is. *

* * @param config A {@link FTPClientConfig FTPClientConfig} * used to configure the parser created * * @return the @link FTPFileEntryParser FTPFileEntryParser} so created. * @exception ParserInitializationException * Thrown on any exception in instantiation * @since 1.4 */ public FTPFileEntryParser createFileEntryParser(FTPClientConfig config) throws ParserInitializationException; } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootcommons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.javacommons-net-2.2/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.jav0000644000175000017500000002266311456056230033546 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.Configurable; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * This is the default implementation of the * FTPFileEntryParserFactory interface. This is the * implementation that will be used by * org.apache.commons.net.ftp.FTPClient.listFiles() * if no other implementation has been specified. * * @see org.apache.commons.net.ftp.FTPClient#listFiles * @see org.apache.commons.net.ftp.FTPClient#setParserFactory */ public class DefaultFTPFileEntryParserFactory implements FTPFileEntryParserFactory { private FTPClientConfig config = null; /** * This default implementation of the FTPFileEntryParserFactory * interface works according to the following logic: * First it attempts to interpret the supplied key as a fully * qualified classname of a class implementing the * FTPFileEntryParser interface. If that succeeds, a parser * object of this class is instantiated and is returned; * otherwise it attempts to interpret the key as an identirier * commonly used by the FTP SYST command to identify systems. *

* If key is not recognized as a fully qualified * classname known to the system, this method will then attempt * to see whether it contains a string identifying one of * the known parsers. This comparison is case-insensitive. * The intent here is where possible, to select as keys strings * which are returned by the SYST command on the systems which * the corresponding parser successfully parses. This enables * this factory to be used in the auto-detection system. *

* * @param key should be a fully qualified classname corresponding to * a class implementing the FTPFileEntryParser interface
* OR
* a string containing (case-insensitively) one of the * following keywords: *

    *
  • {@link FTPClientConfig#SYST_UNIX UNIX}
  • *
  • {@link FTPClientConfig#SYST_NT WINDOWS}
  • *
  • {@link FTPClientConfig#SYST_OS2 OS/2}
  • *
  • {@link FTPClientConfig#SYST_OS400 OS/400}
  • *
  • {@link FTPClientConfig#SYST_VMS VMS}
  • *
  • {@link FTPClientConfig#SYST_MVS MVS}
  • *
  • {@link FTPClientConfig#SYST_NETWARE NETWARE}
  • *
* @return the FTPFileEntryParser corresponding to the supplied key. * @throws ParserInitializationException thrown if for any reason the factory cannot resolve * the supplied key into an FTPFileEntryParser. * @see FTPFileEntryParser */ public FTPFileEntryParser createFileEntryParser(String key) { if (key == null) throw new ParserInitializationException("Parser key cannot be null"); Class parserClass = null; FTPFileEntryParser parser = null; try { parserClass = Class.forName(key); try { parser = (FTPFileEntryParser) parserClass.newInstance(); } catch (ClassCastException e) { throw new ParserInitializationException(parserClass.getName() + " does not implement the interface " + "org.apache.commons.net.ftp.FTPFileEntryParser.", e); } } catch (ClassNotFoundException e) { try { String ukey = key.toUpperCase(java.util.Locale.ENGLISH); if (ukey.indexOf(FTPClientConfig.SYST_UNIX) >= 0) { parser = createUnixFTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_VMS) >= 0) { parser = createVMSVersioningFTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0) { parser = createNTFTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_OS2) >= 0) { parser = createOS2FTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_OS400) >= 0 || ukey.indexOf(FTPClientConfig.SYST_AS400) >= 0) { parser = createOS400FTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0) { parser = createMVSEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_NETWARE) >= 0) { parser = createNetwareFTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0) { // L8 normally means Unix, but move it to the end for some L8 systems that aren't. // This check should be last! parser = createUnixFTPEntryParser(); } else { throw new ParserInitializationException("Unknown parser type: " + key); } } // TODO can this happen? catch (NoClassDefFoundError nf) { throw new ParserInitializationException("Error initializing parser", nf); } } catch (NoClassDefFoundError e) { throw new ParserInitializationException("Error initializing parser", e); } catch (ParserInitializationException e) // Don't rewrap exception { throw e; } catch (Throwable e) { throw new ParserInitializationException("Error initializing parser", e); } if (parser instanceof Configurable) { ((Configurable)parser).configure(this.config); } return parser; } /** *

Implementation extracts a key from the supplied * {@link FTPClientConfig FTPClientConfig} * parameter and creates an object implementing the * interface FTPFileEntryParser and uses the supplied configuration * to configure it. *

* Note that this method will generally not be called in scenarios * that call for autodetection of parser type but rather, for situations * where the user knows that the server uses a non-default configuration * and knows what that configuration is. *

* @param config A {@link FTPClientConfig FTPClientConfig} * used to configure the parser created * * @return the @link FTPFileEntryParser FTPFileEntryParser} so created. * @exception ParserInitializationException * Thrown on any exception in instantiation * @since 1.4 */ public FTPFileEntryParser createFileEntryParser(FTPClientConfig config) throws ParserInitializationException { this.config = config; String key = config.getServerSystemKey(); return createFileEntryParser(key); } public FTPFileEntryParser createUnixFTPEntryParser() { return new UnixFTPEntryParser(); } public FTPFileEntryParser createVMSVersioningFTPEntryParser() { return new VMSVersioningFTPEntryParser(); } public FTPFileEntryParser createNetwareFTPEntryParser() { return new NetwareFTPEntryParser(); } public FTPFileEntryParser createNTFTPEntryParser() { if (config != null && FTPClientConfig.SYST_NT.equals( config.getServerSystemKey())) { return new NTFTPEntryParser(); } else { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new NTFTPEntryParser(), new UnixFTPEntryParser() }); } } public FTPFileEntryParser createOS2FTPEntryParser() { return new OS2FTPEntryParser(); } public FTPFileEntryParser createOS400FTPEntryParser() { if (config != null && FTPClientConfig.SYST_OS400.equals(config.getServerSystemKey())) { return new OS400FTPEntryParser(); } else { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new OS400FTPEntryParser(), new UnixFTPEntryParser() }); } } public FTPFileEntryParser createMVSEntryParser() { return new MVSFTPEntryParser(); } } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPFileFilter.java0000644000175000017500000000232711466231525026523 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; /** * Perform filtering on FTPFile entries. * @since 2.2 */ public interface FTPFileFilter { /** * Checks if an FTPFile entry should be included or not. * * @param file entry to be checked for inclusion. May be null. * @return true if the file is to be included, false otherwise */ public boolean accept(FTPFile file); } commons-net-2.2/src/main/java/org/apache/commons/net/ftp/FTPFileFilters.java0000644000175000017500000000317511466231525026710 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; /** * Implements some simple FTPFileFilter classes. * @since 2.2 */ public class FTPFileFilters { /** * Accepts all FTPFile entries, including null */ public static final FTPFileFilter ALL = new FTPFileFilter() { public boolean accept(FTPFile file) { return true; } }; /** * Accepts all non-null FTPFile entries */ public static final FTPFileFilter NON_NULL = new FTPFileFilter() { public boolean accept(FTPFile file) { return file != null; } }; /** * Accepts all (non-null) FTPFile directory entries */ public static final FTPFileFilter DIRECTORIES = new FTPFileFilter() { public boolean accept(FTPFile file) { return file != null && file.isDirectory(); } }; } commons-net-2.2/src/main/java/org/apache/commons/net/daytime/0000755000175000017500000000000011617452467024130 5ustar twernertwernercommons-net-2.2/src/main/java/org/apache/commons/net/daytime/DaytimeUDPClient.java0000644000175000017500000000605311354710167030073 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.daytime; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import org.apache.commons.net.DatagramSocketClient; /*** * The DaytimeUDPClient class is a UDP implementation of a client for the * Daytime protocol described in RFC 867. To use the class, merely * open a local datagram socket with * {@link org.apache.commons.net.DatagramSocketClient#open open } * and call {@link #getTime getTime } to retrieve the daytime * string, then * call {@link org.apache.commons.net.DatagramSocketClient#close close } * to close the connection properly. Unlike * {@link org.apache.commons.net.daytime.DaytimeTCPClient}, * successive calls to {@link #getTime getTime } are permitted * without re-establishing a connection. That is because UDP is a * connectionless protocol and the Daytime protocol is stateless. *

*

* @author Daniel F. Savarese * @see DaytimeTCPClient ***/ public final class DaytimeUDPClient extends DatagramSocketClient { /*** The default daytime port. It is set to 13 according to RFC 867. ***/ public static final int DEFAULT_PORT = 13; private final byte[] __dummyData = new byte[1]; // Received dates should be less than 256 bytes private final byte[] __timeData = new byte[256]; /*** * Retrieves the time string from the specified server and port and * returns it. *

* @param host The address of the server. * @param port The port of the service. * @return The time string. * @exception IOException If an error occurs while retrieving the time. ***/ public String getTime(InetAddress host, int port) throws IOException { DatagramPacket sendPacket, receivePacket; sendPacket = new DatagramPacket(__dummyData, __dummyData.length, host, port); receivePacket = new DatagramPacket(__timeData, __timeData.length); _socket_.send(sendPacket); _socket_.receive(receivePacket); return new String(receivePacket.getData(), 0, receivePacket.getLength()); } /*** Same as getTime(host, DaytimeUDPClient.DEFAULT_PORT); ***/ public String getTime(InetAddress host) throws IOException { return getTime(host, DEFAULT_PORT); } } commons-net-2.2/src/main/java/org/apache/commons/net/daytime/DaytimeTCPClient.java0000644000175000017500000000617611354710167030077 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.daytime; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import org.apache.commons.net.SocketClient; /*** * The DaytimeTCPClient class is a TCP implementation of a client for the * Daytime protocol described in RFC 867. To use the class, merely * establish a connection with * {@link org.apache.commons.net.SocketClient#connect connect } * and call {@link #getTime getTime() } to retrieve the daytime * string, then * call {@link org.apache.commons.net.SocketClient#disconnect disconnect } * to close the connection properly. *

*

* @author Daniel F. Savarese * @see DaytimeUDPClient ***/ public final class DaytimeTCPClient extends SocketClient { /*** The default daytime port. It is set to 13 according to RFC 867. ***/ public static final int DEFAULT_PORT = 13; // Received dates will likely be less than 64 characters. // This is a temporary buffer used while receiving data. private final char[] __buffer = new char[64]; /*** * The default DaytimeTCPClient constructor. It merely sets the default * port to DEFAULT_PORT . ***/ public DaytimeTCPClient () { setDefaultPort(DEFAULT_PORT); } /*** * Retrieves the time string from the server and returns it. The * server will have closed the connection at this point, so you should * call * {@link org.apache.commons.net.SocketClient#disconnect disconnect } * after calling this method. To retrieve another time, you must * initiate another connection with * {@link org.apache.commons.net.SocketClient#connect connect } * before calling getTime() again. *

* @return The time string retrieved from the server. * @exception IOException If an error occurs while fetching the time string. ***/ public String getTime() throws IOException { int read; StringBuilder result = new StringBuilder(__buffer.length); BufferedReader reader; reader = new BufferedReader(new InputStreamReader(_input_)); while (true) { read = reader.read(__buffer, 0, __buffer.length); if (read <= 0) break; result.append(__buffer, 0, read); } return result.toString(); } } commons-net-2.2/src/site/0000755000175000017500000000000011617452470015314 5ustar twernertwernercommons-net-2.2/src/site/resources/0000755000175000017500000000000011617452467017334 5ustar twernertwernercommons-net-2.2/src/site/resources/images/0000755000175000017500000000000011617452470020573 5ustar twernertwernercommons-net-2.2/src/site/resources/images/net-logo-white.xcf0000644000175000017500000004536110034336445024143 0ustar twernertwernergimp xcf fileæQBBK/ gimp-commentCreated with The GIMP¦¤ÃëI4netÿ     ¤&JN4b4rHHH-þU0ý8ª0ýƪ/üUÿª.ûâÿª-úâÿÿªüqúUªª8 ý8qªªýUþqÿÿþÆUUöÿÿªUâÿÿþù8ÆÿªªâÿÿþþÆÿÿüÆÿÿüªUÿÿþUûUÿªþqÿÿþªûªÿÿªÿ÷ªUÿ8qÿÿþÆüUÿÆþqÿÿþqûªÿÿªùªÿÿââþÿÿþüâÿ8ÿûªÿÿªûªÿÿÆþ8ÿÿþUüqÿâþªÿÿþUûªÿÿªûªÿÿªÿþUüÆÿÆUUþÆÿÿþªûªÿÿªûªÿÿªÿþUÿþªûªÿÿªûªÿÿªÿþUûUÿÿªûªÿÿªûªÿÿªÿþUûUÿÿªûªÿÿªûªÿÿªÿþUûUÿÿâûªÿÿªûªÿÿªÿþUþUÿÿþûªÿÿªûªÿÿªÿþUþ8ÿÿþ þ8ûªÿÿªûªÿÿªÿþUÿþý8ûªÿÿªûªÿÿªÿþUþªÿÿýâýÆ8ûªÿÿªûªÿÿªÿþUþ8ÿÿýâ8ýªÆûªÿÿªûªÿÿªÿþUþªÿÿ÷ÆqUUâÿ8þªÿÿúªqûâÿÿÆþÿÿþqþªÿÿþUþUÿÿûâªââþqÿÿþUþªÿÿýâ8þªÿÿþUþâÿÿü88ªªû8qªª÷8ªâÿÿâùªÿÿªR8Drop-Shadow#2Ì     KNR8f·R8z`ú63þ.üþú  ù  ý ù ý ÷ û ò ô   ø è ð ã !##ü" ð ÷ç #&)+,+*'#ï  !!÷ í !"#%(+.133ü1-(î "$&'())÷('&#!ç!#$%&'(*+-0369;;:84.í !%),.01122Û10.,)&$!  !#$&(*+-./01358;>ABCB>:4ï "',04689::Û98641.,)(''()*,.02356789;=?BEGIIGD>8í  '-37;>?@AA÷@><96410//ç023579:<=>?@ACFHKMONLHB;î $,29>BDFGGHGøECA><9877ç89:<=?@BCDEFGIKMPRSRPKE=í  (07>CGIKKLLøKJHFCA@??è@ABCDEFGHIJKLNQSUUTRMF>ï "*3:AGKMNNOPùONLJHGFFGHíIJJKLLMOPRUVWVSNG?ï $,5=DJMOPPóQRSTSSRPONMMLLKLòMNOQSUVWVSNG>î %.6?FKNPQPPëQSTVWWVUUTSSRRQPOMLLKKLôNPRTUVURMF>Ô %.7?FLOPQPOOPQSUWYYZYYXXWWVTSQOMKJJIIóJKMPRTUTQLE=í &.7@FLOPPONNöPRUXZ[\]]\\õ[YXURPMKIGFFóGHKMPRSSPKD<ã &/7?FKNONMLLMNQTXZ\^__æ^\ZWTPMJGEDCCDEHKNPRQOKD<ñ %.7?EJMMÖKJJKMPSWZ\^_`aa``^\YUQMIFCA@@ABEHKNPPNJD<á %.6>DIKLKJHHIKNQUY\^_`aaç_]ZVRMIEB?>=>?BEILNNMIC<à $-5=CGJJIHFFGILPTWZ\^_`aaç`^[WSNIEA><;;=?BFILMLHC<í $,4;AFHHGFDDõGJMQUXZ\]^__è][XSOJEA>;:9:=@DGJKJGB<Å #+3:?CEFECBABDGJNRTVXYZ[\]]\ZWTOKFA>:988:=ADGIHFA;Þ !)07=@BBA@?>?ACGJMPRSTUWXYYéXVSOJFA=97667:=ADEEC?:í '.49=>?><;;Ú=?BEHJLMNOPRSTUTSQMIE@<854347:=@BB@=8Ü $*058::987678:=@BDEFGHIKMNOOëMJFB>:63100258;<=<94ñ  &,0344Ö32123579;=>>?@ACEFHIHGEB>:62/-,,-02577640ó "'*-..þ-,,Ú-/124566778:<>?@A@><951-*('&(),.010.+æ !$&'('&&%&'()+,--.ä/1246788752/+(%"!!"#%')*)(%ò  !! ú !"#$%%&ê()+-.//.-*(%" ""ý!ð ûú!"$%&&ø%# üþó üðüþó þûî ÷  û ù    þ ùþ     ü ü þþþ   þ  ððð ù ø ÷ö ö õ õ õ ô# ô(! ô,% ô0(  ô3*" ô4+# ô5,# ô5,# ô5," ô4+" ô4*! ô3*! ô3*! ô3*" ô3+" ô4+# ó4+# ó4,$ ó3+# ó1*# ó/(! ó+% ó&! ó! ô ô õ õ ö ùø  h)×commonsÿ     g׃Óßן¤¢I€€€ý8qªªüUý8Uªªýq8üq8ýqâÿÿýª ýqâÿÿüâ úUªÿÿUõ8âÿÿ8ªÿÿþUôUâÿÿ8qâÿÿþUüqªÿÿþUúUÿÿÆþÆÿÿþUþqÿÿþUþªÿÿþªüªªÿÿüUÆûUÿÿâþqÿÿþâþUÿÿþUþªÿÿþªþqÿÿùªÿÆ8ÿÿþþÿÿþUþ8ÿÿþÆ þâÿÿþUÿþªûâÿÿþÆÿÿþþÆÿÿþU þ8ÿÿþâÿþÆþqÿÿþ8úâÿÿUþ8ÿÿ þâÿÿþqÿþªþÆÿÿ þþªÿÿþÆ þÿÿþÆÿûªÿÿþÆÿþª þ8ÿÿÿûªUÿÿþªþÿÿþª ÿþ8ÿûªÿÿþªþUÿÿþª þâÿÿþUÿûªªÿÿþªþUÿÿþª þªÿÿþUÿûªªÿÿþâþUÿÿ þªÿÿþUÿûªªÿÿþUÿÿ þªÿÿþ8ÿûªªÿÿþUÿþU þªÿÿÿûªUÿÿþÆ þ8þâÿÿþ þªÿÿþÆÿûª8ÿÿþ8 ýUâþÿÿþÆ ÿþqÿþªþâÿÿýâ ü8ÿ8þ8ÿÿþ8 þÿÿþÿþªþqÿÿýªü8âÆþÆÿÿþ þqÿÿþÿþªþâÿÿýâ8ûqÿÿþÿÿþûâÿÿâÿþªþUÿÿýâUUúâÿÿUþUÿÿþÆúqÿÿâÿþªþUÿ ÿþUþUÿÿþªúUÿÿâþÿÿþªþUÿ ÿýâU ý8âÿÿôâqUÆÿÿÆþqÿÿþýÆÿÿý ýqâÿÿýÆ8üUqÆÿÿýâªýUªªýUý8qªªýU ª€€€ù8qªª8ùUªª8 ý8ùUªªqùUª8ÆÿÿýÆýqâÿÿýÆúqÆÿÿýqâÿÿþýÿÿþÿÿþÆý8âÿÿþâü8ÆÿÿýÆÿÿþqþqÿÿúâUUÿÿùqUÿÿªUUýâÿÿþqüƪÆÿÿöUâÿÆqUUÆÿÿùªÿâUUþ8þÿÿúâUÿªýâÿÿþâþÆÿÿûªÿþqÿÿûªÿq þÿÿþªþqÿÿþ8þUÿÿþUþâÿÿþU þ8ÿÿþÆþ8ÿÿþUþUÿÿþqþÿÿþq ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU ÿþªÿþªþUÿÿþUþUÿÿþU þÿÿþâÿþÆþqÿÿþUþqÿÿþ þqÿÿþUþqÿÿþþÆÿÿþÆþÆÿÿýâøU8qÆÿÿ÷ªU88qÆÿÿ÷âU8UâÿÿüÆUüUâÿÿóâUUª8qª ªûqqª ªýq8ª ª ªü8ª€€€ªýqüUªªýUü88ýqªªþUÿþ ý8Æÿÿýª8 õ8âÿÿUÿÿýâUÿþ ùÆÿÿÆUýUÆÿÿþªüUªâÿÿûU8âÿÿûUªÿÿþú8âÿÿªþUÿÿýâªÿUøÿâUUâÿÿþâþUÿÿþúâÿÿªþUÿÿýâþªÿÿûâÿªþÆÿÿþUþÆÿÿþâþâÿÿþþÿÿþªþUÿÿþUþ8ÿÿþªþÿÿþqÿÿþª þâÿÿþ8þUÿÿþqþâÿÿþâþUÿÿþUþâÿÿþU þÿÿþÆþUÿÿþUþªÿÿþUÿÿþUþUÿÿþ þ8ÿÿþþUÿÿþUþªÿÿþUÿÿþUþªÿÿ þâÿÿþUþUÿÿþUþªÿÿþUÿÿþUþÆÿÿ þªÿÿþþUÿÿþUþªÿÿþUÿÿþUÿ þÿÿþªþUÿÿþUþªÿÿþUÿÿþUÿ þUÿÿþªþUÿÿþUþªÿÿþUÿÿþUÿþU þUÿÿþªþUÿÿþUþªÿÿþUÿÿþUÿþU þUÿÿþþUÿÿþUþªÿÿþUÿÿþUþªÿÿþª þUÿÿþUþUÿÿþUþªÿÿþUÿÿþUþÿÿþâ þUÿÿþþUÿÿþUþªÿÿþUÿÿþUþ8ÿÿþ þªÿÿþÆþUÿÿþUþªÿÿþUÿÿþUþâÿÿþ þÆÿÿþqþUÿÿþUþªÿÿþUÿÿþUþqÿÿþâ þÿÿþâþUÿÿþUþªÿÿþUÿÿþUþÆÿÿþqþÿÿþ8þUÿÿþUþªÿÿþUÿÿþUýâÿÿþþÿÿþUþUÿÿþUþªÿÿþUÿÿþqýâÿÿýâúâÿÿUþqÿÿþUþâÿÿûÆÿÿþÆýªÿÿõ88ÿÿâUþâÿÿþÆþUÿÿüqâÿÿûÆqUý8Æÿÿýâqü8qâÿÿ÷âUUªÿÿ ªþ8ýUªªýq8 þqª ªþ8ªªVVV ýUªªúU óÿÿ⪪ÆÿÿªÆÿûÆÿâ8ý8Æÿÿûªÿÿ8üâÿÿû8ÿÿÆü8ÿÿûÿÿªýªÿûªÿÿâýUÿþªÿÿþqþÿþqÿÿþqþ8þÿÿýÆ8þÿÿýÆ þªÿÿý þÿÿýâq ý8âÿÿýâ þqÿÿýâU ýÿÿýâ ýªÿÿþýªqþUÿÿþ⪠þÿÿýªÿþÿÿüªÿqÿþÆûªÿâþÿÿþqûªÿÿªûÿÿªþªÿÿýÆ8öÿÿªÆqøªÆªªÿÿ⪪ÿýâqªþ8ý8ø8UªªUk 5õ8 Drop-ShadowÌ     ÿÿÿúÿÿÿú9 “õ8 ¯HöIõ8 Ë+5È@ŸU  þþþþ øúùù ô  í     ù  ò ÷ ø ø ×  øî ÷ôøí  !#$%%÷$# ó!"##$%%ù$" Ð  "$&')*+,,+*'%"!#$&'())*+,,ú*(&#!é !$&(*+-.0122ç1.,)&#! !#$'(*+,--./02344ú31.,)×  #'),-/01346787642/,)(''(*,./11223û568:;;û9752ß !&*-/12334679:;<;9742/..è0245677665668:=?ABCB@=:ð "',024566Ù78:<=>>=;97544579;<==<:9878:>á=;:99:<>ABCCB@=;988:=@EIMOPONKâ &-38;==<:8655679;<=>==å>@BEGIIHFC?;9779<@FKPSUVTRÅ $+29=@AA>;853223579:;<==?ADGKMOOMJE@;7556:?EKQVZ[ZXé  (08>CEED@<830..Ü024689;=@CGLPSTSQLGA;63237=CKRX\__]à $,5=CGJIGB=72.+))*,.1369<@EJOTWXWTOHA:40/04:AJRY^abaè '09AHLNMID>71+(%%Ý'),/26:@FLRW[\[WQIA93.,-17?HQY_cddà  )3=ELPRPLF?70*%"!!"$'*.38?FMTZ^_^YSJA92-*+/5=FOX_dfeà ",6@HOTUSOIA81*$!!#'+06>ENU\`a`[TKB91,))-3;DNW^cffà #-8BKSWYWRLC;2+% !$(.55-'" #'-471,)&%&'*.3:AJRZ_bc`ZSJA93/-/28@HOUY[[à !+6ALV]bdd`[TME>83/,*)*+.38?GOV\`a_ZTLC<610149@FMRUWWã (3>IS[aeec_ZSLE?:52/--â/27=DKRX\]\YSME>94336:?EJOQRRà %/:EOX_ceeb^XRLFA<741/./149?FMSWYYWSMF@;7557;?CGKLMLÅ !+5@JS[`dec`\WQLFA<741/./15:@FLQTUSPLGB=9778;>ADFGGFÏ &0:DMU\`bba]YTOID?:51.-,.04:?EJMOOMJFA=:88÷:<>@AA@?Ä !*3=FNUZ]_^\YUPJE?:50-*))+.27=AEHIHFC@=:87789:;;:98Ð $-5>FMRVYYXVRNIC>83.*'%$%(+059=@BBA?=:8755ü421Å &-5=DINPRQPMID?:4/*%" !$(,048:;;:875321100/.,+*Ø %,3:?CFHIHEB>94/*%! $(,/133ò10/.-,+*('%$#Ö $*059<>?><:62.)$  #&)+,,ò+*)('&%#" È !&+.134431.*&"!#$%%$$#"! É !$')**)'%" ò   õ ö ö Ú   õ ô é   ö  ö  ÷ ø øù "    þü      ú  ô      ø ø   ë  üø  ÷ ó ûöø  öî !!û"#$$%%û$#"!  !þ"##ø!ö !!ð"#$%!$&'))*û+,-.//õ.-,*))()*+,,ì*(%!"$&())**ú+,-.÷ #&*-/12334ü57899ú8764211ü23455í31-*&" #'*-01233í4567'%%&(+/369;<==<<ó=>@ACCDCB@><::ý;=>>ì=:62.)&$$%'+/37:;<=<<ñ=>@/--.037<@CEFFþEDDûFGIKMMÞKIGECAABCDFGFEC?:51-+*,.27<@CEFFEDDEFH86558;@DILNOOMLKJJLNPSUVVTROMJHGGIJLMNMKGB=841125:?DILNONMKJJKLN@>==?CHLQTVWVTRPOOPRUX[\]\YVSPMLLMOQSTTRNID?:778;@FKPTVVUSQOO€ÅQSHEDDFJNSX[]][YVSRQRUX\_aba_\XTQONOQTVXXWTPJE@=<=@EKQWZ\\ZXUSQQSVOLKJLOTY]`ba_\XUSRSUY^adfec_[VRPOPRUX[\[YUOJEA@ADJPV[_``^ZWTRRTWUSQPQTY]adedb^YURQRUY^bfhgea\WSONOQUY\^^\XSNHECDHMSY_bcb`\WTQQSV[XUU€;X\`dggfc^YTPOPSW]bfhhfb\WRNLMPTX\_`_[VQLHFGJOU\aded`[WRPOQT_\YXY[^bfhhfb]WRNLMPU[`ehhfb\VPLJKNRW\_a`]YSNJHHKPW]befd`[UPMLNRb_\[[]`dgiifb\UPKIJMRY_dggea[TNJHHKPU[_ba_ZUPKIJLQW]beec_YSNJIKOca^\\^adgiheaZTMIGGJPV]befd`YSLHEFINTZ_ab`\VQLJJMRX]beeb^WQKHGHLda_]]^adghhe`YRKGDEHMT[`dec^XQKFCDGLRY^ab`\WQMJJMRW]bdda\VOIFDFJda_]]^adghgd^XPJEBCFLRY_cdb]WPIDBBEKQX^aba]XRNKKMRW]adc`[UNHDBDHc`^\\^`cfgfc^WOICAAEJQX^bca\VOHCAADJPW]aba]XSNKKMRW]acc`ZTMFBABG`^\[[]_cegfc]VNHC@@DJQX^aba\UNHB@@DIPW]aba^YSOLLNRW]acc_ZSLFB@BF][YXY[^befeb\UNGB?@CIPW]ab`\UNGB@@CIPW]aba^YSOLLNRW\`cb_YRKEA@AEZXVVWY]`deea\UNGB?@CIPW]ab`[UNGB@@CIOW]aba^YTOLLNRW\`bb_YRKEA?AEUTRRTW[_bdda[UMGB?@CIPW\`a`[UNGB@@CIOV\`ba^YTOMLNRW\`ba^YRKEA?AEPONNPTX]acb_[TMFB?@CHOV\_`_ZTMGB@@CHOV\`a`]YTPMMNRW\_a`]XQJEA?AEJIIJLPUZ^``^YSLFA??CHNU[^_^YTMGB@@CHNU[_`_\XSOMLNRV[^`_\WQJD@?ADD€2EHMRW[^^\WQKEA>?BGMSY\]\XRLFA??BGMSY]^][WRNLLMQUY]^]ZUOIC@>@D>=>@CHMSWZZXTNHC?==@EKQVYZXUOJD@>>AEKQVY[ZXTPLJIKNRVY[ZWRLFA>=>B778:>CHNRUUTPKE@=;;>BHMRUVTQLGB><<>CHMRUWVTPLIGGHKOSUVVSOID?<;CHLOPNKGB>:88;>CHLOPPNKHECCDFJMOPPMID?;878;))+.27BFHIHEA=96446:>BFHJIGEB?>>?ADGIIÂGC?:64347"#$'+059=?@?<952/..037;>@A@>:731//147;>@AA@=;9878:=?AAí?<841/./1!$(-1466×41.+)((*,/2578752/,*))*-035788753100134688È630-*)()+!%(+-.-+)'$#""#%(*-./.,*(%$##$&(+-.//.-+*))ü+,.//ú-+)&$""î$!#$%$#! ë #$%&%$" !#$&&õ%$#"!!"#$%&&ú%#!î óû÷úõ õûûî ü  û õ û  ó                õ ü 9 þ,  ú   ô û üþþ     ù ÷  þ  ù ÷ üþö õ ú  é ö  õ ùõ%%û$#"!  ü!""##ö"   óë !"#//õ.,+*)(()*+,,ç+)&# !"#$%%ù$#!ô"$')+,,899õ875321122455Ç42/+'" "$%&'()*+,--,+*(&#"!!"$'*.13566BCDCCA?=;::ü;<=>>å<84/*&" "%')*+,-./012344Ê20.,*))*-037;=?@@JLMMLKIFDBAABCEFGFDA=83.)&%%&(*,.01122Ã34689;<<;975321358=AEGIJJQSUVUTQNLIHGHIKMNNLJE@;61.,,-/2456766è5679<>ABCCB@><::;>AFJNQSSÚVY[\\[XUROMLLMORSTSQMHC>964468:;==<;988‰9;>BEHJKJIGECBCFINRVY[[ZZ]`bba^ZVRPNNPRUWYYWTOJEA><=>@ACCB@>;9889;?CHLOQQPOMKJKMQUY]`aa_[_cefeb^YUQOOQSWZ\]\ZVQLHFDEFGII€ùGD@=9778;?DIOSVWWVTRQRTW[_cefebZ_dghgd`ZUQONPSV[^``^[WSOMLLMOPONKGB=86458=CIPUZ\]\ZYWWY\_cghigdY^cghhe`ZUPMLNQUZ^acb_\XUSRSTUVURNIC=74236;AIPW\`aa`^\\]`cfikjhdW]bfhhe`ZTOKJLOTY_bdec`][YXYZ[[ZVQJC<61/028?GOW^bdedb``acehklkhcT[`eggd_XRMIHIMRX^cfgfda_^^€=`a`^ZTLD<50--055.*(*.5>HQZaeggfeddegijjhc]LSZ_bb_ZSLFA@AFLS[bgijjhggÂijkkid]TJ@70+)+/5>GPX_ceedcbbdfhiigb\LSY_bb_YSLEA@AELS[afijihffåhijjid^ULB92-+,/5=FNV\`bba``Ãbdghhfb\KRY^aa^YRKEA?AEKSZafhihfeddeghigd^VMD<50-.16=EMTY]^^]]…^`ceggea[KRY^aa^YRKEA@AEKSZ`eghfdbaabdefeb^WOF>830037=DKQVXZYYXYZ]`cefd`ZKQX]``]XRKEA@AEKRY_dffdb_^]^_abb`\WPHA:63358>CINRTTÂUWZ]addc_ZJQW\__\WQKEA@AEJQX^bcca^[YXYZ\]^]ZUOIC=86569=BGJMNONNÃPRVZ^aba^XIOUZ]]ZVPJDA?@DIPV[_``]ZWTSRSUWXXVSNIC>:878:=@DFHIHHÛJMRV[^_^[WGMRWYYWSMHB?>?BGMSX[\[XUQNLLìNPQRQOLGC?;9889;>@ABBAÂBDHLQVY[ZXSDJOSUUSOJE@=<=@DJOSVWVSOKHEDEFHIKKJGDA>;97789:;<<;::Ê<>BGLPTVVSO@EIMOOMJE@<989<@EIMPPOLHD@><<=?ABCCB@>;976556ý5433’57;@EJMOOMJ;?CGHIGD@;85457;?CFHIGDA=9654568:;<;:9754221100/.-,+,.049>BFHHFC48?@><-14677641.+*))+.13677530,)&%$$%'(*+,,Ú+*)('&%$"!  "&*.256764&)+-./.,)'%##é$&)+-..,*(%" "#$%%â$#"! #&),-.-+!#$%%¢#" !#$%%$" !#$%$#ä ûýú  û î ú û   þù û   ð  ü      þ  ú ô üþ   ! ˜ ˜ ˜×*   þþ    ù÷÷ ú     öö ù ô ì ñ þ#$$%ì$" ñ -.Ù-,)&"  678ö753/+'"ø!#$%&&ï%$#! @?ê@AA@?<84/*%" !#%(*,--í,+*(&# ýIHGGþHIIÙGEA<71,)&%&'*-/1344321/-*'# ýQPNNÖOPPOMJE?94/-,,.1479:;::8641.*&! æWUSRRSTUVVTQLF@;632247;>@AAì?=;851-(# ü\YVUUÖWYZ[ZWRMGA<978:=ADFHHGEB?<840*% Ð_[XVUVX[]^^\XRLFA><=?BFJLNNMKHD@<72,'! Ð_[WUTUX[^`a_\VPJEB@ACGKNQSSRPMID@:5/(" Ð_ZVSRSVZ^aba^YTMHDCCFINRUWXWURNID>81*$ Ï^XSPOQTX]acc`\VPJFDEGKPTXZ\[YWSNHB<4-& Ï\VQNMNRV\`cca]WQKGEEGKPUY\^^][WSMG@91)" ÏZTNKJKOTZ_bcb^XRLGEDFJOTY]`aa_\XSLE=5-% ÏYRLIGIMSY^bcb^XRLGDCDHMRW\_bcb`\XRKC:1)  ÎWPJGFGLQX^bcb^XRKFBABEJOUZ^acdc`\WPH?6-$ ÎVOIEDFJPW]acb^XQKEA?@BFKQV[_bddc`[UMD;1( ÎUNHDCEJPV]acb^XQJD@==?CGMRW\`bdcb^XQH?5+" ÎUNHDCEIPV\acb^XQJD?<;;:;=@EINSX\_aa_[UMD:0& ÎTMGDCEIOV\`bb^XQJD>;99;>AEJNSW[]^]ZUNE;1( ÎSMGDCEIOU[`ba^XQJD>;98:<>BFJNRVYZZXSMD;1( ÎRLGCCDINUZ_a`]WQJD>;989::8789:@CFIJJIE@:2*" ÎJEA?>?CHMRUWVSOJD?;75445678:<>@BCCB?:4-& êEA=;:BFHJIGC?;630/..è/0123455430,'" ê95311247;>@AA?<840.+*))*+ë,--..-+)%! ë1.,**+-025787630-*'%$$%&î'&%$! ü)'%$$ð&(*-./.-+(&#! ð é! !"$%&%$#!ñ üñò õøó þ  ù ù    ô þ       û  þ  øz=,d Backgroundÿ     ÿÿÿÿIµ,dIÕJÍJÙJå,dJ J'J7JGJWJgJJJ­J½ÿÿÿùÿûúôÿþÿ:ÿý Åÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ&ÿüþýüÿ>ÿýþýÿ>ÿüþÿüÿQÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ0ÿ0ÿ0ÿ0ÿ–2K% commons-net-2.2/src/site/resources/images/net-logo-white.png0000644000175000017500000002507610034336445024150 0ustar twernertwerner‰PNG  IHDRæQÆ¥ÚvbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ/+œÝÍd IDATxœí}{tUÕñÿç&!øO×RyûW)H@…$ F[QIHj©ÖvUW«åM—µ•*‚«€(—€•Æ €¥Õ‚D! Ø ò®y¡ $÷¹àçÌ™}î µýÅoï¬uÖ}íÙ{öÌ|ffïó¸cŒA'ˆ7ï$«‹@§ÇëJcO¢cH^?>¿ß:+«Öþ|d¶ïKëW޾öLDæG7¶þÿ“>ä§»@¢Àܲe‹s]|ñÅ(,,DQQrss=‚zûê³6Ù@ €-[¶àÈ‘#¨®®výVTT„¢¢"ºú÷› M¡ xõÕW1tèPyúÛºu+¶lÙ‚­[·:s,//wm£U«VaÛ¶m8r䈋·¨¨Èj8)¯”{ëÖ­¨®®ÆÜ¹sÕ¹WWWcë֭ΘEEE¨¨¨ðØCÓömÛ\º&Þ¼¼¼„äµÙ—ú'=’l——çŒÏõâžtSQQáØ’ú$?";@yy9***âŽççCRßPQQ¡C‡::¿ï¾û0wî\kðöûì¼7qhÞ¼y&//Ïð=ÊËËÍáÇM0´¡PÈ„B!‡M$1ÑhÔD£Q3wîÜ„ÆÈËË3“'Oîô8‘HĬ\¹ÒTTT8}­\¹ÒD"‡M(2›7o6………Ö± Í¡C‡L{{»çxì±Ç|å'ÞŽŽ_GG‡éèèpɇÍÇlæÎkŠŠŠœ>HV’÷‰'žðsÒ¤IžñÚÛÛÍÁƒͤI“|õL¼th²ry¹-ß{ï=—Üñ|fÓ¦M& ºÆÓìIs¯­­5S¦LqÍý•W^qôò¯ýËLž<ÙׇV¬XáÑ‹Í4¿©S§ºú¨¨¨0®¹–——;>”¨_’ޢѨ‰Åb&‹cŒ±sË–-®ÉO:ÕÔÖÖ: 8|ø°)//÷L¼²²Òœ9sÆsœ={ÖQ úòË/»Æ˜2eŠÙ¼y³ …B& šÃ‡›Ç\uÀxã:tÈ<þøãªŒÌË/¿ìÈÏQé(((0_~ù¥9}ú´9}ú´yûí·MnnnB¼¹¹¹æË/¿ô$wMM™4i’58¬‡ö ü˜3gŽKÞ9sæ$ÄÀLœ8Ñ*«´e(2ü±ËI‹ŠŠÌÊ•+!{k²—••ùÚò¥—^2åååÖ@D¶|÷Ýw ðÌ‹/¾èèåôéÓ¾ó#™óòòÌæÍ›]2 šM›6yæÕÞÞnΞ=ëôe¿ œ*0ÿò—¿¸üé§Ÿº ƒÎÀžI/_¾Ü|ñÅÎqêÔ)×äÏž=k{ì1+Pxÿ¤¬²²2Ï8¥¥¥Öq&NœhÊÊÊ̘1cTìX±Â8pÀ‘?77×L˜0Á¼ð fùòåfüøñ*߬Y³L[[›Yºt©óÝèѣͲeËÌòåË^ °³fÍ2'OžtŸþ¹ùâ‹/LAA)++SõI†^±b…ÓoAA™={¶3æ!CT¾úúzÓÖÖfFíÌsܸq.yKKK­¼š¬¤g²¥Dyy¹ËW(ë’=_|ñE5p}ôÑGª=ËÊÊâÚ²²²ÒeÇx¶ÈÍÍ5mmmÎ!çG¾ÊǤìn›‡D-°ñ &«˜”yyyN Å9sæŒùòË/Í©S§ÌìÙ³=“ÎÉÉ1­­­¦¥¥Å´¶¶šÖÖVÓÖÖæLü…^ð(–GêÿôéÓŽ‘>ÿüsǹø1zôhg çäÉ“Ÿ-SЇ bÖ¯_oNž<éôÑÒÒbZZZÌîݻչ=÷Üs€)))1;vì0'Nœpަ¦&ÓÜÜlvíÚerrr<¼¼í‰'Lss³£'R›¼ãÇ7{öì1mmmyyäß½÷ÞkJJJ 3sæLUÖææfóüóÏ«¼ZûÖÖVGÇûöís9ä˜1c\%0·ç©S§[.[¶LÕíîÝ»=öä€Ñ4_ZZjêêê477›¦¦&ÓÔÔdìá{î¹ç|ç·açmAA“ý4?=uꔫ½Ð$è9@%8]›?[¶lÁ°aÃè#>ùääääÀƒX,†X,æ¼§×#GŽ ??’–,Y‚’’_oìØ±#GŽtÚàí·ßv>U^;EÇ AƒpôèQu,¾!‘’’‚””ú.|ÑEu“2Ž=K—.UçF4sæL,Y²Ä3¿Q£FaÑ¢EÎg>G’aÉ’%˜9s¦‹oÍš5¸òÊ+Ï$#É›ššŠ5kÖà®»îòŒ¹téRÜzë­Y¹¼C† ñè-Z„Q£FùÊ{ë­·bûöíN›ììl|ðÁ.ëÀÑØØè´9pà€³ "e”ï§OŸŽÅ‹»ä,))Á’%K\rј@Àª›çŸ%%%._%Œ1رcFíâá6äcÐüf̘gžyPZZŠÊÊJÒ˜ð‹_ük×®Ess³k,©;þ^~€b4Æà¶Ûns:š2eŠÊh4ŠX,†h4ŠH$‚H$‚p8Œp8ŒÌÌL\uÕUEåçç# ¹Žp8Œ?üá®v÷Þ{¯Ó'?Âá0B¡k¬p8ì(ŠÓÃ?ŒP(„`0ˆ`0èðÒ˜¡P(Uò <K–,qÚ/ 1bÄÏxƒ ÂüùóÑÑÑa=‚Á °>ýôSWÿÔ–ËF=|<òFå’WÊÚÑÑá zD<ð®¿þzUF.àAƒ\|ÇŽsõÏu …ðÔSO¹@YZZŠÌÌL«=é »<ôÐCÈÎÎvùÆo`ëÖ­®±8¦›™3gâæ›oVõAsëׯ²²²\|Û·oWmAcñ×þóŸÎ\8hn‘H¡PÈ ~Üÿ4}D£QW2ˆ ˜óçÏGCCƒ#Hyy¹ÆX,¦ BŠ^´h‘KÁ .DïÞ½=ÆØ¶m›+"碖ìš,ÿ.??ßcÌcÇŽáÙgŸuÆáÎó¸S (++Ëù  Iïûõëçq„ŒŒ _PRýû÷÷ð®[·ÎêìV`fddx‚ˆ®Ë/¿ÜÃÛ³gOלèhoowõ1`ÀïÚµk=cœÏ>û¬«mII‰ˆ`Ôæ–[nñŒ9sæL—ý¸Œ‘HÄÓ¾wïÞŽ^:(?îiÃß` ±± .tù&Ÿ'Í‹£¦ L—Vý¤çúꫯº„2dˆ Ñå¼Ã^½z¡¶¶ÈÊÊ‚1ápØs®Q–„W^y¥GÑZ¹L2R#GŽÄ²eË\|ëÖ­ÃwÜáŒÅË*ä8”‘åœøXÚ¹¬X,æ1W–%œ¢Ñ(:::\<©©©ÎAÑXããò’Ì\Þ@  òF"tttxÎÊ2*{xÃá°K^*a×­[‡cÇŽ¹Ú8¡PÈ)÷H>é|À×ö¼é¦›ðüóÏ»úÙ¹s'>ûì3'Ãq95#‘‚Á £©"i/ƒÜ¥fjj*"‘òóóñ·¿ýÍi;}útÄb1üêW¿r•Ì|)dŒAUU•£¹´¢þù˜$/“ÓŒ1hhhpˆ-,,t£‰Òy•àÉÈÈ@$ñÔß$À›o¾éR e-^’+–+xĈ`îÚµËe4 NI.šÍSÓÌP(ä*C¸ò9@%c …\z HKKs¸˜6ymÀ¤ˆÎ!×<6`Ò¸$/µåKD™‹ë)ž= €¬¬,?~ÜÕ×öíÛqã7zdµé†²© ˜@@­D¸¼˜iii¸þúëñ裺ÚϘ1k׮Ń>ˆªsìß¿?Âá°Ë¾”4—c& Þÿ}×๹¹*(98e´&eËÅ0}njjò(%‹¹œÁ¶p—“ÐJ.رc.¿ürqeð±y¢W9f"ÀtÖ_155ÕyµÍ™ƒ?%%ÅíãeLNüøòrç‘Âæ¸ÄKD<HÀ¹ìCAPfúŽËJýåçç{úÛ¹s'®»î:—-RRR\²QËIºáãh“Û‚tB•K=pçw¢²²ÒųcÇŒ3ƒ ¼yó‘‘ᚣ¶i•ššê™‹†¢4ضm›k`*?ÈIx}¬-X%/}ÇÁûá‡z”B%/‘ ð4®¼ÌÌLœ8qÂÕßÑ£GqÙe—yøü2&&?^ÖãÕ×555Uuâ•óKKKs¾³e¹V![ð¹j¼´‘„;!/ÉNú¯¯¯÷´µU?yòd?~ëׯ÷ðîܹ×_=î¸ãÜ~ûíÈÈÈp~³-i(@ðC“-ÍãÚ}"¥Úvž¤3ÊmmNT3Ûˆ]«Õ¥Rùˆüã¹¹¢yVÐÆ¦]>™ø¸/9wvÞ/É«eLžI¸näšÌ¦+P>6ɪ¾ü$‹9ë[¯h(cÊ¥Œ¯&èÉJ¤ 0¿R–gK>OÒæ‹r_A++gÏžÌÌL¬X±B÷K/½„õë×ãÇ?þ1ÆŽë©Ö´Ì-¬<½^‡s[Ã2cÊÝ%YÇkkyÞFÒúõëÕþeVÐÊÈ Hn¾(‰]Û1³+Çâ Ó6Ç4Gç¼¼„–cÛä•[öÚ†Gû¬˜ü"j¢úúzÔ××»@b–ÆÑΡÝxãjôó+ü Àê¬r“‹·KÄÑ9 ¥<ñ6Œ4J$ss™äö½æ˜\V~ªŠèÒK/EÏž==í_ýuu}f[{kö1b„G&ž­%Ù€Ãåµíqð=M‡}ô‘Ú¯<Š‹‹QZZêâmiiQ7’´ÝcY:ÒNœ8Ñ#ôñãÇ1oÞ<;v̺¶áÊþðÃ1nÜ8\uÕU}\í[[[±víZ˜¤<—V>ùä“*(;cÃÎê&^ÿÕÕÕªÍùfgJJŠë¸ì²ËÔ]e¿MN:\§KfÍš¥ ÖÔÔ„‰'âŽ;îÀâÅ‹ñî»ï¢¦¦7nÄüùóqÓM7á±Ç<ýôÓÈÎζF°œœ,X°ÀóÛÿøGç½Üáß-_¾Ü¹x:;;Û¹øÞ~JלNfNüé7n¢àM„·ãN%¿?_ç:uª§¤}á…ÐÒÒâÙT“ÇñãÇ]À\¸p!®¸â 뼕Qã±ñjúT]]¦¦&5Ùpp¶µµ¹ø† æÙÝõ+kyÐr…ÉÒÒR<÷ÜsªpÀ¹šyõêÕ˜={6þøÇ?bÆŒX¹r¥siÜüùó1räȸço¹åüéOr}·wï^Ì™3Çù,³¦1o½õ–²³³Q]]ììlÕñ¸ò¤ÂˆüB¿É^¨—£É>lŽpâÄ _0cÔ1ýˆÏ¡¥¥E•׿àñU2¶v={öÄìÙ³=à|ðÁÑÚÚ À[(o¿ýv§ýSO=…[n¹E]Ëq[RŸœ´%ŒÐ={ötz~À¹Ö§žzÊ“5)S0_ýu‡çꫯv­9yõg«:=kL.ÔèÑ£]wæ'BxôÑGqà 7¨‘@3ÌÈ‘#QYYéJÿµµµ¸ûî»±víZ—QkjjðË_þ¿ûÝQ¹ªª YYYêægjjªç"}«µµÕ7Ó¼óÎ;Þ¦¦&ÔÔÔÄͰUUUÞúúzõ‚~Nr]Às[ž-Ë×ÔÔxx7nÜèë€ô&ïÆ}e èÙ³'æÌ™ƒ¡C‡:ß·¶¶bܸq¨¬¬Äœ³åž={°`ÁŒ5 'Nœ@VV,X€›o¾Ù Jοþõ¯Ö¬Y·ô}÷ÝwÕ€§éK£ššÜ}÷ݨ««sÉCÑ<óÌ3Σ@¯¹æL›6ÍiGdŒû¡~›@p8lè\]¹ ññÇc„ ؽ{·¯Àååå;v,òòòžžŽôôtç¼%C Æ/\…Bxñűråʸ™bÀ€¸ÿþûqÕUW9ÑŠ&Âo’‡Ãذaššš°iÓ&ìÛ·Oí¯W¯^èÛ·/† æÚeèÑ£.¼ðBìß¿û÷ïÇ{ï½§f=èׯúöí‹>}ú8epîî ƒbóæÍVfdd ¸¸}úôAŸ>}pÑE8÷8™øòöïßÅÅŸ袋ðÝï~^x¡`evÚ¿?–.]ê€ÑF¸óÎ;q×]w9¾BŽI—S’=wíÚ…úúz¼öÚkVÝôêÕ Ã† CŸ>}œÑÚÚŠC‡áý÷ßGmm­U–~ýúášk®Á°aܹ<ñÄhmmEFFRRRgff:7]c°aÃgN?úÑ0fÌOüá¡[·nHOOÇ\à:8~‘sríÑÜíííøä“O°}ûv¼ýöÛNvêÙ³'úôéƒââb¤¥¥9uïÞÝuA¥x29’6^(®]»PWWçrè””\wÝu8p .¾øbð©OyI_(ÂôéÓ=»¹üUfðÑ£GãÒK/pîñ°î ÊäË.» ·Þz+Œ1X»v-öïß——^ (kÖ¬qäãÙ‚ç½ÿþû¹=ñÄ®(ÎûÐ6Òø\;Ë[RR‚K.¹ÄLíüiSS“hxŸýû÷G~~>®¼òJ—-)€Sàæ¶|ùå—±gÏßÍ1.ë}÷Ýc <ˆ7ÞxÃzݶœé…Æ9xð ²²²““ãÈúÑG¡¹¹uuuÎižŒŒ \~ùåøþ÷¿¯ž÷—º"ÌtïÞÝe÷îÝÃLîÜ”5ÛÛÛÇOÐãøsW(ppreS$”†ãWäÈÇOÈKè(¤¥¥9BSߤ`^·ó«M\5»ˆ¶ çÊKMMu͉‚Œ t-(¿ Š_ñÄ«”äslˆW»Î˜ˆo8%Oàë«­HVÎKóÔ¶êI¿¤Oš/Sš+—•_^Gz• æÎNÄå¤Ì@Ÿ'Sn”ØÎaò Ée“c’Ž(ð±øÜhò=é×2Ùðµ£v¡ŒôCÒ7Rfšm§‰ƒN>úÂU Žš²xI+×oô=oÏû vZTŒÅb.còö|lŸ ,5é{*™y$Œ—xmÃG3¦$¹6‘g õÇ¿—áF㎠KFT wÕÁ¿ãDV$3w¹S¨EoYæs½Ê51×wVG.äúYÚ€ëq+ÒŽÔ'ù·5÷U-;q½I›ñql¼²êŸ'©w L PÒW²–1»uë¦^(@Y+\̱åâYf¾hÖÖ}œ_W’”…J.“Œ|~F‘ëS’M–Þ|}Î7ª´À"7üJC)+ñhFæ¶•Ù%^ç¼4W-£Ê¹Ê&³¦Í–‰TDRÔw4uùŽ Îr¯„gLZfÙl¡í³øÉʳ§ JÜ%0e@MãBÉ’E¢+UÛ䥃t¹Û¨…+B{z¸,a¸¢´ÒƒÆ’ÁC–0e&ãpåÛx¹a$¯t|^ZQ¦ÕJ; .@-@JÇ%~9.·­œ«VYÄ+gåZšgxÍžR~ê7‰¸ä㠃뒋~“_ÚBXYòr’à´U\ß¶¬éZc’Á98»uëæFjjªz•œ’L;dd¥ZŸo5Óg^Ùj}éü¶ŒH}ó(¥o¢ #Ëhn¹!Fcq#J^î@Zðѵ‰F£HKKóDa œÏU–VÚ\90åÕJa~hA^f`-Øjßq}ðùó3š-eF§ùi¶z%~ ˜€¼[¥ %/ÇdôäBË4Ÿ05'áƒû•<´–áýJeq…$J n iP- ÉÒ›œ•xø—t—Ï“ÍxRv*½d°âcIPË`d«Bø\¹ŽÉùIfíܰ\cJ~¹ÞLÔ–RÀ\Nš_›ÊùñþÈ–òÕ ç•öä$ÁÉ¿çsreFQbSÿ®R–;W41ò«¤±¸cjõ¹Œ 2²’’Éq);Hg’ÆäŽ¢’+‰—Í4–.-{Q|G϶óhã%~ÉËç$Ë:ÉË€#ƒ9Í[––2H^ ÐZ‘óÔÖ_2kj%^¢ ÔlÀ«ò?{HPÙlÁí .#ïG{o›#¢Ô«”娦ï8(e§d,0åàrEF?š 9¾­,¯¶–ƒ›Q¸ãKcJ'çºã²Ð{jãÇksT›SI`iΧ9╲ʀi Z@àºÒdOÄ–28ÙôÁw¸ãŒÏU“Ë¯ÔæóÒ|WÎWÚSëëM&+5cÒà2ŠS§Zic‹à¶2Ks_ö-&I£0y¤å™D:‹4ª­)¿-êk¼¨µW‘mG€:ž”×–QâÊfWtý‹6éÐ6`jYÏÏÖ‡´ïצ›_­^½Úóÿ›¶ÀÃAhÓ]ïHËœ2jq‡Ö²™æ”Úàšãñ¾©m<ƒj”†Êâ §Ìl¥IgJ3I~ó’ºá<ü5Þx2¢“Íd•WŽ­9ngç,çígWÞ—æ‹~ÁN“-Q;jrÀ|€5kÖ ¼¼Ü7èp,Ùªú=M2Kp?aJ¯™Íx6g—ð‹´6#JrÀÓ|8øýúÕHË"|ÌDœTòJ™¥üZ{>ÖùÊÛ^m\z¯­µ±ýlé'“Í_d÷“Óonš^4¹8ýþ÷¿G^^žSéiòjýikz5cò9¥k ±)BS´¦ ÞNËH‰¦DIÔeIþ½×€áxÑŸ¿j<~üšüùÍ=ž¼á¥÷~§Éï§+%Ò§ôDl)Éf‹x6€U«Váƒ>@^^€Ç¯l}ɵnÜŒÉ;²ML*$‘²D*ÆOI6úQ"}ksà}kŠ´}î,°4£&â¤HiëÇOÞDyãSRgÀ™H_šŸØ~·ùq¼ äç» ÎS5h [PrQ;¹á›1ý& Ñí§d¿Ì¨ý®)*ž:36—7чM ¿IDAT9øÉz>òt–ï|ÈæçÃ>º‰×®³¶$žÎ‰ó‘Åo޲φ†£¡¡Ái/yüÊZúLe8×7cjú'¯ís¢¿ñ1¿éþÎ×Q·Ηïߥÿ´¼çÓ"•FCCæÏŸÜÜ\ÏŸùTWW;ÏÙÉËËCyy9 ^³lݺÕ9ˆ***PTT„¼¼<5‹>ù䓸ío룱±ÑõÔvàÜÃídðàëJ™]]ÙÔü‹Åâ]™ŸKgÚÿ/ß49rÄüæ7¿1 SQQa¢Ñ¨‰F£fåÊ•&//Ïù“&M2íí힣££Ã9‚Á Ù´i“),,4Lyy¹)//÷ô9yòd ]|Ä“ÈÑÖÖfÚÚÚLkk«ikk3'Ož4_|ñ…9}ú´9sæŒioo7Á`ЄB!óÕ“DL45±XÌü[ÀLR’¾i:räˆ:t¨ÇÉ+**L$1¯¼òJ\@TVVš3gΨÇÙ³gÍŠ+@>|ØG04?þ¸«¯1cƘöövsöìYsöìYW_eeeN»ÒÒRóù矛¶¶6ÓÒÒbšššÌ‰'\Gss³immuÊÁ‡pÆb1ãÏT’’ô_¦¼¼s}oŒAUU~ò“Ÿ`Ò¤I¨©©Á™3gpúôiÌž=ÛÕvÁ‚ê?ŽE"TWWã§?ý) PYY‰œœ×Å 'NÄ£>êôõÚk¯áÏþ³ú°f#6òä_Êÿ•Gϯ ÷\aÌa7"IIê‘KÞvÛm®5$pî9·&c¾¾âçÁÄ3Ï<ãô±sçNäääpŸªËÏÏGcc#6lØ€‚‚ÏŽ-ÿï|Çõ][[›g½y×]waíÚµ€’’,^¼X½ù‚ú×n÷’w®8kÐoT£IJÒ7D2_äææbÿþýÈÎÎö<®4‰xþInëÖ­žÌµpáB466"''ƒ RŸÄG‡¼¼nÕªU®¾‚Á k×5‹¹~“¯~ÿJ†Ï9¡]Ù$%é¿EÆè”P–䆤ϱX  pµ§‡—_gLÊnÙÙÙXµj•õºbàÜ.+§Õ«W㦛nreM ˜üIëÔ–ÆçÈKTé” eØ$0“ÔeI”?«U»õ=ø;vìlß¾÷ÜsO§d‰Åb®çkÀ¤,ªÝz&AÉ" ™1“Ô…Hn¦ÈßøSÚµ8çD³@´~ýzçýÈ‘#±`Áßûee‰IÀ“¿‘\¶[!ù{yw–¦‡$0“Ô¥Hn°ðïå_kä/0ùÉ£Ñ(B¡“É´rVfF-cc …¬OBà™SfT™-dÆLÒ·ˆ¨LäàämãDàÎe)ÌÝ»w# ªp¯s%€x&”¥¬<ýADch§Elkê$0“ÔåHsX^ÊÊsŠ6`ò,Êߟ8q ÈÊÊR)eЀ¤ÉÇ7}˜¶Š@RòtI’¾Ä3_Çq Êö¼M¯^½\¿¿ôÒKž‹ä|-»sçN׿ÈÓ€÷‘12svæ’$0“Ô%Isbžu´'J~޾}ûº~¯ªªÂÑ£G=ç:µE«««ÃÆ­ƒñ“Ùø…ô™( Ì$}kˆg#¹Þ‹ c Š‹‹]ß?Þ§ÜTâ,\¸×]wçNÛSp~w¶h¼ô> Ì$}ëH®í4PjkÆ1cƸ¾knnƤI“P__ïY³R¦}øá‡aŒA¿~ý\`Ónp–›I¶ƒóØ.pHnþ$é[I‰”ôl'jû½ï}×\s 6oÞì´iiiÁ”)Sзo_ >½{÷F À¾}û°yóf477ãé§ŸvÚÛ@VSSƒ &8kÙ3f _¿~¨¨¨ð'õ)) Ì$uYÚ¶m›óþèÑ£ÜO  ×@ €¦¦&oKK €¯ÃJí§M›†Y³f¡¶¶ÖÕ~ß¾}Ø·oŸG†‡zýúõsEYñ†nÀƶ¿þõ¯Ñ¿Ô×צOŸî›‰´ “,e“Ô%éÉ'Ÿt]¯º}ûv¬[·ÎZ .Z´ÈÅ_UU…½{÷zÚÀ<€áÇǕaÚ´i(..ö\óJà1b233öMMM¨©©Ass3fΜé)k%ùm"%oûJR—!c ¶lÙ‚ùóç{NêóSwÞy'úöí‹H$‚+V ¾¾Þ•%͘1Ãu”Î5îÝ»«W¯Æþýû Û«W/ >eeeÈÈÈPÿ‡`œã¼yó°aÃÀ~ðLœ8={öt_Éózz:ºwïîéééHOO÷ü_˜Iê2ÄÁH0|§4 zn¥’ÿÑ Àu§†¼0Až‡ÔNðÛý“òL¨?>º€™žžŽ .¸ÀyŸžžŽnݺ¹úN®1“ô­">þànúMî˜ÒÿÓh$^­¤´] $Ûð› åX|}ë·ÖÔ®J3I]’$Øø{@þ‡MòwcŒçÏy»xÁÁï8¡W™Yù+%OçHÙµ¾$8“ÀLR—'¹JÙ‰ÞóRVf&í¶*žeù:–>Ëqµ+sxæ–æÄ™è¼ÉŒ™¤.L2;ÊWíŸåS 8/]µ»<88µ ¬~ÉGcr¹´‹4J3I]ŽlŠoÈðLdËrrûê¿4mw‰ð‹ÎeŸÚßHjŸG}Ðxä$;ç—s&J3I]’´u#e¢Àä1òî"yí-ÏžÔ§Ü¥µíÎÒ8ô*Ël~ZD”ƒ3 Ì$u)․ψ˜ø/S¾Ãù¹ƒÛ'wAå9SþÜl²“gIyJ†~×Ήʬ$Æ•¤.D~ÙœZn¦ð¬¨m¨he«¶k*/hm90 œ<‹j›Iü•ƒ[6Ÿ/̘Iꢤm°Ðéþ½¶ëJüÄC¯¶Ó"DÚ-eòt§VÊò±dÉÌ çÕÀ™f’ºÉõ%eÆ´´sîÊÏ]ʧÑñW@?_(É/kJ’`’›8¼O­ÉÇ7ƒ\§fŒ-|üÿ'þç.©qÚ&éÿÉ“íür7mý¦ô·õ—ȸ²_mÍïô‡-;k»ºœ@×&'hòn˜ÿ’3¶ÓžDú$ÒÎ?ú•½Ú…6`ò¾ˆ—gEÀÀ·˜D@@É,úš´]ÓDý¯ÏÎŒ­S‚‹¾÷“߯¯íÈßžŒ™¤ÿA²ÒïÿÓcrâÒÖ´Z_’dP~ 3f’þÇÈÛ÷ß䘶þ5pÒg›œ¯ß÷I`&©ËS< ü§ÇÔÈo=Û’À&ú0$ÂH¨å€IEND®B`‚commons-net-2.2/src/site/xdoc/0000755000175000017500000000000011617452470016251 5ustar twernertwernercommons-net-2.2/src/site/xdoc/migration.xml0000644000175000017500000000352711352236431020764 0ustar twernertwerner Apache Commons Net Migration How-to Jeffrey D. Brekke

This how-to lists the migration steps for moving between versions of Commons/Net.

This version requires a JDK 5.0+ runtime. It has also been tested on JDK 6.0. There should be no changes required to existing client code.

This version is a drop in replacement for NetComponents. Only package names have changed.

  1. Change all occurances of com.oroinc.net.* to org.apache.commons.net.*
  2. Change all occurances of com.oroinc.io.* to org.apache.commons.net.io.*
  3. Change all occurances of com.oroinc.util.* to org.apache.commons.net.util.*
commons-net-2.2/src/site/xdoc/tasks.xml0000644000175000017500000000401111352236431020105 0ustar twernertwerner Tasks Jeffrey D. Brekke Rory Winston

  • Add more unit tests, and implement mock servers for testing
  • Convert code to specified coding standards. Checkstyle report provided.
  • Clean out any classes that don't belong in this project. Probably classes from org.apache.commons.net.util and org.apache.commons.net.io could be moved to their corresponding commons projects.
  • Parse the client/server interactions without creating so many strings. Many operations are slow because of this.
  • Add ESMTP and more extended NNTP commands.
  • Make NNTPClient.listNewsgroups() and NNTPClient.listNewNews() more efficient. Don't preparse into lots of little objects.
  • FTP proxy support

commons-net-2.2/src/site/xdoc/issue-tracking.xml0000644000175000017500000001320710762657376021742 0ustar twernertwerner Commons Net Issue tracking Commons Documentation Team

Commons Net uses ASF JIRA for tracking issues. See the Commons Net JIRA project page.

To use JIRA you may need to create an account (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically created and you can use the Forgot Password page to get a new password).

If you would like to report a bug, or raise an enhancement request with Commons Net please do the following:

  1. Search existing open bugs. If you find your issue listed then please add a comment with your details.
  2. Search the mailing list archive(s). You may find your issue or idea has already been discussed.
  3. Decide if your issue is a bug or an enhancement.
  4. Submit either a bug report or enhancement request.

Please also remember these points:

  • the more information you provide, the better we can help you
  • test cases are vital, particularly for any proposed enhancements
  • the developers of Commons Net are all unpaid volunteers

For more information on subversion and creating patches see the Apache Contributors Guide.

You may also find these links useful:

commons-net-2.2/src/site/xdoc/index.xml0000644000175000017500000000676011352236431020104 0ustar twernertwerner Apache Commons Net Commons Documentation Team

Apache Commons Net implements the client side of many basic Internet protocols. The purpose of the library is to provide fundamental protocol access, not higher-level abstractions. Therefore, some of the design violates object-oriented design principles. Our philosophy is to make the global functionality of a protocol accessible (e.g., TFTP send file and receive file) when possible, but also provide access to the fundamental protocols where applicable so that the programmer may construct his own custom implementations (e.g, the TFTP packet classes and the TFTP packet send and receive methods are exposed).

Supported protocols are:

  • FTP/FTPS
  • NNTP
  • SMTP
  • POP3
  • Telnet
  • TFTP
  • Finger
  • Whois
  • rexec/rcmd/rlogin
  • Time (rdate) and Daytime
  • Echo
  • Discard
  • NTP/SNTP

Jakarta Commons Net started as a commercial Java library called NetComponents, originally developed by ORO, Inc. in the early days of Java. After its 1.3.8 release in 1998, the source code was donated to the Apache Software Foundation and made available under the Apache License. Since then, many programmers have contributed to the continued development of Jakarta Commons Net. The current version numbering scheme bears no relation to the old. In other words, Jakarta Commons Net 1.0 succeeded and supplanted NetComponents 1.3.8. Apache Jakarta Commons is now an independent project and is called Apache Commons.

For more info, see the JavaDoc, or look at some of the following articles:

commons-net-2.2/src/site/xdoc/download_net.xml0000644000175000017500000002063011470611172021442 0ustar twernertwerner Download Commons Net Commons Documentation Team

We recommend you use a mirror to download our release builds, but you must verify the integrity of the downloaded files using signatures downloaded from our main distribution directories. Recent releases (48 hours) may not yet be available from the mirrors.

You are currently using [preferred]. If you encounter a problem with this mirror, please select another mirror. If all mirrors are failing, there are backup mirrors (at the end of the mirrors list) that should be available.

[if-any logo][end]

Other mirrors:

The KEYS link links to the code signing keys used to sign the product. The PGP link downloads the OpenPGP compatible signature from our main site. The MD5 link downloads the checksum from the main site.

commons-net-2.2.tar.gz md5 pgp
commons-net-2.2.zip md5 pgp
commons-net-2.2-src.tar.gz md5 pgp
commons-net-2.2-src.zip md5 pgp
commons-net-1.4.1.tar.gz md5 pgp
commons-net-1.4.1.zip md5 pgp
commons-net-1.4.1-src.tar.gz md5 pgp
commons-net-1.4.1-src.zip md5 pgp

Older releases can be obtained from the archives.

commons-net-2.2/src/site/xdoc/faq.xml0000644000175000017500000000310311351151237017527 0ustar twernertwerner Apache Commons Net FAQ Apache Commons User Mailing List

This document attempts to answer some of the more frequently asked questions regarding various aspects of Commons/Net. These questions are typically asked over and over again on the mailing lists, as a courtesy to the developers, we ask that you read this document before posting to the mailing lists.

CommonsNet/FrequentlyAskedQuestions

commons-net-2.2/src/site/xdoc/code-standards.xml0000644000175000017500000001123311351150063021652 0ustar twernertwerner Coding Standards Jon S. Stevens Jason van Zyl

This document describes a list of coding conventions that are required for code submissions to the project. By default, the coding conventions for most Open Source Projects should follow the existing coding conventions in the code that you are working on. For example, if the bracket is on the same line as the if statement, then you should write all your code to have that convention.

If you commit code that does not follow these conventions, you are responsible for also fixing your own code.

Below is a list of coding conventions that are specific to Apache Commons Net everything else not specificially mentioned here should follow the official Sun Java Coding Conventions.

1. Brackets should begin and end on a new line and should exist even for one line statements. Examples:

2. Though it's considered okay to include spaces inside parens, the preference is to not include them. Both of the following are okay:

3. 4 space indent. NO tabs. Period. We understand that many developers like to use tabs, but the fact of the matter is that in a distributed development environment where diffs are sent to the mailing lists by both developers and the version control system (which sends commit log messages), the use tabs makes it impossible to preserve legibility.

In Emacs-speak, this translates to the following command:

4. Native linefeeds (svn:eol-style native) for all .java source code and text files. Platform specific files should have the platform specific linefeeds.

5. JavaDoc MUST exist on all public and protected methods. JavaDoc on private and default access methods and members is preferred and encouraged. If your code modifications use an existing class/method/variable which lacks JavaDoc, it is required that you add it. This will improve the project as a whole.

6. The Apache License header MUST be placed at the top of each and every file.

9. Import statements must be fully qualified for clarity.

And not


X/Emacs users might appreciate this in their .emacs file.

Thanks for your cooperation.

commons-net-2.2/src/site/xdoc/download.xml0000644000175000017500000000223311351150414020566 0ustar twernertwerner Apache Commons Net Download Jeffrey D. Brekke

You can download binary and source release builds.

commons-net-2.2/src/site/site.xml0000644000175000017500000000356311467044742017013 0ustar twernertwerner Commons Net /images/net-logo-white.png /index.html commons-net-2.2/src/site/apt/0000755000175000017500000000000011617452467016106 5ustar twernertwernercommons-net-2.2/src/site/fml/0000755000175000017500000000000011617452470016072 5ustar twernertwernercommons-net-2.2/src/test/0000755000175000017500000000000011617452465015333 5ustar twernertwernercommons-net-2.2/src/test/java/0000755000175000017500000000000011617452465016254 5ustar twernertwernercommons-net-2.2/src/test/java/org/0000755000175000017500000000000011617452465017043 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/0000755000175000017500000000000011617452465020264 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/0000755000175000017500000000000011617452465021737 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/0000755000175000017500000000000011617452466022526 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/ntp/0000755000175000017500000000000011617452465023326 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/ntp/TimeStampTest.java0000644000175000017500000000730511364045325026731 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ntp; import java.util.Date; import java.util.Calendar; import junit.framework.TestCase; import org.apache.commons.net.ntp.TimeStamp; /** * Test class that validates assertions for the basic TimeStamp operations and comparisons. * * @author Jason Mathews, MITRE Corp */ public class TimeStampTest extends TestCase { private static final String TIME1 = "c1a9ae1c.cf6ac48d"; // Tue, Dec 17 2002 14:07:24.810 UTC private static final String TIME2 = "c1a9ae1c.cf6ac48f"; // Tue, Dec 17 2002 14:07:24.810 UTC private static final String TIME3 = "c1a9ae1d.cf6ac48e"; // Tue, Dec 17 2002 14:07:25.810 UTC public void testCompare() { TimeStamp ts1 = new TimeStamp(TIME1); // Tue, Dec 17 2002 14:07:24.810 UTC TimeStamp ts2 = new TimeStamp(TIME1); TimeStamp ts3 = new TimeStamp(TIME2); // Tue, Dec 17 2002 14:07:24.810 UTC TimeStamp ts4 = new TimeStamp(TIME3); // Tue, Dec 17 2002 14:07:25.810 UTC // do assertion tests on TimeStamp class assertEquals("equals(1,2)", ts1, ts2); assertEquals("compareTo(1,2)", 0, ts1.compareTo(ts2)); assertEquals("ntpValue(1,2)", ts1.ntpValue(), ts2.ntpValue()); assertEquals("hashCode(1,2)", ts1.hashCode(), ts2.hashCode()); assertEquals("ts1==ts1", ts1, ts1); // timestamps in ts1 (TIME1) and ts3 (TIME2) are only off by the smallest // fraction of a second (~200 picoseconds) so the times are not equal but // when converted to Java dates (in milliseconds) they will be equal. assertTrue("ts1 != ts3", !ts1.equals(ts3)); assertEquals("compareTo(1,3)", -1, ts1.compareTo(ts3)); assertEquals("seconds", ts1.getSeconds(), ts3.getSeconds()); assertTrue("fraction", ts1.getFraction() != ts3.getFraction()); assertTrue("ntpValue(1,3)", ts1.ntpValue() != ts3.ntpValue()); assertTrue("hashCode(1,3)", ts1.hashCode() != ts3.hashCode()); long time1 = ts1.getTime(); long time3 = ts3.getTime(); assertEquals("equals(time1,3)", time1, time3); // ntpTime1 != ntpTime3 but JavaTime(t1) == JavaTime(t3)... assertTrue("ts3 != ts4", !ts3.equals(ts4)); assertTrue("time3 != ts4.time", time3 != ts4.getTime()); } public void testUTCString() { TimeStamp ts1 = new TimeStamp(TIME1); // Tue, Dec 17 2002 14:07:24.810 UTC String actual = ts1.toUTCString(); assertEquals("Tue, Dec 17 2002 14:07:24.810 UTC", actual); } public void testDateConversion() { // convert current date to NtpTimeStamp then compare Java date // computed from NTP timestamp with original Java date. Calendar refCal = Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC")); Date refDate = refCal.getTime(); TimeStamp ts = new TimeStamp(refDate); assertEquals("refDate.getTime()", refDate.getTime(), ts.getTime()); Date tsDate = ts.getDate(); assertEquals(refDate, tsDate); } } commons-net-2.2/src/test/java/org/apache/commons/net/io/0000755000175000017500000000000011617452465023134 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/io/DotTerminatedMessageReaderTest.java0000644000175000017500000000553411347152644032035 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.io; import java.io.IOException; import java.io.StringReader; import junit.framework.TestCase; public class DotTerminatedMessageReaderTest extends TestCase { private DotTerminatedMessageReader reader; private StringBuilder str = new StringBuilder(); private char[] buf = new char[64]; final static String SEP = System.getProperty("line.separator"); public void testReadSimpleStringCrLfLineEnding() throws IOException { final String test = "Hello World!\r\n.\r\n"; reader = new DotTerminatedMessageReader(new StringReader(test)); reader.LS_CHARS = new char[]{'\r','\n'}; int read = 0; while ((read = reader.read(buf)) != -1) { str.append(buf, 0, read); } assertEquals("Hello World!" + String.valueOf(reader.LS_CHARS), str.toString()); } public void testReadSimpleStringLfLineEnding() throws IOException { final String test = "Hello World!\r\n.\r\n"; reader = new DotTerminatedMessageReader(new StringReader(test)); reader.LS_CHARS = new char[]{'\n'}; int read = 0; while ((read = reader.read(buf)) != -1) { str.append(buf, 0, read); } assertEquals("Hello World!" + String.valueOf(reader.LS_CHARS), str.toString()); } public void testEmbeddedNewlines() throws IOException { final String test = "Hello\r\nWorld\nA\rB\r\n.\r\n"; reader = new DotTerminatedMessageReader(new StringReader(test)); int read = 0; while ((read = reader.read(buf)) != -1) { str.append(buf, 0, read); } assertEquals(str.toString(), "Hello" + SEP +"World\nA\rB" + SEP); } public void testDoubleCrBeforeDot() throws IOException { final String test = "Hello World!\r\r\n.\r\n"; reader = new DotTerminatedMessageReader(new StringReader(test)); int read = 0; while ((read = reader.read(buf)) != -1) { str.append(buf, 0, read); } assertEquals("Hello World!\r" + SEP,str.toString()); } } commons-net-2.2/src/test/java/org/apache/commons/net/SubnetUtilsTest.java0000644000175000017500000002365411466130325026511 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net; import org.apache.commons.net.util.SubnetUtils; import org.apache.commons.net.util.SubnetUtils.SubnetInfo; import junit.framework.TestCase; public class SubnetUtilsTest extends TestCase { public void testParseSimpleNetmask() { final String address = "192.168.0.1"; final String masks[] = new String[] { "255.0.0.0", "255.255.0.0", "255.255.255.0", "255.255.255.248"}; final String bcastAddresses[] = new String[] { "192.255.255.255", "192.168.255.255", "192.168.0.255", "192.168.0.7"}; final String lowAddresses[] = new String[] { "192.0.0.1", "192.168.0.1", "192.168.0.1", "192.168.0.1" }; final String highAddresses[] = new String[] { "192.255.255.254", "192.168.255.254", "192.168.0.254", "192.168.0.6" }; final String networkAddresses[] = new String[] { "192.0.0.0", "192.168.0.0", "192.168.0.0", "192.168.0.0" }; final String cidrSignatures[] = new String[] { "192.168.0.1/8", "192.168.0.1/16", "192.168.0.1/24", "192.168.0.1/29" }; final int usableAddresses[] = new int[] { 16777214, 65534, 254, 6 }; for (int i = 0; i < masks.length; ++i) { SubnetUtils utils = new SubnetUtils(address, masks[i]); SubnetInfo info = utils.getInfo(); assertEquals(bcastAddresses[i], info.getBroadcastAddress()); assertEquals(cidrSignatures[i], info.getCidrSignature()); assertEquals(lowAddresses[i], info.getLowAddress()); assertEquals(highAddresses[i], info.getHighAddress()); assertEquals(networkAddresses[i], info.getNetworkAddress()); assertEquals(usableAddresses[i], info.getAddressCount()); } } // TODO Lower address test public void testAddresses() { SubnetUtils utils = new SubnetUtils("192.168.0.1/29"); SubnetInfo info = utils.getInfo(); assertTrue(info.isInRange("192.168.0.1")); // We don't count the broadcast address as usable assertFalse(info.isInRange("192.168.0.7")); assertFalse(info.isInRange("192.168.0.8")); assertFalse(info.isInRange("10.10.2.1")); assertFalse(info.isInRange("192.168.1.1")); assertFalse(info.isInRange("192.168.0.255")); } public void testZeroNetmaskBits() { try { @SuppressWarnings("unused") SubnetUtils utils = new SubnetUtils("192.168.0.1/0"); fail("Mask /0 should have generated an IllegalArgumentException"); } catch (IllegalArgumentException expected) { } } /** * Test using the inclusiveHostCount flag, which includes * the network and broadcast addresses in host counts */ public void testCidrAddresses() { SubnetUtils utils = new SubnetUtils("192.168.0.1/8"); utils.setInclusiveHostCount(true); SubnetInfo info = utils.getInfo(); assertEquals("255.0.0.0",info.getNetmask()); assertEquals(16777216, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/9"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.128.0.0",info.getNetmask()); assertEquals(8388608, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/10"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.192.0.0",info.getNetmask()); assertEquals(4194304, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/11"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.224.0.0",info.getNetmask()); assertEquals(2097152, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/12"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.240.0.0",info.getNetmask()); assertEquals(1048576, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/13"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.248.0.0",info.getNetmask()); assertEquals(524288, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/14"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.252.0.0",info.getNetmask()); assertEquals(262144, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/15"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.254.0.0",info.getNetmask()); assertEquals(131072, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/16"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.0.0",info.getNetmask()); assertEquals(65536, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/17"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.128.0",info.getNetmask()); assertEquals(32768, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/18"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.192.0",info.getNetmask()); assertEquals(16384, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/19"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.224.0",info.getNetmask()); assertEquals(8192, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/20"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.240.0",info.getNetmask()); assertEquals(4096, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/21"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.248.0",info.getNetmask()); assertEquals(2048, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/22"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.252.0",info.getNetmask()); assertEquals(1024, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/23"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.254.0",info.getNetmask()); assertEquals(512, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/24"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.0",info.getNetmask()); assertEquals(256, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/25"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.128",info.getNetmask()); assertEquals(128, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/26"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.192",info.getNetmask()); assertEquals(64, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/27"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.224",info.getNetmask()); assertEquals(32, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/28"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.240",info.getNetmask()); assertEquals(16, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/29"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.248",info.getNetmask()); assertEquals(8, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/30"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.252",info.getNetmask()); assertEquals(4, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/31"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.254",info.getNetmask()); assertEquals(2, info.getAddressCount()); utils = new SubnetUtils("192.168.0.1/32"); utils.setInclusiveHostCount(true); info = utils.getInfo(); assertEquals("255.255.255.255",info.getNetmask()); assertEquals(1, info.getAddressCount()); new SubnetUtils("192.168.0.1/1"); } public void testInvalidMasks(){ try { new SubnetUtils("192.168.0.1/33"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { new SubnetUtils("192.168.0.1/0"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { new SubnetUtils("192.168.0.1","0.0.0.0"); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } } } commons-net-2.2/src/test/java/org/apache/commons/net/tftp/0000755000175000017500000000000011617452466023503 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/tftp/TFTPTest.java0000644000175000017500000001660711421555273025766 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.net.tftp.TFTPServer.ServerMode; import junit.framework.TestCase; /** * Test the TFTP Server and TFTP Client by creating some files in the system temp folder and then * uploading and downloading them. * * @author Dan Armbrust * */ public class TFTPTest extends TestCase { private static TFTPServer tftpS; private static final File serverDirectory = new File(System.getProperty("java.io.tmpdir")); private static final String filePrefix = "tftp-"; private static final File[] files = new File[8]; static int testsLeftToRun = 6; // only want to do this once... static { try { files[0] = createFile(new File(serverDirectory, filePrefix + "empty.txt"), 0); files[1] = createFile(new File(serverDirectory, filePrefix + "small.txt"), 1); files[2] = createFile(new File(serverDirectory, filePrefix + "511.txt"), 511); files[3] = createFile(new File(serverDirectory, filePrefix + "512.txt"), 512); files[4] = createFile(new File(serverDirectory, filePrefix + "513.txt"), 513); files[5] = createFile(new File(serverDirectory, filePrefix + "med.txt"), 1000 * 1024); files[6] = createFile(new File(serverDirectory, filePrefix + "big.txt"), 5000 * 1024); files[7] = createFile(new File(serverDirectory, filePrefix + "huge.txt"), 37000 * 1024); // Start the server tftpS = new TFTPServer(serverDirectory, serverDirectory, 6900, ServerMode.GET_AND_PUT, null, null); tftpS.setSocketTimeout(2000); } catch (IOException e) { e.printStackTrace(); } } @Override protected void tearDown() throws Exception { testsLeftToRun--; if (testsLeftToRun <= 0) { if (tftpS != null) { tftpS.shutdown(); } for (int i = 0; i < files.length; i++) { files[i].delete(); } } super.tearDown(); } /* * Create a file, size specified in bytes */ private static File createFile(File file, int size) throws IOException { OutputStream os = new BufferedOutputStream(new FileOutputStream(file)); byte[] temp = "0".getBytes(); for (int i = 0; i < size; i++) { os.write(temp); } os.close(); return file; } public void testTFTPBinaryDownloads() throws Exception { // test with the smaller files for (int i = 0; i < 6; i++) { testDownload(TFTP.BINARY_MODE, files[i]); } } public void testASCIIDownloads() throws Exception { // test with the smaller files for (int i = 0; i < 6; i++) { try { testDownload(TFTP.ASCII_MODE, files[i]); } catch (IOException e) { fail("Entry "+i+" Error "+e.toString()); } } } public void testTFTPBinaryUploads() throws Exception { // test with the smaller files for (int i = 0; i < 6; i++) { testUpload(TFTP.BINARY_MODE, files[i]); } } public void testASCIIUploads() throws Exception { // test with the smaller files for (int i = 0; i < 6; i++) { testUpload(TFTP.ASCII_MODE, files[i]); } } public void testHugeUploads() throws Exception { for (int i = 5; i < files.length; i++) { testUpload(TFTP.BINARY_MODE, files[i]); } } public void testHugeDownloads() throws Exception { // test with the smaller files for (int i = 5; i < files.length; i++) { testDownload(TFTP.BINARY_MODE, files[i]); } } private void testDownload(int mode, File file) throws IOException { // Create our TFTP instance to handle the file transfer. TFTPClient tftp = new TFTPClient(); tftp.open(); tftp.setSoTimeout(2000); File out = new File(serverDirectory, filePrefix + "download"); // cleanup old failed runs out.delete(); assertTrue("Couldn't clear output location", !out.exists()); FileOutputStream output = new FileOutputStream(out); tftp.receiveFile(file.getName(), mode, output, "localhost", 6900); output.close(); assertTrue("file not created", out.exists()); assertTrue("files not identical on file " + file, filesIdentical(out, file)); // delete the downloaded file out.delete(); } private void testUpload(int mode, File file) throws Exception { // Create our TFTP instance to handle the file transfer. TFTPClient tftp = new TFTPClient(); tftp.open(); tftp.setSoTimeout(2000); File in = new File(serverDirectory, filePrefix + "upload"); // cleanup old failed runs in.delete(); assertTrue("Couldn't clear output location", !in.exists()); FileInputStream fis = new FileInputStream(file); tftp.sendFile(in.getName(), mode, fis, "localhost", 6900); fis.close(); // need to give the server a bit of time to receive our last packet, and // close out its file buffers, etc. Thread.sleep(100); assertTrue("file not created", in.exists()); assertTrue("files not identical on file " + file, filesIdentical(file, in)); in.delete(); } private boolean filesIdentical(File a, File b) throws IOException { if (!a.exists() || !b.exists()) { return false; } if (a.length() != b.length()) { return false; } InputStream fisA = new BufferedInputStream(new FileInputStream(a)); InputStream fisB = new BufferedInputStream(new FileInputStream(b)); int aBit = fisA.read(); int bBit = fisB.read(); while (aBit != -1) { if (aBit != bBit) { fisA.close(); fisB.close(); return false; } aBit = fisA.read(); bBit = fisB.read(); } fisA.close(); fisB.close(); return true; } } commons-net-2.2/src/test/java/org/apache/commons/net/tftp/TFTPServer.java0000644000175000017500000007421211055252003026275 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.SocketTimeoutException; import java.util.HashSet; import java.util.Iterator; import org.apache.commons.net.io.FromNetASCIIOutputStream; import org.apache.commons.net.io.ToNetASCIIInputStream; /** * A fully multi-threaded tftp server. Can handle multiple clients at the same time. Implements RFC * 1350 and wrapping block numbers for large file support. * * To launch, just create an instance of the class. An IOException will be thrown if the server * fails to start for reasons such as port in use, port denied, etc. * * To stop, use the shutdown method. * * To check to see if the server is still running (or if it stopped because of an error), call the * isRunning() method. * * By default, events are not logged to stdout/stderr. This can be changed with the * setLog and setLogError methods. * *

* Example usage is below: * * * public static void main(String[] args) throws Exception * { * if (args.length != 1) * { * System.out * .println("You must provide 1 argument - the base path for the server to serve from."); * System.exit(1); * } * * TFTPServer ts = new TFTPServer(new File(args[0]), new File(args[0]), GET_AND_PUT); * ts.setSocketTimeout(2000); * * System.out.println("TFTP Server running. Press enter to stop."); * new InputStreamReader(System.in).read(); * * ts.shutdown(); * System.out.println("Server shut down."); * System.exit(0); * } * * * * * @author Dan Armbrust * @since 2.0 */ public class TFTPServer implements Runnable { private static final int DEFAULT_TFTP_PORT = 69; public static enum ServerMode { GET_ONLY, PUT_ONLY, GET_AND_PUT; } private HashSet transfers_ = new HashSet(); private volatile boolean shutdownServer = false; private TFTP serverTftp_; private File serverReadDirectory_; private File serverWriteDirectory_; private int port_; private Exception serverException = null; private ServerMode mode_; /* /dev/null output stream (default) */ private static final PrintStream nullStream = new PrintStream( new OutputStream() { @Override public void write(int b){} @Override public void write(byte[] b) throws IOException {} } ); // don't have access to a logger api, so we will log to these streams, which // by default are set to a no-op logger private PrintStream log_; private PrintStream logError_; private int maxTimeoutRetries_ = 3; private int socketTimeout_; private Thread serverThread; /** * Start a TFTP Server on the default port (69). Gets and Puts occur in the specified * directories. * * The server will start in another thread, allowing this constructor to return immediately. * * If a get or a put comes in with a relative path that tries to get outside of the * serverDirectory, then the get or put will be denied. * * GET_ONLY mode only allows gets, PUT_ONLY mode only allows puts, and GET_AND_PUT allows both. * Modes are defined as int constants in this class. * * @param serverReadDirectory directory for GET requests * @param serverWriteDirectory directory for PUT requests * @param mode A value as specified above. * @throws IOException if the server directory is invalid or does not exist. */ public TFTPServer(File serverReadDirectory, File serverWriteDirectory, ServerMode mode) throws IOException { this(serverReadDirectory, serverWriteDirectory, DEFAULT_TFTP_PORT, mode, null, null); } /** * Start a TFTP Server on the specified port. Gets and Puts occur in the specified directory. * * The server will start in another thread, allowing this constructor to return immediately. * * If a get or a put comes in with a relative path that tries to get outside of the * serverDirectory, then the get or put will be denied. * * GET_ONLY mode only allows gets, PUT_ONLY mode only allows puts, and GET_AND_PUT allows both. * Modes are defined as int constants in this class. * * @param serverReadDirectory directory for GET requests * @param serverWriteDirectory directory for PUT requests * @param mode A value as specified above. * @param log Stream to write log message to. If not provided, uses System.out * @param errorLog Stream to write error messages to. If not provided, uses System.err. * @throws IOException if the server directory is invalid or does not exist. */ public TFTPServer(File serverReadDirectory, File serverWriteDirectory, int port, ServerMode mode, PrintStream log, PrintStream errorLog) throws IOException { port_ = port; mode_ = mode; log_ = (log == null ? nullStream: log); logError_ = (errorLog == null ? nullStream : errorLog); launch(serverReadDirectory, serverWriteDirectory); } /** * Set the max number of retries in response to a timeout. Default 3. Min 0. * * @param retries */ public void setMaxTimeoutRetries(int retries) { if (retries < 0) { throw new RuntimeException("Invalid Value"); } maxTimeoutRetries_ = retries; } /** * Get the current value for maxTimeoutRetries */ public int getMaxTimeoutRetries() { return maxTimeoutRetries_; } /** * Set the socket timeout in milliseconds used in transfers. Defaults to the value here: * http://commons.apache.org/net/apidocs/org/apache/commons/net/tftp/TFTP.html#DEFAULT_TIMEOUT * (5000 at the time I write this) Min value of 10. */ public void setSocketTimeout(int timeout) { if (timeout < 10) { throw new RuntimeException("Invalid Value"); } socketTimeout_ = timeout; } /** * The current socket timeout used during transfers in milliseconds. */ public int getSocketTimeout() { return socketTimeout_; } /* * start the server, throw an error if it can't start. */ private void launch(File serverReadDirectory, File serverWriteDirectory) throws IOException { log_.println("Starting TFTP Server on port " + port_ + ". Read directory: " + serverReadDirectory + " Write directory: " + serverWriteDirectory + " Server Mode is " + mode_); serverReadDirectory_ = serverReadDirectory.getCanonicalFile(); if (!serverReadDirectory_.exists() || !serverReadDirectory.isDirectory()) { throw new IOException("The server read directory " + serverReadDirectory_ + " does not exist"); } serverWriteDirectory_ = serverWriteDirectory.getCanonicalFile(); if (!serverWriteDirectory_.exists() || !serverWriteDirectory.isDirectory()) { throw new IOException("The server write directory " + serverWriteDirectory_ + " does not exist"); } serverTftp_ = new TFTP(); // This is the value used in response to each client. socketTimeout_ = serverTftp_.getDefaultTimeout(); // we want the server thread to listen forever. serverTftp_.setDefaultTimeout(0); serverTftp_.open(port_); serverThread = new Thread(this); serverThread.setDaemon(true); serverThread.start(); } @Override protected void finalize() throws Throwable { shutdown(); } /** * check if the server thread is still running. * * @return true if running, false if stopped. * @throws Exception throws the exception that stopped the server if the server is stopped from * an exception. */ public boolean isRunning() throws Exception { if (shutdownServer && serverException != null) { throw serverException; } return !shutdownServer; } public void run() { try { while (!shutdownServer) { TFTPPacket tftpPacket; tftpPacket = serverTftp_.receive(); TFTPTransfer tt = new TFTPTransfer(tftpPacket); synchronized(transfers_) { transfers_.add(tt); } Thread thread = new Thread(tt); thread.setDaemon(true); thread.start(); } } catch (Exception e) { if (!shutdownServer) { serverException = e; logError_.println("Unexpected Error in TFTP Server - Server shut down! + " + e); } } finally { shutdownServer = true; // set this to true, so the launching thread can check to see if it started. if (serverTftp_ != null && serverTftp_.isOpen()) { serverTftp_.close(); } } } /** * Stop the tftp server (and any currently running transfers) and release all opened network * resources. */ public void shutdown() { shutdownServer = true; synchronized(transfers_) { Iterator it = transfers_.iterator(); while (it.hasNext()) { it.next().shutdown(); } } try { serverTftp_.close(); } catch (RuntimeException e) { // noop } try { serverThread.join(); } catch (InterruptedException e) { // we've done the best we could, return } } /* * An instance of an ongoing transfer. */ private class TFTPTransfer implements Runnable { private TFTPPacket tftpPacket_; private boolean shutdownTransfer = false; TFTP transferTftp_ = null; public TFTPTransfer(TFTPPacket tftpPacket) { tftpPacket_ = tftpPacket; } public void shutdown() { shutdownTransfer = true; try { transferTftp_.close(); } catch (RuntimeException e) { // noop } } public void run() { try { transferTftp_ = new TFTP(); transferTftp_.beginBufferedOps(); transferTftp_.setDefaultTimeout(socketTimeout_); transferTftp_.open(); if (tftpPacket_ instanceof TFTPReadRequestPacket) { handleRead(((TFTPReadRequestPacket) tftpPacket_)); } else if (tftpPacket_ instanceof TFTPWriteRequestPacket) { handleWrite((TFTPWriteRequestPacket) tftpPacket_); } else { log_.println("Unsupported TFTP request (" + tftpPacket_ + ") - ignored."); } } catch (Exception e) { if (!shutdownTransfer) { logError_ .println("Unexpected Error in during TFTP file transfer. Transfer aborted. " + e); } } finally { try { if (transferTftp_ != null && transferTftp_.isOpen()) { transferTftp_.endBufferedOps(); transferTftp_.close(); } } catch (Exception e) { // noop } synchronized(transfers_) { transfers_.remove(this); } } } /* * Handle a tftp read request. */ private void handleRead(TFTPReadRequestPacket trrp) throws IOException, TFTPPacketException { InputStream is = null; try { if (mode_ == ServerMode.PUT_ONLY) { transferTftp_.bufferedSend(new TFTPErrorPacket(trrp.getAddress(), trrp .getPort(), TFTPErrorPacket.ILLEGAL_OPERATION, "Read not allowed by server.")); return; } try { is = new BufferedInputStream(new FileInputStream(buildSafeFile( serverReadDirectory_, trrp.getFilename(), false))); } catch (FileNotFoundException e) { transferTftp_.bufferedSend(new TFTPErrorPacket(trrp.getAddress(), trrp .getPort(), TFTPErrorPacket.FILE_NOT_FOUND, e.getMessage())); return; } catch (Exception e) { transferTftp_.bufferedSend(new TFTPErrorPacket(trrp.getAddress(), trrp .getPort(), TFTPErrorPacket.UNDEFINED, e.getMessage())); return; } if (trrp.getMode() == TFTP.NETASCII_MODE) { is = new ToNetASCIIInputStream(is); } byte[] temp = new byte[TFTPDataPacket.MAX_DATA_LENGTH]; TFTPPacket answer; int block = 1; boolean sendNext = true; int readLength = TFTPDataPacket.MAX_DATA_LENGTH; TFTPDataPacket lastSentData = null; // We are reading a file, so when we read less than the // requested bytes, we know that we are at the end of the file. while (readLength == TFTPDataPacket.MAX_DATA_LENGTH && !shutdownTransfer) { if (sendNext) { readLength = is.read(temp); if (readLength == -1) { readLength = 0; } lastSentData = new TFTPDataPacket(trrp.getAddress(), trrp.getPort(), block, temp, 0, readLength); transferTftp_.bufferedSend(lastSentData); } answer = null; int timeoutCount = 0; while (!shutdownTransfer && (answer == null || !answer.getAddress().equals(trrp.getAddress()) || answer .getPort() != trrp.getPort())) { // listen for an answer. if (answer != null) { // The answer that we got didn't come from the // expected source, fire back an error, and continue // listening. log_.println("TFTP Server ignoring message from unexpected source."); transferTftp_.bufferedSend(new TFTPErrorPacket(answer.getAddress(), answer.getPort(), TFTPErrorPacket.UNKNOWN_TID, "Unexpected Host or Port")); } try { answer = transferTftp_.bufferedReceive(); } catch (SocketTimeoutException e) { if (timeoutCount >= maxTimeoutRetries_) { throw e; } // didn't get an ack for this data. need to resend // it. timeoutCount++; transferTftp_.bufferedSend(lastSentData); continue; } } if (answer == null || !(answer instanceof TFTPAckPacket)) { if (!shutdownTransfer) { logError_ .println("Unexpected response from tftp client during transfer (" + answer + "). Transfer aborted."); } break; } else { // once we get here, we know we have an answer packet // from the correct host. TFTPAckPacket ack = (TFTPAckPacket) answer; if (ack.getBlockNumber() != block) { /* * The origional tftp spec would have called on us to resend the * previous data here, however, that causes the SAS Syndrome. * http://www.faqs.org/rfcs/rfc1123.html section 4.2.3.1 The modified * spec says that we ignore a duplicate ack. If the packet was really * lost, we will time out on receive, and resend the previous data at * that point. */ sendNext = false; } else { // send the next block block++; if (block > 65535) { // wrap the block number block = 0; } sendNext = true; } } } } finally { try { if (is != null) { is.close(); } } catch (IOException e) { // noop } } } /* * handle a tftp write request. */ private void handleWrite(TFTPWriteRequestPacket twrp) throws IOException, TFTPPacketException { OutputStream bos = null; try { if (mode_ == ServerMode.GET_ONLY) { transferTftp_.bufferedSend(new TFTPErrorPacket(twrp.getAddress(), twrp .getPort(), TFTPErrorPacket.ILLEGAL_OPERATION, "Write not allowed by server.")); return; } int lastBlock = 0; String fileName = twrp.getFilename(); try { File temp = buildSafeFile(serverWriteDirectory_, fileName, true); if (temp.exists()) { transferTftp_.bufferedSend(new TFTPErrorPacket(twrp.getAddress(), twrp .getPort(), TFTPErrorPacket.FILE_EXISTS, "File already exists")); return; } bos = new BufferedOutputStream(new FileOutputStream(temp)); if (twrp.getMode() == TFTP.NETASCII_MODE) { bos = new FromNetASCIIOutputStream(bos); } } catch (Exception e) { transferTftp_.bufferedSend(new TFTPErrorPacket(twrp.getAddress(), twrp .getPort(), TFTPErrorPacket.UNDEFINED, e.getMessage())); return; } TFTPAckPacket lastSentAck = new TFTPAckPacket(twrp.getAddress(), twrp.getPort(), 0); transferTftp_.bufferedSend(lastSentAck); while (true) { // get the response - ensure it is from the right place. TFTPPacket dataPacket = null; int timeoutCount = 0; while (!shutdownTransfer && (dataPacket == null || !dataPacket.getAddress().equals(twrp.getAddress()) || dataPacket .getPort() != twrp.getPort())) { // listen for an answer. if (dataPacket != null) { // The data that we got didn't come from the // expected source, fire back an error, and continue // listening. log_.println("TFTP Server ignoring message from unexpected source."); transferTftp_.bufferedSend(new TFTPErrorPacket(dataPacket.getAddress(), dataPacket.getPort(), TFTPErrorPacket.UNKNOWN_TID, "Unexpected Host or Port")); } try { dataPacket = transferTftp_.bufferedReceive(); } catch (SocketTimeoutException e) { if (timeoutCount >= maxTimeoutRetries_) { throw e; } // It didn't get our ack. Resend it. transferTftp_.bufferedSend(lastSentAck); timeoutCount++; continue; } } if (dataPacket != null && dataPacket instanceof TFTPWriteRequestPacket) { // it must have missed our initial ack. Send another. lastSentAck = new TFTPAckPacket(twrp.getAddress(), twrp.getPort(), 0); transferTftp_.bufferedSend(lastSentAck); } else if (dataPacket == null || !(dataPacket instanceof TFTPDataPacket)) { if (!shutdownTransfer) { logError_ .println("Unexpected response from tftp client during transfer (" + dataPacket + "). Transfer aborted."); } break; } else { int block = ((TFTPDataPacket) dataPacket).getBlockNumber(); byte[] data = ((TFTPDataPacket) dataPacket).getData(); int dataLength = ((TFTPDataPacket) dataPacket).getDataLength(); int dataOffset = ((TFTPDataPacket) dataPacket).getDataOffset(); if (block > lastBlock || (lastBlock == 65535 && block == 0)) { // it might resend a data block if it missed our ack // - don't rewrite the block. bos.write(data, dataOffset, dataLength); lastBlock = block; } lastSentAck = new TFTPAckPacket(twrp.getAddress(), twrp.getPort(), block); transferTftp_.bufferedSend(lastSentAck); if (dataLength < TFTPDataPacket.MAX_DATA_LENGTH) { // end of stream signal - The tranfer is complete. bos.close(); // But my ack may be lost - so listen to see if I // need to resend the ack. for (int i = 0; i < maxTimeoutRetries_; i++) { try { dataPacket = transferTftp_.bufferedReceive(); } catch (SocketTimeoutException e) { // this is the expected route - the client // shouldn't be sending any more packets. break; } if (dataPacket != null && (!dataPacket.getAddress().equals(twrp.getAddress()) || dataPacket .getPort() != twrp.getPort())) { // make sure it was from the right client... transferTftp_ .bufferedSend(new TFTPErrorPacket(dataPacket .getAddress(), dataPacket.getPort(), TFTPErrorPacket.UNKNOWN_TID, "Unexpected Host or Port")); } else { // This means they sent us the last // datapacket again, must have missed our // ack. resend it. transferTftp_.bufferedSend(lastSentAck); } } // all done. break; } } } } finally { if (bos != null) { bos.close(); } } } /* * Utility method to make sure that paths provided by tftp clients do not get outside of the * serverRoot directory. */ private File buildSafeFile(File serverDirectory, String fileName, boolean createSubDirs) throws IOException { File temp = new File(serverDirectory, fileName); temp = temp.getCanonicalFile(); if (!isSubdirectoryOf(serverDirectory, temp)) { throw new IOException("Cannot access files outside of tftp server root."); } // ensure directory exists (if requested) if (createSubDirs) { createDirectory(temp.getParentFile()); } return temp; } /* * recursively create subdirectories */ private void createDirectory(File file) throws IOException { File parent = file.getParentFile(); if (parent == null) { throw new IOException("Unexpected error creating requested directory"); } if (!parent.exists()) { // recurse... createDirectory(parent); } if (parent.isDirectory()) { if (file.isDirectory()) { return; } boolean result = file.mkdir(); if (!result) { throw new IOException("Couldn't create requested directory"); } } else { throw new IOException( "Invalid directory path - file in the way of requested folder"); } } /* * recursively check to see if one directory is a parent of another. */ private boolean isSubdirectoryOf(File parent, File child) { File childsParent = child.getParentFile(); if (childsParent == null) { return false; } if (childsParent.equals(parent)) { return true; } else { return isSubdirectoryOf(parent, childsParent); } } } /** * Set the stream object to log debug / informational messages. By default, this is a no-op * * @param log */ public void setLog(PrintStream log) { this.log_ = log; } /** * Set the stream object to log error messsages. By default, this is a no-op * * @param logError */ public void setLogError(PrintStream logError) { this.logError_ = logError; } } commons-net-2.2/src/test/java/org/apache/commons/net/tftp/TFTPServerPathTest.java0000644000175000017500000001234011014672436027757 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.tftp; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import org.apache.commons.net.tftp.TFTPServer.ServerMode; import junit.framework.TestCase; /** * Some basic tests to ensure that the TFTP Server is honoring its read/write mode, and preventing * files from being read or written from outside of the assigned roots. * * @author Dan Armbrust * */ public class TFTPServerPathTest extends TestCase { String filePrefix = "tftp-"; File serverDirectory = new File(System.getProperty("java.io.tmpdir")); public void testReadOnly() throws IOException { // Start a read-only server TFTPServer tftpS = new TFTPServer(serverDirectory, serverDirectory, 6900, ServerMode.GET_ONLY, null, null); // Create our TFTP instance to handle the file transfer. TFTPClient tftp = new TFTPClient(); tftp.open(); tftp.setSoTimeout(2000); // make a file to work with. File file = new File(serverDirectory, filePrefix + "source.txt"); file.createNewFile(); // Read the file from the tftp server. File out = new File(serverDirectory, filePrefix + "out"); // cleanup old failed runs out.delete(); assertTrue("Couldn't clear output location", !out.exists()); FileOutputStream output = new FileOutputStream(out); tftp.receiveFile(file.getName(), TFTP.BINARY_MODE, output, "localhost", 6900); output.close(); assertTrue("file not created", out.exists()); out.delete(); FileInputStream fis = new FileInputStream(file); try { tftp.sendFile(out.getName(), TFTP.BINARY_MODE, fis, "localhost", 6900); fail("Server allowed write"); } catch (IOException e) { // expected path } fis.close(); file.delete(); tftpS.shutdown(); } public void testWriteOnly() throws IOException { // Start a write-only server TFTPServer tftpS = new TFTPServer(serverDirectory, serverDirectory, 6900, ServerMode.PUT_ONLY, null, null); // Create our TFTP instance to handle the file transfer. TFTPClient tftp = new TFTPClient(); tftp.open(); tftp.setSoTimeout(2000); // make a file to work with. File file = new File(serverDirectory, filePrefix + "source.txt"); file.createNewFile(); File out = new File(serverDirectory, filePrefix + "out"); // cleanup old failed runs out.delete(); assertTrue("Couldn't clear output location", !out.exists()); FileOutputStream output = new FileOutputStream(out); try { tftp.receiveFile(file.getName(), TFTP.BINARY_MODE, output, "localhost", 6900); fail("Server allowed read"); } catch (IOException e) { // expected path } output.close(); out.delete(); FileInputStream fis = new FileInputStream(file); tftp.sendFile(out.getName(), TFTP.BINARY_MODE, fis, "localhost", 6900); fis.close(); assertTrue("file not created", out.exists()); // cleanup file.delete(); out.delete(); tftpS.shutdown(); } public void testWriteOutsideHome() throws IOException { // Start a server TFTPServer tftpS = new TFTPServer(serverDirectory, serverDirectory, 6900, ServerMode.GET_AND_PUT, null, null); // Create our TFTP instance to handle the file transfer. TFTPClient tftp = new TFTPClient(); tftp.open(); File file = new File(serverDirectory, filePrefix + "source.txt"); file.createNewFile(); assertFalse("test construction error", new File(serverDirectory, "../foo").exists()); FileInputStream fis = new FileInputStream(file); try { tftp.sendFile("../foo", TFTP.BINARY_MODE, fis, "localhost", 6900); fail("Server allowed write!"); } catch (IOException e) { // expected path } fis.close(); assertFalse("file created when it should not have been", new File(serverDirectory, "../foo").exists()); // cleanup file.delete(); tftpS.shutdown(); } } commons-net-2.2/src/test/java/org/apache/commons/net/pop3/0000755000175000017500000000000011617452465023406 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/pop3/POP3ConstructorTest.java0000644000175000017500000001331311347047772030102 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; import junit.framework.TestCase; import java.io.Reader; /** * @author [Net] * @version $Id: POP3ConstructorTest.java 922741 2010-03-14 02:54:50Z sebb $ * * The POP3* tests all presume the existence of the following parameters: * mailserver: localhost (running on the default port 110) * account: username=test; password=password * account: username=alwaysempty; password=password. * mail: At least four emails in the test account and zero emails * in the alwaysempty account * * If this won't work for you, you can change these parameters in the * TestSetupParameters class. * * The tests were originally run on a default installation of James. * Your mileage may vary based on the POP3 server you run the tests against. * Some servers are more standards-compliant than others. */ public class POP3ConstructorTest extends TestCase { String user = TestSetupParameters.user; String emptyUser = TestSetupParameters.emptyuser; String password = TestSetupParameters.password; String mailhost = TestSetupParameters.mailhost; /** * */ public POP3ConstructorTest(String name) { super(name); } /** * This test will ensure that the constants are not inadvertently changed. * If the constants are changed in org.apache.commons.net.pop3 for some * reason, this test will have to be updated. */ public void testConstants() { //From POP3 assertEquals(110, POP3.DEFAULT_PORT); assertEquals(-1, POP3.DISCONNECTED_STATE); assertEquals(0, POP3.AUTHORIZATION_STATE); assertEquals(1, POP3.TRANSACTION_STATE); assertEquals(2, POP3.UPDATE_STATE); //From POP3Command assertEquals(0, POP3Command.USER); assertEquals(1, POP3Command.PASS); assertEquals(2, POP3Command.QUIT); assertEquals(3, POP3Command.STAT); assertEquals(4, POP3Command.LIST); assertEquals(5, POP3Command.RETR); assertEquals(6, POP3Command.DELE); assertEquals(7, POP3Command.NOOP); assertEquals(8, POP3Command.RSET); assertEquals(9, POP3Command.APOP); assertEquals(10, POP3Command.TOP); assertEquals(11, POP3Command.UIDL); } /** * Test the default constructor * */ public void testPOP3DefaultConstructor() { POP3 pop = new POP3(); assertEquals(110, pop.getDefaultPort()); assertEquals(POP3.DISCONNECTED_STATE, pop.getState()); assertNull(pop._reader); assertNotNull(pop._replyLines); } /** * Test the default constructor * */ public void testPOP3ClientStateTransition() throws Exception { POP3Client pop = new POP3Client(); //Initial state assertEquals(110, pop.getDefaultPort()); assertEquals(POP3.DISCONNECTED_STATE, pop.getState()); assertNull(pop._reader); assertNotNull(pop._replyLines); //Now connect pop.connect(mailhost); assertEquals(POP3.AUTHORIZATION_STATE, pop.getState()); //Now authenticate pop.login(user, password); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); //Now do a series of commands and make sure the state stays as it should pop.noop(); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); pop.status(); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); //Make sure we have at least one message to test POP3MessageInfo[] msg = pop.listMessages(); if (msg.length > 0) { pop.deleteMessage(1); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); pop.reset(); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); pop.listMessage(1); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); pop.listMessages(); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); pop.listUniqueIdentifier(1); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); pop.listUniqueIdentifiers(); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); Reader r = pop.retrieveMessage(1); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); //Add some sleep here to handle network latency while(!r.ready()) { Thread.sleep(10); } r.close(); r = null; r = pop.retrieveMessageTop(1, 10); assertEquals(POP3.TRANSACTION_STATE, pop.getState()); //Add some sleep here to handle network latency while(!r.ready()) { Thread.sleep(10); } r.close(); r = null; } //Now logout pop.logout(); assertEquals(POP3.UPDATE_STATE, pop.getState()); } } commons-net-2.2/src/test/java/org/apache/commons/net/pop3/POP3ClientTest.java0000644000175000017500000001117011347047772026772 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; import junit.framework.TestCase; import java.net.InetAddress; import java.io.IOException; /** * @author [Net] * @version $Id: POP3ClientTest.java 922741 2010-03-14 02:54:50Z sebb $ * * The POP3* tests all presume the existence of the following parameters: * mailserver: localhost (running on the default port 110) * account: username=test; password=password * account: username=alwaysempty; password=password. * mail: At least four emails in the test account and zero emails * in the alwaysempty account * * If this won't work for you, you can change these parameters in the * TestSetupParameters class. * * The tests were originally run on a default installation of James. * Your mileage may vary based on the POP3 server you run the tests against. * Some servers are more standards-compliant than others. */ public class POP3ClientTest extends TestCase { POP3Client p = null; String user = TestSetupParameters.user; String emptyUser = TestSetupParameters.emptyuser; String password = TestSetupParameters.password; String mailhost = TestSetupParameters.mailhost; /** * */ public POP3ClientTest(String name) { super(name); } private void reset() throws IOException { //Case where this is the first time reset is called if (p == null) { //Do nothing } else if (p.isConnected()) { p.disconnect(); } p = null; p = new POP3Client(); } private void connect() throws Exception { p.connect(InetAddress.getByName(mailhost)); assertTrue(p.isConnected()); assertEquals(POP3.AUTHORIZATION_STATE, p.getState()); } private void login() throws Exception { assertTrue(p.login(user, password)); assertEquals(POP3.TRANSACTION_STATE, p.getState()); } /** * Simple test to logon to a valid server using a valid * user name and password. */ public void testValidLoginWithNameAndPassword() throws Exception { reset(); connect(); //Try with a valid user login(); } /** * */ public void testInvalidLoginWithBadName() throws Exception { reset(); connect(); //Try with an invalid user that doesn't exist assertFalse(p.login("badusername", password)); } /** * */ public void testInvalidLoginWithBadPassword() throws Exception { reset(); connect(); //Try with a bad password assertFalse(p.login(user, "badpassword")); } /** * Test to try to run the login method from the * disconnected, transaction and update states */ public void testLoginFromWrongState() throws Exception { reset(); //Not currently connected, not in authorization state //Try to login with good name/password assertFalse(p.login(user, password)); //Now connect and set the state to 'transaction' and try again connect(); p.setState(POP3.TRANSACTION_STATE); assertFalse(p.login(user, password)); p.disconnect(); //Now connect and set the state to 'update' and try again connect(); p.setState(POP3.UPDATE_STATE); assertFalse(p.login(user, password)); p.disconnect(); } /** * * */ public void testLogoutFromAllStates() throws Exception { //From 'transaction' state reset(); connect(); login(); assertTrue(p.logout()); assertEquals(POP3.UPDATE_STATE, p.getState()); //From 'update' state reset(); connect(); login(); p.setState(POP3.UPDATE_STATE); assertTrue(p.logout()); } } commons-net-2.2/src/test/java/org/apache/commons/net/pop3/TestSetupParameters.java0000644000175000017500000000365611014672436030240 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; /** * @author [Net] * @version $Id: TestSetupParameters.java 658518 2008-05-21 01:04:30Z sebb $ * * The POP3* tests all presume the existence of the following parameters: * mailserver: localhost (running on the default port 110) * account: username=test; password=password * account: username=alwaysempty; password=password. * mail: At least four emails in the test account and zero emails * in the alwaysempty account * * If this won't work for you, you can change these parameters in the * TestSetupParameters class. * * The tests were originally run on a default installation of James. * Your mileage may vary based on the POP3 server you run the tests against. * Some servers are more standards-compliant than others. */ public class TestSetupParameters { public static final String user = "test"; public static final String emptyuser = "alwaysempty"; public static final String password = "password"; public static final String mailhost = "localhost"; //Cannot be instantiated private TestSetupParameters() {} } commons-net-2.2/src/test/java/org/apache/commons/net/pop3/POP3ClientCommandsTest.java0000644000175000017500000003563011364045325030452 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.pop3; import junit.framework.TestCase; import java.net.InetAddress; import java.io.IOException; import java.io.Reader; /** * @author [Net] * @version $Id: POP3ClientCommandsTest.java 936824 2010-04-22 13:10:45Z sebb $ * * The POP3* tests all presume the existence of the following parameters: * mailserver: localhost (running on the default port 110) * account: username=test; password=password * account: username=alwaysempty; password=password. * mail: At least four emails in the test account and zero emails * in the alwaysempty account * * If this won't work for you, you can change these parameters in the * TestSetupParameters class. * * The tests were originally run on a default installation of James. * Your mileage may vary based on the POP3 server you run the tests against. * Some servers are more standards-compliant than others. */ public class POP3ClientCommandsTest extends TestCase { POP3Client p = null; String user = TestSetupParameters.user; String emptyUser = TestSetupParameters.emptyuser; String password = TestSetupParameters.password; String mailhost = TestSetupParameters.mailhost; /** * */ public POP3ClientCommandsTest(String name) { super(name); } private void reset() throws IOException { //Case where this is the first time reset is called if (p == null) { //Do nothing } else if (p.isConnected()) { p.disconnect(); } p = null; p = new POP3Client(); } private void connect() throws Exception { p.connect(InetAddress.getByName(mailhost)); assertTrue(p.isConnected()); assertEquals(POP3.AUTHORIZATION_STATE, p.getState()); } private void login() throws Exception { assertTrue(p.login(user, password)); assertEquals(POP3.TRANSACTION_STATE, p.getState()); } /** * * */ public void testNoopCommand() throws Exception { reset(); connect(); //Should fail before authorization assertFalse(p.noop()); //Should pass in transaction state login(); assertTrue(p.noop()); //Should fail in update state p.setState(POP3.UPDATE_STATE); assertFalse(p.noop()); } /** * * */ public void testStatus() throws Exception { reset(); connect(); //Should fail in authorization state assertNull(p.status()); //Should pass on a mailbox with mail in it login(); POP3MessageInfo msg = p.status(); assertTrue(msg.number > 0); assertTrue(msg.size > 0); assertNull(msg.identifier); p.logout(); //Should also pass on a mailbox with no mail in it reset(); connect(); assertTrue(p.login(emptyUser, password)); POP3MessageInfo msg2 = p.status(); assertEquals(0, msg2.number); assertEquals(0, msg2.size); assertNull(msg2.identifier); p.logout(); //Should fail in the 'update' state reset(); connect(); login(); p.setState(POP3.UPDATE_STATE); assertNull(p.status()); } /** * * */ public void testListMessagesOnFullMailbox() throws Exception { reset(); connect(); login(); POP3MessageInfo[] msg = p.listMessages(); assertTrue(msg.length > 0); for(int i = 0; i < msg.length; i++) { assertNotNull(msg[i]); assertEquals(i+1, msg[i].number); assertTrue(msg[i].size > 0); assertNull(msg[i].identifier); } //Now test from the update state p.setState(POP3.UPDATE_STATE); msg = p.listMessages(); assertNull(msg); } /** * * */ public void testListMessageOnFullMailbox() throws Exception { reset(); connect(); login(); //The first message is always at index 1 POP3MessageInfo msg = p.listMessage(1); assertNotNull(msg); assertEquals(1, msg.number); assertTrue(msg.size > 0); assertNull(msg.identifier); //Now retrieve a message from index 0 msg = p.listMessage(0); assertNull(msg); //Now retrieve a msg that is not there msg = p.listMessage(100000); assertNull(msg); //Now retrieve a msg with a negative index msg = p.listMessage(-2); assertNull(msg); //Now try to get a valid message from the update state p.setState(POP3.UPDATE_STATE); msg = p.listMessage(1); assertNull(msg); } /** * * */ public void testListMessagesOnEmptyMailbox() throws Exception { reset(); connect(); assertTrue(p.login(emptyUser, password)); POP3MessageInfo[] msg = p.listMessages(); assertEquals(0, msg.length); //Now test from the update state p.setState(POP3.UPDATE_STATE); msg = p.listMessages(); assertNull(msg); } /** * * */ public void testListMessageOnEmptyMailbox() throws Exception { reset(); connect(); assertTrue(p.login(emptyUser, password)); //The first message is always at index 1 POP3MessageInfo msg = p.listMessage(1); assertNull(msg); } /** * * */ public void testListUniqueIDsOnFullMailbox() throws Exception { reset(); connect(); login(); POP3MessageInfo[] msg = p.listUniqueIdentifiers(); assertTrue(msg.length > 0); for(int i = 0; i < msg.length; i++) { assertNotNull(msg[i]); assertEquals(i + 1, msg[i].number); assertNotNull(msg[i].identifier); } //Now test from the update state p.setState(POP3.UPDATE_STATE); msg = p.listUniqueIdentifiers(); assertNull(msg); } /** * * */ public void testListUniqueIDOnFullMailbox() throws Exception { reset(); connect(); login(); //The first message is always at index 1 POP3MessageInfo msg = p.listUniqueIdentifier(1); assertNotNull(msg); assertEquals(1, msg.number); assertNotNull(msg.identifier); //Now retrieve a message from index 0 msg = p.listUniqueIdentifier(0); assertNull(msg); //Now retrieve a msg that is not there msg = p.listUniqueIdentifier(100000); assertNull(msg); //Now retrieve a msg with a negative index msg = p.listUniqueIdentifier(-2); assertNull(msg); //Now try to get a valid message from the update state p.setState(POP3.UPDATE_STATE); msg = p.listUniqueIdentifier(1); assertNull(msg); } /** * * */ public void testListUniqueIDsOnEmptyMailbox() throws Exception { reset(); connect(); assertTrue(p.login(emptyUser, password)); POP3MessageInfo[] msg = p.listUniqueIdentifiers(); assertEquals(0, msg.length); //Now test from the update state p.setState(POP3.UPDATE_STATE); msg = p.listUniqueIdentifiers(); assertNull(msg); } /** * * */ public void testListUniqueIdentifierOnEmptyMailbox() throws Exception { reset(); connect(); assertTrue(p.login(emptyUser, password)); //The first message is always at index 1 POP3MessageInfo msg = p.listUniqueIdentifier(1); assertNull(msg); } /** * * */ public void testRetrieveMessageOnFullMailbox() throws Exception { reset(); connect(); login(); int reportedSize = 0; int actualSize = 0; POP3MessageInfo[] msg = p.listMessages(); assertTrue(msg.length > 0); for (int i = msg.length; i > 0; i--) { reportedSize = msg[i - 1].size; Reader r = p.retrieveMessage(i); assertNotNull(r); int delaycount = 0; if (!r.ready()) { //Give the reader time to get the message //from the server Thread.sleep(500); delaycount++; //but don't wait too long if (delaycount == 4) { break; } } while(r.ready()) { r.read(); actualSize++; } //Due to variations in line termination //on different platforms, the actual //size may vary slightly. On Win2KPro, the //actual size is 2 bytes larger than the reported //size. assertTrue(actualSize >= reportedSize); } } /** * * */ public void testRetrieveMessageOnEmptyMailbox() throws Exception { reset(); connect(); assertTrue(p.login(emptyUser, password)); assertNull(p.retrieveMessage(1)); } /** * * */ public void testRetrieveMessageShouldFails() throws Exception { reset(); connect(); login(); //Try to get message 0 assertNull(p.retrieveMessage(0)); //Try to get a negative message assertNull(p.retrieveMessage(-2)); //Try to get a message that is not there assertNull(p.retrieveMessage(100000)); //Change states and try to get a valid message p.setState(POP3.UPDATE_STATE); assertNull(p.retrieveMessage(1)); } /** * * */ public void testRetrieveMessageTopOnFullMailbox() throws Exception { reset(); connect(); login(); int numLines = 10; POP3MessageInfo[] msg = p.listMessages(); assertTrue(msg.length > 0); for (int i = 0; i < msg.length; i++) { Reader r = p.retrieveMessageTop(i + 1, numLines); assertNotNull(r); r.close(); r = null; } } /** * * */ public void testRetrieveOverSizedMessageTopOnFullMailbox() throws Exception { reset(); connect(); login(); int reportedSize = 0; int actualSize = 0; POP3MessageInfo msg = p.listMessage(1); reportedSize = msg.size; //Now try to retrieve more lines than exist in the message Reader r = p.retrieveMessageTop(1, 100000); assertNotNull(r); int delaycount = 0; while(!r.ready()) { //Give the reader time to get the message //from the server Thread.sleep(500); delaycount++; //but don't wait too long if (delaycount == 4) { break; } } while(r.ready()) { r.read(); actualSize++; } //Due to variations in line termination //on different platforms, the actual //size may vary slightly. On Win2KPro, the //actual size is 2 bytes larger than the reported //size. assertTrue(actualSize >= reportedSize); } /** * * */ public void testRetrieveMessageTopOnEmptyMailbox() throws Exception { reset(); connect(); assertTrue(p.login(emptyUser, password)); assertNull(p.retrieveMessageTop(1, 10)); } /** * * */ public void testRetrieveMessageTopShouldFails() throws Exception { reset(); connect(); login(); //Try to get message 0 assertNull(p.retrieveMessageTop(0, 10)); //Try to get a negative message assertNull(p.retrieveMessageTop(-2, 10)); //Try to get a message that is not there assertNull(p.retrieveMessageTop(100000, 10)); //Change states and try to get a valid message p.setState(POP3.UPDATE_STATE); assertNull(p.retrieveMessageTop(1, 10)); } public void testDeleteWithReset() throws Exception { reset(); connect(); login(); //Get the original number of messages POP3MessageInfo[] msg = p.listMessages(); int numMessages = msg.length; int numDeleted = 0; //Now delete some and logout for (int i = 0; i < numMessages - 1; i ++) { p.deleteMessage(i + 1); numDeleted++; } //Check to see that they are marked as deleted assertEquals(numMessages, (numDeleted + 1)); //Now reset to unmark the messages as deleted p.reset(); //Logout and come back in p.logout(); reset(); connect(); login(); //Get the new number of messages, because of //reset, new number should match old number msg = p.listMessages(); assertEquals(numMessages, msg.length); } public void testDelete() throws Exception { reset(); connect(); login(); //Get the original number of messages POP3MessageInfo[] msg = p.listMessages(); int numMessages = msg.length; int numDeleted = 0; //Now delete some and logout for (int i = 0; i < numMessages - 3; i ++) { p.deleteMessage(i + 1); numDeleted++; } //Check to see that they are marked as deleted assertEquals(numMessages, (numDeleted + 3)); //Logout and come back in p.logout(); reset(); connect(); login(); //Get the new number of messages, because of //reset, new number should match old number msg = p.listMessages(); assertEquals(numMessages - numDeleted, msg.length); } public void testResetAndDeleteShouldFails() throws Exception { reset(); connect(); login(); p.setState(POP3.UPDATE_STATE); assertFalse(p.reset()); assertFalse(p.deleteMessage(1)); } } commons-net-2.2/src/test/java/org/apache/commons/net/telnet/0000755000175000017500000000000011617452466024021 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/telnet/TelnetClientTest.java0000644000175000017500000006671711364045325030126 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import junit.framework.TestCase; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; /*** * JUnit test class for TelnetClient.s * Implements protocol compliance tests *

* @author Bruno D'Avanzo ***/ public class TelnetClientTest extends TestCase implements TelnetNotificationHandler { /** * Handy holder to hold both sides of the connection * used in testing for clarity. */ private class TestConnection { TelnetTestSimpleServer server; TelnetClient client; int port; TestConnection( TelnetTestSimpleServer server, TelnetClient client, int port) { this.server = server; this.client = client; this.port = port; } protected void close() { TelnetClientTest.this.closeConnection( this.server, this.client, this.port); } } // four connections with different properties // to use in tests. private TestConnection STANDARD; private TestConnection OPTIONS; private TestConnection ANSI; private TestConnection NOREAD; private int NUM_CONNECTIONS = 4; protected int numdo = 0; protected int numdont = 0; protected int numwill = 0; protected int numwont = 0; /*** * open connections needed for the tests for the test. ***/ @Override protected void setUp() throws Exception { super.setUp(); for (int port = 3333, socket = 0; socket < NUM_CONNECTIONS && port < 4000; port++) { TelnetTestSimpleServer server = null; TelnetClient client = null; try { server = new TelnetTestSimpleServer(port); switch (socket) { case 0: client = new TelnetClient(); // redundant but makes code clearer. client.setReaderThread(true); break; case 1: client = new TelnetClient(); TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false); EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false); SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true); client.addOptionHandler(ttopt); client.addOptionHandler(echoopt); client.addOptionHandler(gaopt); break; case 2: client = new TelnetClient("ANSI"); break; case 3: client = new TelnetClient(); client.setReaderThread(false); break; } client.connect("127.0.0.1", port); switch (socket) { case 0: STANDARD = new TestConnection(server, client, port); break; case 1: OPTIONS = new TestConnection(server, client, port); break; case 2: ANSI = new TestConnection(server, client, port); break; case 3: NOREAD = new TestConnection(server, client, port); break; } // only increment socket number on success socket++; } catch (IOException e) { closeConnection(server, client, port); System.err.println("failed to open client-server connection on port " + port); } } Thread.sleep(1000); } /* * @throws java.lang.Exception */ @Override protected void tearDown() throws Exception { NOREAD.close(); ANSI.close(); OPTIONS.close(); STANDARD.close(); try { Thread.sleep(1000); } catch (InterruptedException ie) { //do nothing } super.tearDown(); } void closeConnection(TelnetTestSimpleServer server, TelnetClient client, int port) { if (server != null) { server.disconnect(); server.stop(); } try { if (client != null) { client.disconnect(); } } catch (IOException e) { System.err.println("failed to close client-server connection on port " + port); System.err.println("ERROR in closeConnection(), "+ e.getMessage()); } } /*** * tests the initial condition of the sessions ***/ public void testInitial() throws Exception { boolean connect1_ok = false; boolean connect2_ok = false; boolean connect3_ok = false; boolean init2_ok = false; boolean add_invalid_ok1 = false; boolean add_invalid_ok2 = false; byte buffread2[] = new byte[9]; byte expected2[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD, }; SimpleOptionHandler hand = new SimpleOptionHandler(550); try { STANDARD.client.addOptionHandler(hand); } catch (Exception e) { add_invalid_ok1 = true; } try { OPTIONS.client.addOptionHandler(hand); } catch (Exception e) { add_invalid_ok2 = true; } InputStream is1 = STANDARD.server.getInputStream(); Thread.sleep(1000); if(is1.available() == 0) { connect1_ok = true; } Thread.sleep(1000); InputStream is2 = OPTIONS.server.getInputStream(); if(is2.available() == 9) { is2.read(buffread2); connect2_ok = true; if(equalBytes(buffread2, expected2)) init2_ok = true; } InputStream is3 = ANSI.server.getInputStream(); Thread.sleep(1000); if(is3.available() == 0) { connect3_ok = true; } assertTrue(connect1_ok); assertTrue(connect2_ok); assertTrue(connect3_ok); assertTrue(!STANDARD.client.getLocalOptionState(TelnetOption.ECHO)); assertTrue(!STANDARD.client.getRemoteOptionState(TelnetOption.ECHO)); assertTrue(!OPTIONS.client.getLocalOptionState(TelnetOption.ECHO)); assertTrue(!OPTIONS.client.getRemoteOptionState(TelnetOption.ECHO)); assertTrue(!ANSI.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE)); assertTrue(!ANSI.client.getRemoteOptionState(TelnetOption.TERMINAL_TYPE)); assertTrue(init2_ok); assertTrue(add_invalid_ok1); assertTrue(add_invalid_ok2); } /*** * protocol compliance test for option negotiation ***/ public void testOptionNegotiation() throws Exception { boolean negotiation1_ok = false; byte buffread1[] = new byte[6]; byte send1[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) 15, }; byte expected1[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) 15, }; boolean negotiation2_ok = false; byte buffread2[] = new byte[9]; byte send2[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte expected2[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte buffread2b[] = new byte[11]; byte send2b[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 1, (byte) TelnetCommand.IAC, (byte) TelnetCommand.SE, }; byte expected2b[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 0, (byte) 'V', (byte) 'T', (byte) '1', (byte) '0', (byte) '0', (byte) TelnetCommand.IAC, (byte) TelnetCommand.SE, }; boolean negotiation3_ok = false; byte buffread3[] = new byte[6]; byte send3[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte expected3[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte buffread3b[] = new byte[10]; byte send3b[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 1, (byte) TelnetCommand.IAC, (byte) TelnetCommand.SE, }; byte expected3b[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 0, (byte) 'A', (byte) 'N', (byte) 'S', (byte) 'I', (byte) TelnetCommand.IAC, (byte) TelnetCommand.SE, }; InputStream is1 = STANDARD.server.getInputStream(); OutputStream os1 = STANDARD.server.getOutputStream(); is1.skip(is1.available()); os1.write(send1); os1.flush(); Thread.sleep(1000); if(is1.available() == 6) { is1.read(buffread1); if(equalBytes(buffread1, expected1)) negotiation1_ok = true; } InputStream is2 = OPTIONS.server.getInputStream(); OutputStream os2 = OPTIONS.server.getOutputStream(); Thread.sleep(1000); is2.skip(is2.available()); os2.write(send2); os2.flush(); Thread.sleep(1000); if(is2.available() == 9) { is2.read(buffread2); if(equalBytes(buffread2, expected2)) negotiation2_ok = true; if(negotiation2_ok) { negotiation2_ok = false; os2.write(send2b); os2.flush(); Thread.sleep(1000); if(is2.available() == 11) { is2.read(buffread2b); if(equalBytes(buffread2b, expected2b)) negotiation2_ok = true; } } } InputStream is3 = ANSI.server.getInputStream(); OutputStream os3 = ANSI.server.getOutputStream(); Thread.sleep(1000); is3.skip(is3.available()); os3.write(send3); os3.flush(); Thread.sleep(1000); if(is3.available() == 6) { is3.read(buffread3); if(equalBytes(buffread3, expected3)) negotiation3_ok = true; if(negotiation3_ok) { negotiation3_ok = false; os3.write(send3b); os3.flush(); Thread.sleep(1000); if(is3.available() == 10) { is3.read(buffread3b); if(equalBytes(buffread3b, expected3b)) negotiation3_ok = true; } } } assertTrue(negotiation1_ok); assertTrue(negotiation2_ok); assertTrue(negotiation3_ok); assertTrue(!STANDARD.client.getLocalOptionState(15)); assertTrue(!STANDARD.client.getRemoteOptionState(15)); assertTrue(!STANDARD.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE)); assertTrue(!OPTIONS.client.getLocalOptionState(TelnetOption.ECHO)); assertTrue(!OPTIONS.client.getRemoteOptionState(TelnetOption.ECHO)); assertTrue(OPTIONS.client.getLocalOptionState(TelnetOption.SUPPRESS_GO_AHEAD)); assertTrue(!OPTIONS.client.getRemoteOptionState(TelnetOption.SUPPRESS_GO_AHEAD)); assertTrue(OPTIONS.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE)); assertTrue(ANSI.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE)); assertTrue(!OPTIONS.client.getLocalOptionState(TelnetOption.ECHO)); } /*** * protocol compliance test for option renegotiation ***/ public void testOptionRenegotiation() throws Exception { boolean negotiation1_ok = false; byte buffread[] = new byte[6]; byte send[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte expected[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte buffread2[] = new byte[3]; byte send2[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.ECHO, }; byte expected2[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.ECHO, }; InputStream is = OPTIONS.server.getInputStream(); OutputStream os = OPTIONS.server.getOutputStream(); Thread.sleep(1000); is.skip(is.available()); os.write(send); os.flush(); Thread.sleep(1000); if(is.available() == 6) { is.read(buffread); if(equalBytes(buffread, expected)) negotiation1_ok = true; if(negotiation1_ok) { negotiation1_ok = false; os.write(send2); os.flush(); Thread.sleep(1000); if(is.available() == 3) { is.read(buffread2); if(equalBytes(buffread2, expected2)) negotiation1_ok = true; } } } assertTrue(negotiation1_ok); assertTrue(!OPTIONS.client.getLocalOptionState(TelnetOption.ECHO)); } /*** * test of option negotiation notification ***/ public void testNotification() throws Exception { byte buffread1[] = new byte[6]; byte send1[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) 15, }; byte buffread2[] = new byte[9]; byte send2[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte buffread2b[] = new byte[11]; numdo = 0; numdont = 0; numwill = 0; numwont = 0; OPTIONS.client.registerNotifHandler(this); InputStream is1 = STANDARD.server.getInputStream(); OutputStream os1 = STANDARD.server.getOutputStream(); is1.skip(is1.available()); os1.write(send1); os1.flush(); Thread.sleep(500); if(is1.available() > 0) { is1.read(buffread1); } InputStream is2 = OPTIONS.server.getInputStream(); OutputStream os2 = OPTIONS.server.getOutputStream(); Thread.sleep(500); is2.skip(is2.available()); os2.write(send2); os2.flush(); Thread.sleep(500); if(is2.available() > 0) { is2.read(buffread2); Thread.sleep(1000); if(is2.available() > 0) { is2.read(buffread2b); } } assertEquals(2, numdo); assertEquals(1, numdont); assertEquals(1, numwont); assertEquals(0, numwill); } /*** * protocol compliance test in case of option handler removal ***/ public void testDeleteOptionHandler() throws Exception { boolean remove_ok = false; boolean remove_invalid_ok1 = false; boolean remove_invalid_ok2 = false; byte buffread[] = new byte[6]; byte send[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; byte expected[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD }; InputStream is = OPTIONS.server.getInputStream(); OutputStream os = OPTIONS.server.getOutputStream(); Thread.sleep(1000); is.skip(is.available()); os.write(send); os.flush(); Thread.sleep(1000); if(is.available() == 0) { OPTIONS.client.deleteOptionHandler(TelnetOption.SUPPRESS_GO_AHEAD); Thread.sleep(1000); if(is.available() == 6) { is.read(buffread); if(equalBytes(buffread, expected)) remove_ok = true; } } try { OPTIONS.client.deleteOptionHandler(TelnetOption.SUPPRESS_GO_AHEAD); } catch (Exception e) { remove_invalid_ok1 = true; } try { OPTIONS.client.deleteOptionHandler(550); } catch (Exception e) { remove_invalid_ok2 = true; } assertTrue(remove_ok); assertTrue(remove_invalid_ok1); assertTrue(remove_invalid_ok2); assertTrue(OPTIONS.client.getLocalOptionState(TelnetOption.ECHO)); assertTrue(!OPTIONS.client.getLocalOptionState(TelnetOption.SUPPRESS_GO_AHEAD)); assertTrue(!OPTIONS.client.getLocalOptionState(TelnetOption.SUPPRESS_GO_AHEAD)); } /*** * test of AYT functionality ***/ public void testAYT() throws Exception { boolean ayt_true_ok = false; boolean ayt_false_ok = false; byte AYT[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT }; byte response[] = { (byte) '[', (byte) 'Y', (byte) 'e', (byte) 's', (byte) ']' }; String inputs[] = new String[1]; String outputs[] = new String[1]; inputs[0] = new String (AYT); outputs[0] = new String (response); OutputStream os = ANSI.server.getOutputStream(); InputStream is = ANSI.server.getInputStream(); TelnetTestResponder tr = new TelnetTestResponder(is, os, inputs, outputs, 30000); assertNotNull(tr); boolean res1 = ANSI.client.sendAYT(2000); if(res1 == true) ayt_true_ok=true; Thread.sleep(1000); is.skip(is.available()); boolean res2 = ANSI.client.sendAYT(2000); if(res2 == false) ayt_false_ok=true; assertTrue(ayt_true_ok); assertTrue(ayt_false_ok); } /*** * test of Spy functionality ***/ public void testSpy() throws Exception { boolean test1spy_ok = false; boolean test2spy_ok = false; boolean stopspy_ok = false; byte expected1[] = { (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1' }; byte expected2[] = { (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '2' }; PipedOutputStream po = new PipedOutputStream(); PipedInputStream pi = new PipedInputStream(po); OutputStream os = STANDARD.server.getOutputStream(); OutputStream ostc = STANDARD.client.getOutputStream(); STANDARD.client.registerSpyStream(po); os.write("test1".getBytes()); os.flush(); Thread.sleep(1000); byte buffer[] = new byte[5]; if(pi.available() == 5) { pi.read(buffer); if(equalBytes(buffer, expected1)) test1spy_ok = true; } ostc.write("test2".getBytes()); ostc.flush(); Thread.sleep(1000); if(pi.available() == 5) { pi.read(buffer); if(equalBytes(buffer, expected2)) test2spy_ok = true; } STANDARD.client.stopSpyStream(); os.write("test1".getBytes()); os.flush(); ostc.write("test2".getBytes()); ostc.flush(); Thread.sleep(1000); if(pi.available() == 0) { stopspy_ok = true; } assertTrue(test1spy_ok); assertTrue(test2spy_ok); assertTrue(stopspy_ok); } /*** * test of setReaderThread ***/ public void testSetReaderThread() throws Exception { boolean negotiation1_ok = false; boolean negotiation2_ok = false; boolean read_ok = false; byte buffread1[] = new byte[6]; byte send1[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) 15, }; byte expected1[] = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) 15, }; InputStream is1 = NOREAD.server.getInputStream(); OutputStream os1 = NOREAD.server.getOutputStream(); is1.skip(is1.available()); os1.write(send1); os1.flush(); os1.write("A".getBytes()); os1.flush(); Thread.sleep(1000); InputStream instr = NOREAD.client.getInputStream(); byte[] buff = new byte[4]; int ret_read = 0; ret_read = instr.read(buff); if((ret_read == 1) && (buff[0] == 'A')) { read_ok = true; } // if(is1.available() == 6) //{ int read = 0; int pos = 0; byte[] tmp = new byte[16]; while ( pos < 5 ) { read = is1.read(tmp); System.arraycopy(tmp, 0, buffread1, pos, read); pos+=read; } if(equalBytes(buffread1, expected1)) negotiation1_ok = true; //} InputStream is2 = STANDARD.server.getInputStream(); OutputStream os2 = STANDARD.server.getOutputStream(); Thread.sleep(1000); is2.skip(is2.available()); os2.write(send1); os2.flush(); Thread.sleep(1000); tmp = new byte[16]; while ( pos < 5 ) { read = is2.read(tmp); System.arraycopy(tmp, 0, buffread1, pos, read); pos+=read; } //if(is2.available() == 6) //{ is2.read(buffread1); if(equalBytes(buffread1, expected1)) negotiation2_ok = true; //} assertTrue(!NOREAD.client.getReaderThread()); assertTrue(STANDARD.client.getReaderThread()); assertTrue("Expected read_ok to be true, got " + read_ok, read_ok); assertTrue("Expected negotiation1_ok to be true, got " + negotiation1_ok, negotiation1_ok); assertTrue("Expected negotiation2_ok to be true, got " + negotiation2_ok, negotiation2_ok); } /*** * Helper method. compares two arrays of int ***/ protected boolean equalBytes(byte a1[], byte a2[]) { if(a1.length != a2.length) { return(false); } else { boolean result = true; for(int ii=0; ii * @param negotiation_code - type of negotiation command received * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT) *

* @param option_code - code of the option negotiated *

***/ public void receivedNegotiation(int negotiation_code, int option_code) { if(negotiation_code == TelnetNotificationHandler.RECEIVED_DO) { numdo++; } else if(negotiation_code == TelnetNotificationHandler.RECEIVED_DONT) { numdont++; } else if(negotiation_code == TelnetNotificationHandler.RECEIVED_WILL) { numwill++; } else if(negotiation_code == TelnetNotificationHandler.RECEIVED_WONT) { numwont++; } } }commons-net-2.2/src/test/java/org/apache/commons/net/telnet/InvalidTelnetOptionExceptionTest.java0000644000175000017500000000303011347047772033332 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import junit.framework.TestCase; /*** * JUnit test class for InvalidTelnetOptionException *

* @author Bruno D'Avanzo ***/ public class InvalidTelnetOptionExceptionTest extends TestCase { private InvalidTelnetOptionException exc1; private String msg1; private int code1; /*** * setUp for the test. ***/ @Override protected void setUp() { msg1 = "MSG"; code1 = 13; exc1 = new InvalidTelnetOptionException(msg1, code1); } /*** * test of the constructors. ***/ public void testConstructors() { assertTrue(exc1.getMessage().indexOf(msg1) >= 0); assertTrue(exc1.getMessage().indexOf("" +code1) >= 0); } }commons-net-2.2/src/test/java/org/apache/commons/net/telnet/SuppressGAOptionHandlerTest.java0000644000175000017500000000451411347047772032253 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * JUnit test class for SuppressGAOptionHandler *

* @author Bruno D'Avanzo ***/ public class SuppressGAOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * setUp for the test. ***/ @Override protected void setUp() { opthand1 = new SuppressGAOptionHandler(); opthand2 = new SuppressGAOptionHandler(true, true, true, true); opthand3 = new SuppressGAOptionHandler(false, false, false, false); } /*** * test of the constructors. ***/ @Override public void testConstructors() { assertEquals(opthand1.getOptionCode(), TelnetOption.SUPPRESS_GO_AHEAD); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testStartSubnegotiation() { int resp1[] = opthand1.startSubnegotiationLocal(); int resp2[] = opthand1.startSubnegotiationRemote(); assertEquals(resp1, null); assertEquals(resp2, null); } /*** * test of server-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testAnswerSubnegotiation() { int subn[] = { TelnetCommand.IAC, TelnetCommand.SB, TelnetOption.SUPPRESS_GO_AHEAD, 1, TelnetCommand.IAC, TelnetCommand.SE, }; int resp1[] = opthand1.answerSubnegotiation(subn, subn.length); assertEquals(resp1, null); } } commons-net-2.2/src/test/java/org/apache/commons/net/telnet/TelnetClientFunctionalTest.java0000644000175000017500000000640711347047772032150 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import junit.framework.TestCase; import java.io.InputStream; import java.io.OutputStream; /*** * JUnit functional test for TelnetClient. * Connects to the weather forecast service * rainmaker.wunderground.com and asks for Los Angeles forecast. *

* @author Bruno D'Avanzo ***/ public class TelnetClientFunctionalTest extends TestCase { protected TelnetClient tc1; /*** * test setUp ***/ @Override protected void setUp() { tc1 = new TelnetClient(); } /*** * Do the functional test: * - connect to the weather service * - press return on the first menu * - send LAX on the second menu * - send X to exit ***/ public void testFunctionalTest() throws Exception { boolean testresult = false; tc1.connect("rainmaker.wunderground.com", 3000); InputStream is = tc1.getInputStream(); OutputStream os = tc1.getOutputStream(); boolean cont = waitForString(is, "Return to continue:", 30000); if (cont) { os.write("\n".getBytes()); os.flush(); cont = waitForString(is, "city code--", 30000); } if (cont) { os.write("LAX\n".getBytes()); os.flush(); cont = waitForString(is, "Los Angeles", 30000); } if (cont) { cont = waitForString(is, "X to exit:", 30000); } if (cont) { os.write("X\n".getBytes()); os.flush(); tc1.disconnect(); testresult = true; } assertTrue(testresult); } /*** * Helper method. waits for a string with timeout ***/ public boolean waitForString(InputStream is, String end, long timeout) throws Exception { byte buffer[] = new byte[32]; long starttime = System.currentTimeMillis(); String readbytes = ""; while((readbytes.indexOf(end) < 0) && ((System.currentTimeMillis() - starttime) < timeout)) { if(is.available() > 0) { int ret_read = is.read(buffer); readbytes = readbytes + new String(buffer, 0, ret_read); } else { Thread.sleep(500); } } if(readbytes.indexOf(end) >= 0) { return (true); } else { return (false); } } }commons-net-2.2/src/test/java/org/apache/commons/net/telnet/TelnetTestResponder.java0000644000175000017500000000606711151645326030642 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import java.io.InputStream; import java.io.OutputStream; /*** * Simple stream responder. * Waits for strings on an input stream and answers * sending corresponfing strings on an output stream. * The reader runs in a separate thread. *

* @author Bruno D'Avanzo ***/ public class TelnetTestResponder implements Runnable { InputStream _is; OutputStream _os; String _inputs[], _outputs[]; long _timeout; /*** * Constructor. * Starts a new thread for the reader. *

* @param is - InputStream on which to read. * @param os - OutputStream on which to answer. * @param inputs - Array of waited for Strings. * @param outputs - Array of answers. * @param timeout - milliseconds ***/ public TelnetTestResponder(InputStream is, OutputStream os, String inputs[], String outputs[], long timeout) { _is = is; _os = os; _timeout = timeout; _inputs = inputs; _outputs = outputs; Thread reader = new Thread (this); reader.start(); } /*** * Runs the responder ***/ public void run() { boolean result = false; byte buffer[] = new byte[32]; long starttime = System.currentTimeMillis(); try { String readbytes = ""; while(!result && ((System.currentTimeMillis() - starttime) < _timeout)) { if(_is.available() > 0) { int ret_read = _is.read(buffer); readbytes = readbytes + new String(buffer, 0, ret_read); for(int ii=0; ii<_inputs.length; ii++) { if(readbytes.indexOf(_inputs[ii]) >= 0) { Thread.sleep(1000 * ii); _os.write(_outputs[ii].getBytes()); result = true; } } } else { Thread.sleep(500); } } } catch (Exception e) { System.err.println("Error while waiting endstring. " + e.getMessage()); } } } commons-net-2.2/src/test/java/org/apache/commons/net/telnet/WindowSizeOptionHandlerTest.java0000644000175000017500000000655511416446726032327 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * JUnit test class for TerminalTypeOptionHandler *

* @author Bruno D'Avanzo ***/ public class WindowSizeOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * setUp for the test. ***/ @Override protected void setUp() { opthand1 = new WindowSizeOptionHandler(80, 24); opthand2 = new WindowSizeOptionHandler(255, 255, true, true, true, true); opthand3 = new WindowSizeOptionHandler(0xFFFF, 0x00FF, false, false, false, false); } /*** * test of the constructors. ***/ @Override public void testConstructors() { assertEquals(TelnetOption.WINDOW_SIZE, opthand1.getOptionCode()); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testStartSubnegotiation() { assertNull(opthand1.startSubnegotiationRemote()); assertNull(opthand2.startSubnegotiationRemote()); assertNull(opthand3.startSubnegotiationRemote()); } /*** * test of client-driven subnegotiation. * ***/ public void testStartSubnegotiationLocal() { int[] exp1 = {31, 0, 80, 0, 24}; int[] start1 = opthand1.startSubnegotiationLocal(); assertEquals(5, start1.length); equalInts(exp1, start1); int[] exp2 = {31, 0, 255, 255, 0, 255, 255}; int[] start2 = opthand2.startSubnegotiationLocal(); equalInts(exp2, start2); int[] exp3 = {31, 255, 255, 255, 255, 0, 255, 255}; int[] start3 = opthand3.startSubnegotiationLocal(); equalInts(exp3, start3); } /*** * test of client-driven subnegotiation. * Checks that nothing is sent ***/ @Override public void testAnswerSubnegotiation() { int subn[] = { TelnetOption.WINDOW_SIZE, 24, 80 }; int resp1[] = opthand1.answerSubnegotiation(subn, subn.length); int resp2[] = opthand2.answerSubnegotiation(subn, subn.length); int resp3[] = opthand3.answerSubnegotiation(subn, subn.length); assertNull(resp1); assertNull(resp2); assertNull(resp3); } /*** * compares two arrays of int ***/ private void equalInts(int a1[], int a2[]) { assertEquals("Arrays should be the same length", a1.length, a2.length); for(int ii=0; ii * @author Bruno D'Avanzo ***/ public class TelnetTestSimpleServer implements Runnable { ServerSocket serverSocket = null; Socket clientSocket = null; Thread listener = null; /*** * test of client-driven subnegotiation. *

* @param port - server port on which to listen. ***/ public TelnetTestSimpleServer(int port) throws IOException { serverSocket = new ServerSocket(port); listener = new Thread (this); listener.start(); } /*** * Run for the thread. Waits for new connections ***/ public void run() { boolean bError = false; while(!bError) { try { clientSocket = serverSocket.accept(); synchronized (clientSocket) { try { clientSocket.wait(); } catch (Exception e) { System.err.println("Exception in wait, "+ e.getMessage()); } try { clientSocket.close(); } catch (Exception e) { System.err.println("Exception in close, "+ e.getMessage()); } } } catch (IOException e) { bError = true; } } try { serverSocket.close(); } catch (Exception e) { System.err.println("Exception in close, "+ e.getMessage()); } } /*** * Disconnects the client socket ***/ public void disconnect() { synchronized (clientSocket) { try { clientSocket.notify(); } catch (Exception e) { System.err.println("Exception in notify, "+ e.getMessage()); } } } /*** * Stop the listener thread ***/ public void stop() { listener.interrupt(); try { serverSocket.close(); } catch (Exception e) { System.err.println("Exception in close, "+ e.getMessage()); } } /*** * Gets the input stream for the client socket ***/ public InputStream getInputStream() throws IOException { if(clientSocket != null) { return(clientSocket.getInputStream()); } else { return(null); } } /*** * Gets the output stream for the client socket ***/ public OutputStream getOutputStream() throws IOException { if(clientSocket != null) { return(clientSocket.getOutputStream()); } else { return(null); } } } commons-net-2.2/src/test/java/org/apache/commons/net/telnet/EchoOptionHandlerTest.java0000644000175000017500000000442311347047772031074 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * JUnit test class for EchoOptionHandler *

* @author Bruno D'Avanzo ***/ public class EchoOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * setUp for the test. ***/ @Override protected void setUp() { opthand1 = new EchoOptionHandler(); opthand2 = new EchoOptionHandler(true, true, true, true); opthand3 = new EchoOptionHandler(false, false, false, false); } /*** * test of the constructors. ***/ @Override public void testConstructors() { assertEquals(opthand1.getOptionCode(), TelnetOption.ECHO); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testStartSubnegotiation() { int resp1[] = opthand1.startSubnegotiationLocal(); int resp2[] = opthand1.startSubnegotiationRemote(); assertEquals(resp1, null); assertEquals(resp2, null); } /*** * test of server-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testAnswerSubnegotiation() { int subn[] = { TelnetCommand.IAC, TelnetCommand.SB, TelnetOption.ECHO, 1, TelnetCommand.IAC, TelnetCommand.SE, }; int resp1[] = opthand1.answerSubnegotiation(subn, subn.length); assertEquals(resp1, null); } } commons-net-2.2/src/test/java/org/apache/commons/net/telnet/SimpleOptionHandlerTest.java0000644000175000017500000000455411347047772031454 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * JUnit test class for SimpleOptionHandler *

* @author Bruno D'Avanzo ***/ public class SimpleOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * setUp for the test. ***/ @Override protected void setUp() { opthand1 = new SimpleOptionHandler(4); opthand2 = new SimpleOptionHandler(8, true, true, true, true); opthand3 = new SimpleOptionHandler(91, false, false, false, false); } /*** * test of the constructors. ***/ @Override public void testConstructors() { assertEquals(opthand1.getOptionCode(), 4); assertEquals(opthand2.getOptionCode(), 8); assertEquals(opthand3.getOptionCode(), 91); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testStartSubnegotiation() { int resp1[] = opthand1.startSubnegotiationLocal(); int resp2[] = opthand1.startSubnegotiationRemote(); assertEquals(resp1, null); assertEquals(resp2, null); } /*** * test of server-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testAnswerSubnegotiation() { int subn[] = { TelnetCommand.IAC, TelnetCommand.SB, 4, 1, TelnetCommand.IAC, TelnetCommand.SE, }; int resp1[] = opthand1.answerSubnegotiation(subn, subn.length); assertEquals(resp1, null); } } commons-net-2.2/src/test/java/org/apache/commons/net/telnet/TelnetOptionTest.java0000644000175000017500000000313211347047772030147 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; import junit.framework.TestCase; /*** * JUnit test class for TelnetOption *

* @author Bruno D'Avanzo ***/ public class TelnetOptionTest extends TestCase { /*** * test of the isValidOption method. ***/ public void testisValidOption() { assertTrue(TelnetOption.isValidOption(0)); assertTrue(TelnetOption.isValidOption(91)); assertTrue(TelnetOption.isValidOption(255)); assertTrue(!TelnetOption.isValidOption(256)); } /*** * test of the getOption method. ***/ public void testGetOption() { assertEquals(TelnetOption.getOption(0), "BINARY"); assertEquals(TelnetOption.getOption(91), "UNASSIGNED"); assertEquals(TelnetOption.getOption(255), "Extended-Options-List"); } }commons-net-2.2/src/test/java/org/apache/commons/net/telnet/TerminalTypeOptionHandlerTest.java0000644000175000017500000000606011347047772032632 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.telnet; /*** * JUnit test class for TerminalTypeOptionHandler *

* @author Bruno D'Avanzo ***/ public class TerminalTypeOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * setUp for the test. ***/ @Override protected void setUp() { opthand1 = new TerminalTypeOptionHandler("VT100"); opthand2 = new TerminalTypeOptionHandler("ANSI", true, true, true, true); opthand3 = new TerminalTypeOptionHandler("ANSI", false, false, false, false); } /*** * test of the constructors. ***/ @Override public void testConstructors() { assertEquals(opthand1.getOptionCode(), TelnetOption.TERMINAL_TYPE); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ @Override public void testStartSubnegotiation() { int resp1[] = opthand1.startSubnegotiationLocal(); int resp2[] = opthand1.startSubnegotiationRemote(); assertEquals(resp1, null); assertEquals(resp2, null); } /*** * test of client-driven subnegotiation. * Checks that the terminal type is sent ***/ @Override public void testAnswerSubnegotiation() { int subn[] = { TelnetOption.TERMINAL_TYPE, 1 }; int expected1[] = { TelnetOption.TERMINAL_TYPE, 0, 'V', 'T', '1', '0', '0' }; int expected2[] = { TelnetOption.TERMINAL_TYPE, 0, 'A', 'N', 'S', 'I' }; int resp1[] = opthand1.answerSubnegotiation(subn, subn.length); int resp2[] = opthand2.answerSubnegotiation(subn, subn.length); assertTrue(equalInts(resp1, expected1)); assertTrue(equalInts(resp2, expected2)); } /*** * compares two arrays of int ***/ protected boolean equalInts(int a1[], int a2[]) { if(a1.length != a2.length) { return(false); } else { boolean result = true; for(int ii=0; ii * @author Bruno D'Avanzo ***/ public abstract class TelnetOptionHandlerTestAbstract extends TestCase { TelnetOptionHandler opthand1; TelnetOptionHandler opthand2; TelnetOptionHandler opthand3; /*** * setUp for the test. The derived test class must implement * this method by creating opthand1, opthand2, opthand3 * like in the following: * opthand1 = new EchoOptionHandler(); * opthand2 = new EchoOptionHandler(true, true, true, true); * opthand3 = new EchoOptionHandler(false, false, false, false); ***/ @Override protected abstract void setUp(); /*** * test of the constructors. The derived class may add * test of the option code. ***/ public void testConstructors() { // add test of the option code assertTrue(!opthand1.getInitLocal()); assertTrue(!opthand1.getInitRemote()); assertTrue(!opthand1.getAcceptLocal()); assertTrue(!opthand1.getAcceptRemote()); assertTrue(opthand2.getInitLocal()); assertTrue(opthand2.getInitRemote()); assertTrue(opthand2.getAcceptLocal()); assertTrue(opthand2.getAcceptRemote()); assertTrue(!opthand3.getInitLocal()); assertTrue(!opthand3.getInitRemote()); assertTrue(!opthand3.getAcceptLocal()); assertTrue(!opthand3.getAcceptRemote()); } /*** * test of setWill/getWill ***/ public void testWill() { opthand2.setWill(true); opthand3.setWill(false); assertTrue(!opthand1.getWill()); assertTrue(opthand2.getWill()); assertTrue(!opthand3.getWill()); } /*** * test of setDo/getDo ***/ public void testDo() { opthand2.setDo(true); opthand3.setDo(false); assertTrue(!opthand1.getDo()); assertTrue(opthand2.getDo()); assertTrue(!opthand3.getDo()); } /*** * test of client-driven subnegotiation. Abstract test: * the derived class should implement it. ***/ public abstract void testStartSubnegotiation(); /*** * test of server-driven subnegotiation. Abstract test: * the derived class should implement it. ***/ public abstract void testAnswerSubnegotiation(); // test subnegotiation }commons-net-2.2/src/test/java/org/apache/commons/net/time/0000755000175000017500000000000011617452466023464 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/time/TimeTestSimpleServer.java0000644000175000017500000001067311014672436030425 0ustar twernertwernerpackage org.apache.commons.net.time; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * The TimetSimpleServer class is a simple TCP implementation of a server * for the Time Protocol described in RFC 868. *

* Listens for TCP socket connections on the time protocol port and writes * the local time to socket outputStream as 32-bit integer of seconds * since midnight on 1 January 1900 GMT. * See the spec for * details. *

* Note this is for debugging purposes only and not meant to be run as a realiable time service. * * @author Jason Mathews, MITRE Corporation * * @version $Revision: 658518 $ $Date: 2008-05-21 03:04:30 +0200 (Mi, 21. Mai 2008) $ */ public class TimeTestSimpleServer implements Runnable { /** * baseline time 1900-01-01T00:00:00 UTC */ public static final long SECONDS_1900_TO_1970 = 2208988800L; /*** The default time port. It is set to 37 according to RFC 868. ***/ public static final int DEFAULT_PORT = 37; private ServerSocket server; private int port; private boolean running = false; /** * Default constructor for TimetSimpleServer. * Initializes port to defaul time port. */ public TimeTestSimpleServer() { port = DEFAULT_PORT; } /** * Constructor for TimetSimpleServer given a specific port. */ public TimeTestSimpleServer(int port) { this.port = port; } public void connect() throws IOException { if (server == null) { server = new ServerSocket(port); } } public int getPort() { return server == null ? port : server.getLocalPort(); } public boolean isRunning() { return running; } /** * Start time service and provide time to client connections. * @throws IOException */ public void start() throws IOException { if (server == null) { connect(); } if (!running) { running = true; new Thread(this).start(); } } public void run() { Socket socket = null; while (running) { try { socket = server.accept(); DataOutputStream os = new DataOutputStream(socket.getOutputStream()); // add 500 ms to round off to nearest second int time = (int) ((System.currentTimeMillis() + 500) / 1000 + SECONDS_1900_TO_1970); os.writeInt(time); os.flush(); } catch (IOException e) { } finally { if (socket != null) try { socket.close(); // force closing of the socket } catch (IOException e) { System.err.println("close socket error: " + e); } } } } /** * Close server socket. */ public void stop() { running = false; if (server != null) { try { server.close(); // force closing of the socket } catch (IOException e) { System.err.println("close socket error: " + e); } server = null; } } public static void main(String[] args) { TimeTestSimpleServer server = new TimeTestSimpleServer(); try { server.start(); } catch (IOException e) { } } } commons-net-2.2/src/test/java/org/apache/commons/net/time/TimeTCPClientTest.java0000644000175000017500000000745611364045325027576 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.time; import java.net.InetAddress; import java.util.Calendar; import java.io.IOException; import java.util.TimeZone; import junit.framework.TestCase; public class TimeTCPClientTest extends TestCase { private TimeTestSimpleServer server1; private int _port = 3333; // default test port /*** * open connections needed for the tests for the test. ***/ protected void openConnections() throws Exception { try { server1 = new TimeTestSimpleServer(_port); server1.connect(); } catch (IOException ioe) { // try again on another port _port = 4000; server1 = new TimeTestSimpleServer(_port); server1.connect(); } server1.start(); } /*** * tests the constant basetime used by TimeClient against tha * computed from Calendar class. */ public void testInitial() { TimeZone utcZone = TimeZone.getTimeZone("UTC"); Calendar calendar = Calendar.getInstance(utcZone); calendar.set(1900, Calendar.JANUARY, 1, 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); long baseTime = calendar.getTime().getTime() / 1000L; assertEquals(baseTime, -TimeTCPClient.SECONDS_1900_TO_1970); } /*** * tests the times retrieved via the Time protocol implementation. ***/ public void testCompareTimes() throws Exception { openConnections(); long time, time2; long clientTime, clientTime2; try { TimeTCPClient client = new TimeTCPClient(); try { // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(InetAddress.getLocalHost(), _port); clientTime = client.getDate().getTime(); time = System.currentTimeMillis(); } finally { if(client.isConnected()) client.disconnect(); } try { // We want to timeout if a response takes longer than 60 seconds client.setDefaultTimeout(60000); client.connect(InetAddress.getLocalHost(), _port); clientTime2 = (client.getTime() - TimeTCPClient.SECONDS_1900_TO_1970)*1000L; time2 = System.currentTimeMillis(); } finally { if(client.isConnected()) client.disconnect(); } } finally { closeConnections(); } // current time shouldn't differ from time reported via network by 5 seconds assertTrue(Math.abs(time - clientTime) < 5000); assertTrue(Math.abs(time2 - clientTime2) < 5000); } /*** * closes all the connections ***/ protected void closeConnections() { try { server1.stop(); Thread.sleep(1000); } catch (Exception e) { } } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/0000755000175000017500000000000011617452466023317 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/ftp/FTPCommandTest.java0000644000175000017500000000205111456023364026740 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import junit.framework.TestCase; public class FTPCommandTest extends TestCase { public FTPCommandTest(String name) { super(name); } public void testArray() { FTPCommand.checkArray(); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/FTPClientConfigTest.java0000644000175000017500000001446511014672436027742 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import junit.framework.TestCase; public class FTPClientConfigTest extends TestCase { /* * Class under test for void FTPClientConfig(String) */ public void testFTPClientConfigString() { FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_VMS); assertEquals(FTPClientConfig.SYST_VMS, config.getServerSystemKey()); assertNull(config.getDefaultDateFormatStr()); assertNull(config.getRecentDateFormatStr()); assertNull(config.getShortMonthNames()); assertNull(config.getServerTimeZoneId()); assertNull(config.getServerLanguageCode()); } String A = "A"; String B = "B"; String C = "C"; String D = "D"; String E = "E"; String F = "F"; /* * Class under test for void FTPClientConfig(String, String, String, String, String, String) */ public void testFTPClientConfigStringStringStringStringStringString() { FTPClientConfig conf = new FTPClientConfig(A,B,C,D,E,F); assertEquals("A", conf.getServerSystemKey()); assertEquals("B", conf.getDefaultDateFormatStr()); assertEquals("C", conf.getRecentDateFormatStr()); assertEquals("E", conf.getShortMonthNames()); assertEquals("F", conf.getServerTimeZoneId()); assertEquals("D", conf.getServerLanguageCode()); } String badDelim = "jan,feb,mar,apr,may,jun,jul,aug.sep,oct,nov,dec"; String tooLong = "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|jan"; String tooShort = "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov"; String fakeLang = "abc|def|ghi|jkl|mno|pqr|stu|vwx|yza|bcd|efg|hij"; public void testSetShortMonthNames() { } public void testGetServerLanguageCode() { } public void testLookupDateFormatSymbols() { DateFormatSymbols dfs1 = null; DateFormatSymbols dfs2 = null; DateFormatSymbols dfs3 = null; DateFormatSymbols dfs4 = null; try { dfs1 = FTPClientConfig.lookupDateFormatSymbols("fr"); } catch (IllegalArgumentException e){ fail("french"); } try { dfs2 = FTPClientConfig.lookupDateFormatSymbols("sq"); } catch (IllegalArgumentException e){ fail("albanian"); } try { dfs3 = FTPClientConfig.lookupDateFormatSymbols("ru"); } catch (IllegalArgumentException e){ fail("unusupported.default.to.en"); } try { dfs4 = FTPClientConfig.lookupDateFormatSymbols(fakeLang); } catch (IllegalArgumentException e){ fail("not.language.code.but.defaults"); } assertEquals(dfs3,dfs4); SimpleDateFormat sdf1 = new SimpleDateFormat("d MMM yyyy", dfs1); SimpleDateFormat sdf2 = new SimpleDateFormat("MMM dd, yyyy", dfs2); SimpleDateFormat sdf3 = new SimpleDateFormat("MMM dd, yyyy", dfs3); Date d1 = null; Date d2 = null; Date d3 = null; try { d1 = sdf1.parse("31 d\u00e9c 2004"); } catch (ParseException px) { fail("failed.to.parse.french"); } try { d2 = sdf2.parse("dhj 31, 2004"); } catch (ParseException px) { fail("failed.to.parse.albanian"); } try { d3 = sdf3.parse("DEC 31, 2004"); } catch (ParseException px) { fail("failed.to.parse.'russian'"); } assertEquals("different.parser.same.date", d1, d2); assertEquals("different.parser.same.date", d1, d3); } public void testGetDateFormatSymbols() { try { FTPClientConfig.getDateFormatSymbols(badDelim); fail("bad delimiter"); } catch (IllegalArgumentException e){ // should have failed } try { FTPClientConfig.getDateFormatSymbols(tooLong); fail("more than 12 months"); } catch (IllegalArgumentException e){ // should have failed } try { FTPClientConfig.getDateFormatSymbols(tooShort); fail("fewer than 12 months"); } catch (IllegalArgumentException e){ // should have failed } DateFormatSymbols dfs2 = null; try { dfs2 = FTPClientConfig.getDateFormatSymbols(fakeLang); } catch (Exception e){ fail("rejected valid short month string"); } SimpleDateFormat sdf1 = new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH); SimpleDateFormat sdf2 = new SimpleDateFormat("MMM dd, yyyy", dfs2); Date d1 = null; Date d2 = null; try { d1 = sdf1.parse("dec 31, 2004"); } catch (ParseException px) { fail("failed.to.parse.std"); } try { d2 = sdf2.parse("hij 31, 2004"); } catch (ParseException px) { fail("failed.to.parse.weird"); } assertEquals("different.parser.same.date",d1, d2); try { d2 = sdf1.parse("hij 31, 2004"); fail("should.have.failed.to.parse.weird"); } catch (ParseException px) { } try { d2 = sdf2.parse("dec 31, 2004"); fail("should.have.failed.to.parse.standard"); } catch (ParseException px) { } } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/FTPClientConfigFunctionalTest.java0000644000175000017500000001344611445713721031764 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.IOException; import java.net.SocketException; import java.util.Calendar; import java.util.Comparator; import java.util.TreeSet; import junit.framework.TestCase; /* * This test was contributed in a different form by W. McDonald Buck * of Boulder, Colorado, to help fix some bugs with the FTPClientConfig * in a real world setting. It is a perfect functional test for the * Time Zone functionality of FTPClientConfig. * * A publicly accessible FTP server at the US National Oceanographic and * Atmospheric Adminstration houses a directory which contains * 300 files, named sn.0000 to sn.0300. Every ten minutes or so * the next file in sequence is rewritten with new data. Thus the directory * contains observations for more than 24 hours of data. Since the server * has its clock set to GMT this is an excellent functional test for any * machine in a different time zone. * * Noteworthy is the fact that the ftp routines in some web browsers don't * work as well as this. They can't, since they have no way of knowing the * server's time zone. Depending on the local machine's position relative * to GMT and the time of day, the browsers may decide that a timestamp * would be in the future if given the current year, so they assume the * year to be last year. This illustrates the value of FTPClientConfig's * time zone functionality. */ public class FTPClientConfigFunctionalTest extends TestCase { private FTPClient FTP = new FTPClient(); private FTPClientConfig FTPConf; /** * */ public FTPClientConfigFunctionalTest() { super(); } /* * @throws java.lang.Exception */ @Override protected void setUp() throws Exception { super.setUp(); FTPConf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); FTPConf.setServerTimeZoneId("GMT"); FTP.configure(FTPConf); try { FTP.connect("tgftp.nws.noaa.gov"); FTP.login("anonymous","testing@apache.org"); FTP.changeWorkingDirectory("SL.us008001/DF.an/DC.sflnd/DS.metar"); FTP.enterLocalPassiveMode(); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * @throws java.lang.Exception */ @Override protected void tearDown() throws Exception { FTP.disconnect(); super.tearDown(); } /** * @param arg0 */ public FTPClientConfigFunctionalTest(String arg0) { super(arg0); } private TreeSet getSortedList(FTPFile[] files) { // create a TreeSet which will sort each element // as it is added. TreeSet sorted = new TreeSet(new Comparator() { public int compare(Object o1, Object o2) { FTPFile f1 = (FTPFile) o1; FTPFile f2 = (FTPFile) o2; return f1.getTimestamp().getTime().compareTo(f2.getTimestamp().getTime()); } }); for (int i=0; i < files.length; i++) { // The directory contains a few additional files at the beginning // which aren't in the series we want. The series we want consists // of files named sn.dddd. This adjusts the file list to get rid // of the uninteresting ones. if (files[i].getName().startsWith("sn")) { sorted.add(files[i]); } } return sorted; } public void testTimeZoneFunctionality() throws Exception { java.util.Date now = new java.util.Date(); FTPFile[] files = FTP.listFiles(); TreeSet sorted = getSortedList(files); //SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm z" ); FTPFile lastfile = null; FTPFile firstfile = null; for (FTPFile thisfile : sorted) { if (firstfile == null) { firstfile = thisfile; } //System.out.println(sdf.format(thisfile.getTimestamp().getTime()) // + " " +thisfile.getName()); if (lastfile != null) { // verify that the list is sorted earliest to latest. assertTrue(lastfile.getTimestamp() .before(thisfile.getTimestamp())); } lastfile = thisfile; } // test that notwithstanding any time zone differences, the newest file // is older than now. assertTrue(lastfile.getTimestamp().getTime().before(now)); Calendar first = firstfile.getTimestamp(); // test that the oldest is less than two days older than the newest // and, in particular, that no files have been considered "future" // by the parser and therefore been relegated to the same date a // year ago. first.add(Calendar.DATE, 2); assertTrue(lastfile.getTimestamp().before(first)); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/ListingFunctionalTest.java0000644000175000017500000002375011456054057030460 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.IOException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Iterator; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * A functional test suite for checking that site listings work. * @author Jeffrey D. Brekke * @version $Id: ListingFunctionalTest.java 1022913 2010-10-15 13:33:35Z sebb $ */ public class ListingFunctionalTest extends TestCase { // Offsets within testData below static final int HOSTNAME = 0; static final int VALID_PARSERKEY = 1; static final int INVALID_PARSERKEY = 2; static final int INVALID_PATH = 3; static final int VALID_FILENAME = 4; static final int VALID_PATH = 5; public static final Test suite() { String[][] testData = { { "ftp.ibiblio.org", "unix", "vms", "HA!", "javaio.jar", "pub/languages/java/javafaq" }, { "ftp.wacom.com", "windows", "VMS", "HA!", "wacom97.zip", "pub\\drivers" }, { "ftp.decuslib.com", "vms", "windows", // VMS OpenVMS V8.3 "[.HA!]", "FREEWARE_SUBMISSION_INSTRUCTIONS.TXT;1", "[.FREEWAREV80.FREEWARE]" }, // { // VMS TCPware V5.7-2 does not return (RWED) permissions // "ftp.process.com", "vms", "windows", // "[.HA!]", "MESSAGE.;1", // "[.VMS-FREEWARE.FREE-VMS]" // // }, }; Class clasz = ListingFunctionalTest.class; Method[] methods = clasz.getDeclaredMethods(); TestSuite allSuites = new TestSuite("FTP Listing Functional Test Suite"); for (int i = 0; i < testData.length; i++) { TestSuite suite = new TestSuite(testData[i][VALID_PARSERKEY]+ " @ " +testData[i][HOSTNAME]); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; if (method.getName().startsWith("test")) { suite.addTest(new ListingFunctionalTest( method.getName(), testData[i])); } } allSuites.addTest(suite); } return allSuites; } private FTPClient client; private String hostName; private String invalidParserKey; private String invalidPath; private String validFilename; private String validParserKey; private String validPath; /** * Constructor for FTPClientTest. * * @param arg0 */ public ListingFunctionalTest(String arg0, String[] settings) { super(arg0); invalidParserKey = settings[INVALID_PARSERKEY]; validParserKey = settings[VALID_PARSERKEY]; invalidPath = settings[INVALID_PATH]; validFilename = settings[VALID_FILENAME]; validPath = settings[VALID_PATH]; hostName = settings[HOSTNAME]; } /** * @param fileList * @param string * * @return */ private boolean findByName(List fileList, String string) { boolean found = false; Iterator iter = fileList.iterator(); while (iter.hasNext() && !found) { Object element = iter.next(); if (element instanceof FTPFile) { FTPFile file = (FTPFile) element; found = file.getName().equals(string); } else { String filename = (String) element; found = filename.endsWith(string); } } return found; } /* * @see TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); client = new FTPClient(); client.connect(hostName); client.login("anonymous", "anonymous"); client.enterLocalPassiveMode(); } /* * @see TestCase#tearDown() */ @Override protected void tearDown() throws Exception { try { client.logout(); } catch (IOException e) { e.printStackTrace(); } if (client.isConnected()) { client.disconnect(); } client = null; super.tearDown(); } /* * Test for FTPListParseEngine initiateListParsing() */ public void testInitiateListParsing() throws IOException { client.changeWorkingDirectory(validPath); FTPListParseEngine engine = client.initiateListParsing(); List files = Arrays.asList(engine.getNext(25)); assertTrue(files.toString(), findByName(files, validFilename)); } /* * Test for FTPListParseEngine initiateListParsing(String, String) */ public void testInitiateListParsingWithPath() throws IOException { FTPListParseEngine engine = client.initiateListParsing(validParserKey, validPath); List files = Arrays.asList(engine.getNext(25)); assertTrue(files.toString(), findByName(files, validFilename)); } /* * Test for FTPListParseEngine initiateListParsing(String) */ public void testInitiateListParsingWithPathAndAutodetection() throws IOException { FTPListParseEngine engine = client.initiateListParsing(validPath); List files = Arrays.asList(engine.getNext(25)); assertTrue(files.toString(), findByName(files, validFilename)); } /* * Test for FTPListParseEngine initiateListParsing(String) */ public void testInitiateListParsingWithPathAndAutodetectionButEmpty() throws IOException { FTPListParseEngine engine = client.initiateListParsing(invalidPath); assertFalse(engine.hasNext()); } /* * Test for FTPListParseEngine initiateListParsing(String, String) */ public void testInitiateListParsingWithPathAndIncorrectParser() throws IOException { FTPListParseEngine engine = client.initiateListParsing(invalidParserKey, invalidPath); assertFalse(engine.hasNext()); } /* * Test for FTPFile[] listFiles(String, String) */ public void testListFiles() throws IOException { FTPClientConfig config = new FTPClientConfig(validParserKey); client.configure(config); List files = Arrays.asList(client.listFiles(validPath)); assertTrue(files.toString(), findByName(files, validFilename)); } public void testListFilesWithAutodection() throws IOException { client.changeWorkingDirectory(validPath); List files = Arrays.asList(client.listFiles()); assertTrue(files.toString(), findByName(files, validFilename)); } /* * Test for FTPFile[] listFiles(String, String) */ public void testListFilesWithIncorrectParser() throws IOException { FTPClientConfig config = new FTPClientConfig(invalidParserKey); client.configure(config); FTPFile[] files = client.listFiles(validPath); assertEquals(0, files.length); } /* * Test for FTPFile[] listFiles(String) */ public void testListFilesWithPathAndAutodectionButEmpty() throws IOException { FTPFile[] files = client.listFiles(invalidPath); assertEquals(0, files.length); } /* * Test for FTPFile[] listFiles(String) */ public void testListFilesWithPathAndAutodetection() throws IOException { List files = Arrays.asList(client.listFiles(validPath)); assertTrue(files.toString(), findByName(files, validFilename)); } /* * Test for String[] listNames() */ public void testListNames() throws IOException { client.changeWorkingDirectory(validPath); String[] names = client.listNames(); assertNotNull(names); List lnames = Arrays.asList(names); assertTrue(lnames.toString(), lnames.contains(validFilename)); } /* * Test for String[] listNames(String) */ public void testListNamesWithPath() throws IOException { String[] listNames = client.listNames(validPath); assertNotNull("listNames not null", listNames); List names = Arrays.asList(listNames); assertTrue(names.toString(), findByName(names, validFilename)); } public void testListNamesWithPathButEmpty() throws IOException { String[] names = client.listNames(invalidPath); assertNull(names); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/TestConnectTimeout.java0000644000175000017500000000337011014672436027755 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp; import java.io.IOException; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import junit.framework.TestCase; /** * Test the socket connect timeout functionality * @author Rory * */ public class TestConnectTimeout extends TestCase { public void testConnectTimeout() throws SocketException, IOException { FTPClient client = new FTPClient(); client.setConnectTimeout(1000); try { // Connect to a valid host on a bogus port client.connect("ftp.microsoft.com", 1234); assertTrue("Expecting SocketTimeoutException", false); } catch (SocketTimeoutException se) { assertTrue(true); } catch (UnknownHostException ue) { // Not much we can do about this, we may be firewalled assertTrue(true); } } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/0000755000175000017500000000000011617452466024613 5ustar twernertwernercommons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/FTPParseTestFramework.java0000644000175000017500000001117010776231260031610 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import junit.framework.TestCase; import java.text.SimpleDateFormat; import java.util.Locale; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: FTPParseTestFramework.java 437134 2006-08-26 09:36:36Z rwinston $ */ public abstract class FTPParseTestFramework extends TestCase { private FTPFileEntryParser parser = null; protected SimpleDateFormat df = null; /** * @see junit.framework.TestCase#TestCase(String) */ public FTPParseTestFramework(String name) { super(name); } /** * Method testBadListing. * Tests that parser provided failures actually fail. * @throws Exception */ public void testBadListing() throws Exception { String[] badsamples = getBadListing(); for (int i = 0; i < badsamples.length; i++) { String test = badsamples[i]; FTPFile f = parser.parseFTPEntry(test); assertNull("Should have Failed to parse " + test, nullFileOrNullDate(f)); doAdditionalBadTests(test, f); } } /** * Method testGoodListing. * Test that parser provided listings pass. * @throws Exception */ public void testGoodListing() throws Exception { String[] goodsamples = getGoodListing(); for (int i = 0; i < goodsamples.length; i++) { String test = goodsamples[i]; FTPFile f = parser.parseFTPEntry(test); assertNotNull("Failed to parse " + test, f); doAdditionalGoodTests(test, f); } } /** * during processing you could hook here to do additional tests * * @param test raw entry * @param f parsed entry */ protected void doAdditionalGoodTests(String test, FTPFile f) { } /** * during processing you could hook here to do additional tests * * @param test raw entry * @param f parsed entry */ protected void doAdditionalBadTests(String test, FTPFile f) { } /** * Method getBadListing. * Implementors must provide a listing that contains failures. * @return String[] */ protected abstract String[] getBadListing(); /** * Method getGoodListing. * Implementors must provide a listing that passes. * @return String[] */ protected abstract String[] getGoodListing(); /** * Method getParser. * Provide the parser to use for testing. * @return FTPFileEntryParser */ protected abstract FTPFileEntryParser getParser(); /** * Method testParseFieldsOnDirectory. * Provide a test to show that fields on a directory entry are parsed correctly. * @throws Exception */ public abstract void testParseFieldsOnDirectory() throws Exception; /** * Method testParseFieldsOnFile. * Provide a test to show that fields on a file entry are parsed correctly. * @throws Exception */ public abstract void testParseFieldsOnFile() throws Exception; /** * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); parser = getParser(); df = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US); } /** * Check if FTPFile entry parsing failed; i.e. if entry is null or date is null. * * @param f FTPFile entry - may be null * @return null if f is null or the date is null */ protected FTPFile nullFileOrNullDate(FTPFile f) { if (f==null){ return null; } if (f.getTimestamp() == null){ return null; } return f; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootcommons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.javacommons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest0000644000175000017500000001005711456056244033661 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import junit.framework.TestCase; import org.apache.commons.net.ftp.FTPFileEntryParser; public class DefaultFTPFileEntryParserFactoryTest extends TestCase { public void testDefaultParserFactory() throws Exception { DefaultFTPFileEntryParserFactory factory = new DefaultFTPFileEntryParserFactory(); FTPFileEntryParser parser = factory.createFileEntryParser("unix"); assertTrue(parser instanceof UnixFTPEntryParser); parser = factory.createFileEntryParser("UNIX"); assertTrue(parser instanceof UnixFTPEntryParser); parser = factory.createFileEntryParser("Unix"); assertTrue(parser instanceof UnixFTPEntryParser); parser = factory.createFileEntryParser("EnterpriseUnix"); assertTrue(parser instanceof UnixFTPEntryParser); assertFalse(parser instanceof EnterpriseUnixFTPEntryParser); // works because contains the expression "Unix" parser = factory.createFileEntryParser("UnixFTPEntryParser"); assertTrue(parser instanceof UnixFTPEntryParser); try { parser = factory.createFileEntryParser("NT"); fail("Exception should have been thrown. \"NT\" is not a recognized key"); } catch (ParserInitializationException pie) { assertNull(pie.getRootCause()); assertTrue(pie.getMessage()+ "should contain 'Unknown parser type:'", pie.getMessage().contains("Unknown parser type:")); } parser = factory.createFileEntryParser("WindowsNT"); assertTrue(parser instanceof CompositeFileEntryParser); parser = factory.createFileEntryParser("ThigaVMSaMaJig"); assertTrue(parser instanceof VMSFTPEntryParser); parser = factory.createFileEntryParser("OS/2"); assertTrue(parser instanceof OS2FTPEntryParser); parser = factory.createFileEntryParser("OS/400"); assertTrue(parser instanceof CompositeFileEntryParser); parser = factory.createFileEntryParser("AS/400"); assertTrue(parser instanceof CompositeFileEntryParser); // Added test to make sure it handles the Unix systems that were // compiled with OS as "UNKNOWN". This test validates that the // check is case-insensitive. parser = factory.createFileEntryParser("UNKNOWN Type: L8"); try { parser = factory.createFileEntryParser("OS2FTPFileEntryParser"); fail("Exception should have been thrown. \"OS2FTPFileEntryParser\" is not a recognized key"); } catch (ParserInitializationException pie) { assertNull(pie.getRootCause()); } parser = factory.createFileEntryParser( "org.apache.commons.net.ftp.parser.OS2FTPEntryParser"); assertTrue(parser instanceof OS2FTPEntryParser); try { parser = factory.createFileEntryParser( "org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory"); fail("Exception should have been thrown. \"DefaultFTPFileEntryParserFactory\" does not implement FTPFileEntryParser"); } catch (ParserInitializationException pie) { Throwable root = pie.getRootCause(); assertTrue(root instanceof ClassCastException); } } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/FTPConfigEntryParserTest.java0000644000175000017500000001535111014672436032271 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.SimpleDateFormat; import java.util.Calendar; import junit.framework.TestCase; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * This is a simple TestCase that tests entry parsing using the new FTPClientConfig * mechanism. The normal FTPClient cannot handle the different date formats in these * entries, however using a configurable format, we can handle it easily. * * The original system presenting this issue was an AIX system - see bug #27437 for details. * * @version $Id$ */ public class FTPConfigEntryParserTest extends TestCase { private SimpleDateFormat df = new SimpleDateFormat(); public void testParseFieldsOnAIX() { // Set a date format for this server type FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); config.setDefaultDateFormatStr("dd MMM HH:mm"); UnixFTPEntryParser parser = new UnixFTPEntryParser(); parser.configure(config); FTPFile f = parser.parseFTPEntry("-rw-r----- 1 ravensm sca 814 02 Mar 16:27 ZMIR2.m"); assertNotNull("Could not parse entry.", f); assertFalse("Is not a directory.", f.isDirectory()); assertTrue("Should have user read permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should have user write permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION)); assertFalse("Should NOT have user execute permission.", f .hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("Should have group read permission.", f.hasPermission( FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION)); assertFalse("Should NOT have group write permission.", f .hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION)); assertFalse("Should NOT have group execute permission.", f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertFalse("Should NOT have world read permission.", f.hasPermission( FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION)); assertFalse("Should NOT have world write permission.", f .hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION)); assertFalse("Should NOT have world execute permission.", f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertEquals(1, f.getHardLinkCount()); assertEquals("ravensm", f.getUser()); assertEquals("sca", f.getGroup()); assertEquals("ZMIR2.m", f.getName()); assertEquals(814, f.getSize()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.DATE, 2); cal.set(Calendar.HOUR_OF_DAY, 16); cal.set(Calendar.MINUTE, 27); cal.set(Calendar.SECOND, 0); // With no year specified, it defaults to 1970 // TODO this is probably a bug - it should default to the current year cal.set(Calendar.YEAR, 1970); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp() .getTime())); } /** * This is a new format reported on the mailing lists. Parsing this kind of * entry necessitated changing the regex in the parser. * */ public void testParseEntryWithSymlink() { FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm"); UnixFTPEntryParser parser = new UnixFTPEntryParser(); parser.configure(config); FTPFile f = parser.parseFTPEntry("lrwxrwxrwx 1 neeme neeme 23 2005-03-02 18:06 macros"); assertNotNull("Could not parse entry.", f); assertFalse("Is not a directory.", f.isDirectory()); assertTrue("Is a symbolic link", f.isSymbolicLink()); assertTrue("Should have user read permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should have user write permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Should have user execute permission.", f .hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("Should have group read permission.", f.hasPermission( FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should have group write permission.", f .hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Should have group execute permission.", f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("Should have world read permission.", f.hasPermission( FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should have world write permission.", f .hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Should have world execute permission.", f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertEquals(1, f.getHardLinkCount()); assertEquals("neeme", f.getUser()); assertEquals("neeme", f.getGroup()); assertEquals("macros", f.getName()); assertEquals(23, f.getSize()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.DATE, 2); cal.set(Calendar.HOUR_OF_DAY, 18); cal.set(Calendar.MINUTE, 06); cal.set(Calendar.SECOND, 0); cal.set(Calendar.YEAR, 2005); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp() .getTime())); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParserTest.java0000644000175000017500000001103711347047772031474 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: OS2FTPEntryParserTest.java 437134 2006-08-26 09:36:36Z rwinston $ */ public class OS2FTPEntryParserTest extends FTPParseTestFramework { private static final String[] badsamples = { " DIR 12-30-97 12:32 jbrekke", " 0 rsa DIR 11-25-97 09:42 junk", " 0 dir 05-12-97 16:44 LANGUAGE", " 0 DIR 13-05-97 25:49 MPTN", "587823 RSA DIR Jan-08-97 13:58 OS2KRNL", " 33280 A 1997-02-03 13:49 OS2LDR", "12-05-96 05:03PM absoft2", "11-14-97 04:21PM 953 AUDITOR3.INI" }; private static final String[] goodsamples = { " 0 DIR 12-30-97 12:32 jbrekke", " 0 DIR 11-25-97 09:42 junk", " 0 DIR 05-12-97 16:44 LANGUAGE", " 0 DIR 05-19-97 12:56 local", " 0 DIR 05-12-97 16:52 Maintenance Desktop", " 0 DIR 05-13-97 10:49 MPTN", "587823 RSA DIR 01-08-97 13:58 OS2KRNL", " 33280 A 02-09-97 13:49 OS2LDR", " 0 DIR 11-28-97 09:42 PC", "149473 A 11-17-98 16:07 POPUPLOG.OS2", " 0 DIR 05-12-97 16:44 PSFONTS", " 0 DIR 05-19-2000 12:56 local", }; /** * @see junit.framework.TestCase#TestCase(String) */ public OS2FTPEntryParserTest(String name) { super(name); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { FTPFile dir = getParser().parseFTPEntry(" 0 DIR 11-28-97 09:42 PC"); assertNotNull("Could not parse entry.", dir); assertTrue("Should have been a directory.", dir.isDirectory()); assertEquals(0,dir.getSize()); assertEquals("PC", dir.getName()); assertEquals("Fri Nov 28 09:42:00 1997", df.format(dir.getTimestamp().getTime())); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile file = getParser().parseFTPEntry("5000000000 A 11-17-98 16:07 POPUPLOG.OS2"); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a file.", file.isFile()); assertEquals(5000000000L, file.getSize()); assertEquals("POPUPLOG.OS2", file.getName()); assertEquals("Tue Nov 17 16:07:00 1998", df.format(file.getTimestamp().getTime())); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ @Override protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ @Override protected String[] getGoodListing() { return (goodsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser(); parser.configure(null); return parser; } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java0000644000175000017500000003570711347047772032646 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.text.Format; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import org.apache.commons.net.ftp.FTPClientConfig; import junit.framework.TestCase; /** * Test the FTPTimestampParser class. * * @author scohen * */ public class FTPTimestampParserImplTest extends TestCase { private static final int TWO_HOURS_OF_MILLISECONDS = 2 * 60 * 60 * 1000; public void testParseTimestamp() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.HOUR_OF_DAY, 1); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); Date anHourFromNow = cal.getTime(); FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); SimpleDateFormat sdf = new SimpleDateFormat(parser.getRecentDateFormatString()); String fmtTime = sdf.format(anHourFromNow); try { Calendar parsed = parser.parseTimestamp(fmtTime); // since the timestamp is ahead of now (by one hour), // this must mean the file's date refers to a year ago. assertEquals("test.roll.back.year", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR)); } catch (ParseException e) { fail("Unable to parse"); } } public void testParseTimestampWithSlop() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.HOUR_OF_DAY, 1); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); Date anHourFromNow = cal.getTime(); cal.add(Calendar.DATE, 1); Date anHourFromNowTomorrow = cal.getTime(); cal.add(Calendar.DATE, -1); FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); // set the "slop" factor on parser.setLenientFutureDates(true); SimpleDateFormat sdf = new SimpleDateFormat(parser.getRecentDateFormatString()); try { String fmtTime = sdf.format(anHourFromNow); Calendar parsed = parser.parseTimestamp(fmtTime); // the timestamp is ahead of now (by one hour), but // that's within range of the "slop" factor. // so the date is still considered this year. assertEquals("test.slop.no.roll.back.year", 0, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR)); // add a day to get beyond the range of the slop factor. // this must mean the file's date refers to a year ago. fmtTime = sdf.format(anHourFromNowTomorrow); parsed = parser.parseTimestamp(fmtTime); assertEquals("test.slop.roll.back.year", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR)); } catch (ParseException e) { fail("Unable to parse"); } } public void testParseTimestampAcrossTimeZones() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); cal.add(Calendar.HOUR_OF_DAY, 1); Date anHourFromNow = cal.getTime(); cal.add(Calendar.HOUR_OF_DAY, 2); Date threeHoursFromNow = cal.getTime(); cal.add(Calendar.HOUR_OF_DAY, -2); FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); // assume we are FTPing a server in Chicago, two hours ahead of // L. A. FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX); config.setDefaultDateFormatStr(FTPTimestampParser.DEFAULT_SDF); config.setRecentDateFormatStr(FTPTimestampParser.DEFAULT_RECENT_SDF); // 2 hours difference config.setServerTimeZoneId("America/Chicago"); parser.configure(config); SimpleDateFormat sdf = (SimpleDateFormat) parser.getRecentDateFormat().clone(); // assume we're in the US Pacific Time Zone TimeZone tzla = TimeZone.getTimeZone("America/Los_Angeles"); sdf.setTimeZone(tzla); // get formatted versions of time in L.A. String fmtTimePlusOneHour = sdf.format(anHourFromNow); String fmtTimePlusThreeHours = sdf.format(threeHoursFromNow); try { Calendar parsed = parser.parseTimestamp(fmtTimePlusOneHour); // the only difference should be the two hours // difference, no rolling back a year should occur. assertEquals("no.rollback.because.of.time.zones", TWO_HOURS_OF_MILLISECONDS, cal.getTime().getTime() - parsed.getTime().getTime()); } catch (ParseException e){ fail("Unable to parse " + fmtTimePlusOneHour); } //but if the file's timestamp is THREE hours ahead of now, that should //cause a rollover even taking the time zone difference into account. //Since that time is still later than ours, it is parsed as occurring //on this date last year. try { Calendar parsed = parser.parseTimestamp(fmtTimePlusThreeHours); // rollback should occur here. assertEquals("rollback.even.with.time.zones", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR)); } catch (ParseException e){ fail("Unable to parse" + fmtTimePlusThreeHours); } } public void testParser() { FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); try { parser.parseTimestamp("feb 22 2002"); } catch (ParseException e) { fail("failed.to.parse.default"); } try { parser.parseTimestamp("f\u00e9v 22 2002"); fail("should.have.failed.to.parse.default"); } catch (ParseException e) { // this is the success case } FTPClientConfig config = new FTPClientConfig(); config.setDefaultDateFormatStr("d MMM yyyy"); config.setRecentDateFormatStr("d MMM HH:mm"); config.setServerLanguageCode("fr"); parser.configure(config); try { parser.parseTimestamp("d\u00e9c 22 2002"); fail("incorrect.field.order"); } catch (ParseException e) { // this is the success case } try { parser.parseTimestamp("22 d\u00e9c 2002"); } catch (ParseException e) { fail("failed.to.parse.french"); } try { parser.parseTimestamp("22 dec 2002"); fail("incorrect.language"); } catch (ParseException e) { // this is the success case } try { parser.parseTimestamp("29 f\u00e9v 2002"); fail("nonexistent.date"); } catch (ParseException e) { // this is the success case } try { parser.parseTimestamp("22 ao\u00fb 30:02"); fail("bad.hour"); } catch (ParseException e) { // this is the success case } try { parser.parseTimestamp("22 ao\u00fb 20:74"); fail("bad.minute"); } catch (ParseException e) { // this is the success case } try { parser.parseTimestamp("28 ao\u00fb 20:02"); } catch (ParseException e) { fail("failed.to.parse.french.recent"); } } /* * Check how short date is interpreted at a given time. * Check both with and without lenient future dates */ private void checkShortParse(String msg, Calendar now, Calendar input) throws ParseException { checkShortParse(msg, now, input, false); checkShortParse(msg, now, input, true); } /* * Check how short date is interpreted at a given time * Check only using specified lenient future dates setting */ private void checkShortParse(String msg, Calendar now, Calendar input, boolean lenient) throws ParseException { FTPTimestampParserImpl parser = new FTPTimestampParserImpl(); parser.setLenientFutureDates(lenient); Format shortFormat = parser.getRecentDateFormat(); // It's expecting this format Format longFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm"); final String shortDate = shortFormat.format(input.getTime()); Calendar output=parser.parseTimestamp(shortDate, now); int outyear = output.get(Calendar.YEAR); int outdom = output.get(Calendar.DAY_OF_MONTH); int outmon = output.get(Calendar.MONTH); int inyear = input.get(Calendar.YEAR); int indom = input.get(Calendar.DAY_OF_MONTH); int inmon = input.get(Calendar.MONTH); if (indom != outdom || inmon != outmon || inyear != outyear){ fail("Test: '"+msg+"' Server="+longFormat.format(now.getTime()) +". Failed to parse "+shortDate +". Actual "+longFormat.format(output.getTime()) +". Expected "+longFormat.format(input.getTime())); } } public void testParseShortPastDates1() throws Exception { GregorianCalendar now = new GregorianCalendar(2001, Calendar.MAY, 30, 12, 0); checkShortParse("2001-5-30",now,now); // should always work GregorianCalendar target = (GregorianCalendar) now.clone(); target.add(Calendar.WEEK_OF_YEAR, -1); checkShortParse("2001-5-30 -1 week",now,target); target.add(Calendar.WEEK_OF_YEAR, -12); checkShortParse("2001-5-30 -13 weeks",now,target); target.add(Calendar.WEEK_OF_YEAR, -13); checkShortParse("2001-5-30 -26 weeks",now,target); } public void testParseShortPastDates2() throws Exception { GregorianCalendar now = new GregorianCalendar(2004, Calendar.AUGUST, 1, 12, 0); checkShortParse("2004-8-1",now,now); // should always work GregorianCalendar target = (GregorianCalendar) now.clone(); target.add(Calendar.WEEK_OF_YEAR, -1); checkShortParse("2004-8-1 -1 week",now,target); target.add(Calendar.WEEK_OF_YEAR, -12); checkShortParse("2004-8-1 -13 weeks",now,target); target.add(Calendar.WEEK_OF_YEAR, -13); checkShortParse("2004-8-1 -26 weeks",now,target); } // It has not yet been decided how to handle future dates, so skip these tests for now // public void testParseShortFutureDates1() throws Exception { // GregorianCalendar now = new GregorianCalendar(2001, Calendar.MAY, 30, 12, 0); // checkShortParse("2001-5-30",now,now); // should always work // GregorianCalendar target = (GregorianCalendar) now.clone(); // target.add(Calendar.WEEK_OF_YEAR, 1); // checkShortParse("2001-5-30 +1 week",now,target); // target.add(Calendar.WEEK_OF_YEAR, 12); // checkShortParse("2001-5-30 +13 weeks",now,target); // target.add(Calendar.WEEK_OF_YEAR, 13); // checkShortParse("2001-5-30 +26 weeks",now,target); // } // public void testParseShortFutureDates2() throws Exception { // GregorianCalendar now = new GregorianCalendar(2004, Calendar.AUGUST, 1, 12, 0); // checkShortParse("2004-8-1",now,now); // should always work // GregorianCalendar target = (GregorianCalendar) now.clone(); // target.add(Calendar.WEEK_OF_YEAR, 1); // checkShortParse("2004-8-1 +1 week",now,target); // target.add(Calendar.WEEK_OF_YEAR, 12); // checkShortParse("2004-8-1 +13 weeks",now,target); // target.add(Calendar.WEEK_OF_YEAR, 13); // checkShortParse("2004-8-1 +26 weeks",now,target); // } // Test leap year if current year is a leap year public void testFeb29IfLeapYear() throws Exception{ GregorianCalendar now = new GregorianCalendar(); final int thisYear = now.get(Calendar.YEAR); if (now.isLeapYear(thisYear) && now.before(new GregorianCalendar(thisYear,Calendar.AUGUST,29))){ GregorianCalendar target = new GregorianCalendar(thisYear,Calendar.FEBRUARY,29); checkShortParse("Feb 29th",now,target); } else { System.out.println("Skipping Feb 29 test"); } } // Test Feb 29 for a known leap year public void testFeb29LeapYear() throws Exception{ int year = 2000; // Use same year for current and short date GregorianCalendar now = new GregorianCalendar(year, Calendar.APRIL, 1, 12, 0); checkShortParse("Feb 29th 2000",now,new GregorianCalendar(year, Calendar.FEBRUARY,29)); } // Test Feb 29 for a known non-leap year - should fail public void testFeb29NonLeapYear(){ GregorianCalendar now = new GregorianCalendar(1999, Calendar.APRIL, 1, 12, 0); // Note: we use a known leap year for the target date to avoid rounding up try { checkShortParse("Feb 29th 1999",now,new GregorianCalendar(2000, Calendar.FEBRUARY,29)); fail("Should have failed to parse Feb 29th 1999"); } catch (ParseException expected) { } } public void testParseDec31Lenient() throws Exception { GregorianCalendar now = new GregorianCalendar(2007, Calendar.DECEMBER, 30, 12, 0); checkShortParse("2007-12-30",now,now); // should always work GregorianCalendar target = (GregorianCalendar) now.clone(); target.add(Calendar.DAY_OF_YEAR, +1); // tomorrow checkShortParse("2007-12-31",now,target, true); } public void testParseJan01Lenient() throws Exception { GregorianCalendar now = new GregorianCalendar(2007, Calendar.DECEMBER, 31, 12, 0); checkShortParse("2007-12-31",now,now); // should always work GregorianCalendar target = (GregorianCalendar) now.clone(); target.add(Calendar.DAY_OF_YEAR, +1); // tomorrow checkShortParse("2008-1-1",now,target, true); } public void testParseJan01() throws Exception { GregorianCalendar now = new GregorianCalendar(2007, Calendar.JANUARY, 1, 12, 0); checkShortParse("2007-01-01",now,now); // should always work GregorianCalendar target = new GregorianCalendar(2006, Calendar.DECEMBER, 31, 12, 0); checkShortParse("2006-12-31",now,target, true); checkShortParse("2006-12-31",now,target, false); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParserTest.java0000644000175000017500000001337111347047772031641 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; import java.util.Calendar; /** * @version $Id: OS400FTPEntryParserTest.java 155429 2005-02-26 13:13:04Z dirkv $ */ public class OS400FTPEntryParserTest extends CompositeFTPParseTestFramework { private static final String[][] badsamples = { { "PEP 4019 04/03/18 18:58:16 STMF einladung.zip", "PEP 422 03/24 14:06:26 *STMF readme", "PEP 6409 04/03/24 30:06:29 *STMF build.xml", "PEP USR 36864 04/03/24 14:06:34 *DIR dir1/", "PEP 3686404/03/24 14:06:47 *DIR zdir2/" }, { "----rwxr-x 1PEP 0 4019 Mar 18 18:58 einladung.zip", "----rwxr-x 1 PEP 0 xx 422 Mar 24 14:06 readme", "----rwxr-x 1 PEP 0 8492 Apr 07 30:13 build.xml", "d---rwxr-x 2 PEP 0 45056Mar 24 14:06 zdir2" } }; private static final String[][] goodsamples = { { "PEP 4019 04/03/18 18:58:16 *STMF einladung.zip", "PEP 422 04/03/24 14:06:26 *STMF readme", "PEP 6409 04/03/24 14:06:29 *STMF build.xml", "PEP 36864 04/03/24 14:06:34 *DIR dir1/", "PEP 36864 04/03/24 14:06:47 *DIR zdir2/" }, { "----rwxr-x 1 PEP 0 4019 Mar 18 18:58 einladung.zip", "----rwxr-x 1 PEP 0 422 Mar 24 14:06 readme", "----rwxr-x 1 PEP 0 8492 Apr 07 07:13 build.xml", "d---rwxr-x 2 PEP 0 45056 Mar 24 14:06 dir1", "d---rwxr-x 2 PEP 0 45056 Mar 24 14:06 zdir2" } }; /** * @see junit.framework.TestCase#TestCase(String) */ public OS400FTPEntryParserTest(String name) { super(name); } /** * @see FTPParseTestFramework#getBadListing() */ @Override protected String[][] getBadListings() { return badsamples; } /** * @see FTPParseTestFramework#getGoodListing() */ @Override protected String[][] getGoodListings() { return goodsamples; } /** * @see FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new OS400FTPEntryParser(), new UnixFTPEntryParser() }); } /** * @see FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { FTPFile f = getParser().parseFTPEntry("PEP 36864 04/03/24 14:06:34 *DIR dir1/"); assertNotNull("Could not parse entry.", f); assertTrue("Should have been a directory.", f.isDirectory()); assertEquals("PEP", f.getUser()); assertEquals("dir1", f.getName()); assertEquals(36864, f.getSize()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.YEAR, 2004); cal.set(Calendar.DATE, 24); cal.set(Calendar.HOUR_OF_DAY, 14); cal.set(Calendar.MINUTE, 6); cal.set(Calendar.SECOND, 34); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime())); } @Override protected void doAdditionalGoodTests(String test, FTPFile f) { if (test.startsWith("d")) { assertEquals("directory.type", FTPFile.DIRECTORY_TYPE, f.getType()); } } /** * @see FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile f = getParser().parseFTPEntry("PEP 5000000000 04/03/24 14:06:29 *STMF build.xml"); assertNotNull("Could not parse entry.", f); assertTrue("Should have been a file.", f.isFile()); assertEquals("PEP", f.getUser()); assertEquals("build.xml", f.getName()); assertEquals(5000000000L, f.getSize()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.DATE, 24); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.YEAR, 2004); cal.set(Calendar.HOUR_OF_DAY, 14); cal.set(Calendar.MINUTE, 6); cal.set(Calendar.SECOND, 29); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime())); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootcommons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.javacommons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.jav0000644000175000017500000001702511347047772033717 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.Calendar; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * Tests the EnterpriseUnixFTPEntryParser * * @version $Id: EnterpriseUnixFTPEntryParserTest.java 437134 2006-08-26 09:36:36Z rwinston $ * @author Winston Ojeda */ public class EnterpriseUnixFTPEntryParserTest extends FTPParseTestFramework { private static final String[] BADSAMPLES = { "zrwxr-xr-x 2 root root 4096 Mar 2 15:13 zxbox", "dxrwr-xr-x 2 root root 4096 Aug 24 2001 zxjdbc", "drwxr-xr-x 2 root root 4096 Jam 4 00:03 zziplib", "drwxr-xr-x 2 root 99 4096 Feb 23 30:01 zzplayer", "drwxr-xr-x 2 root root 4096 Aug 36 2001 zztpp", "-rw-r--r-- 1 14 staff 80284 Aug 22 zxJDBC-1.2.3.tar.gz", "-rw-r--r-- 1 14 staff 119:26 Aug 22 2000 zxJDBC-1.2.3.zip", "-rw-r--r-- 1 ftp no group 83853 Jan 22 2001 zxJDBC-1.2.4.tar.gz", "-rw-r--r-- 1ftp nogroup 126552 Jan 22 2001 zxJDBC-1.2.4.zip", "-rw-r--r-- 1 root root 111325 Apr -7 18:79 zxJDBC-2.0.1b1.tar.gz", "drwxr-xr-x 2 root root 4096 Mar 2 15:13 zxbox", "drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog", "drwxr-xr-x 2 root root 4096 Aug 24 2001 zxjdbc", "drwxr-xr-x 2 root root 4096 Jan 4 00:03 zziplib", "drwxr-xr-x 2 root 99 4096 Feb 23 2001 zzplayer", "drwxr-xr-x 2 root root 4096 Aug 6 2001 zztpp", "-rw-r--r-- 1 14 staff 80284 Aug 22 2000 zxJDBC-1.2.3.tar.gz", "-rw-r--r-- 1 14 staff 119926 Aug 22 2000 zxJDBC-1.2.3.zip", "-rw-r--r-- 1 ftp nogroup 83853 Jan 22 2001 zxJDBC-1.2.4.tar.gz", "-rw-r--r-- 1 ftp nogroup 126552 Jan 22 2001 zxJDBC-1.2.4.zip", "-rw-r--r-- 1 root root 111325 Apr 27 2001 zxJDBC-2.0.1b1.tar.gz", "-rw-r--r-- 1 root root 190144 Apr 27 2001 zxJDBC-2.0.1b1.zip" }; private static final String[] GOODSAMPLES = { "-C--E-----FTP B QUA1I1 18128 41 Aug 12 13:56 QUADTEST", "-C--E-----FTP A QUA1I1 18128 41 Aug 12 13:56 QUADTEST2" }; /** * Creates a new EnterpriseUnixFTPEntryParserTest object. * * @param name Test name. */ public EnterpriseUnixFTPEntryParserTest(String name) { super(name); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { // Everything is a File for now. } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile file = getParser().parseFTPEntry("-C--E-----FTP B QUA1I1 18128 5000000000 Aug 12 13:56 QUADTEST"); Calendar today = Calendar.getInstance(); int year = today.get(Calendar.YEAR); assertTrue("Should be a file.", file.isFile()); assertEquals("QUADTEST", file.getName()); assertEquals(5000000000L, file.getSize()); assertEquals("QUA1I1", file.getUser()); assertEquals("18128", file.getGroup()); if(today.get(Calendar.MONTH) < Calendar.AUGUST) --year; Calendar timestamp = file.getTimestamp(); assertEquals(year, timestamp.get(Calendar.YEAR)); assertEquals(Calendar.AUGUST, timestamp.get(Calendar.MONTH)); assertEquals(12, timestamp.get(Calendar.DAY_OF_MONTH)); assertEquals(13, timestamp.get(Calendar.HOUR_OF_DAY)); assertEquals(56, timestamp.get(Calendar.MINUTE)); assertEquals(0, timestamp.get(Calendar.SECOND)); checkPermisions(file); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ @Override protected String[] getBadListing() { return (BADSAMPLES); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ @Override protected String[] getGoodListing() { return (GOODSAMPLES); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { return (new EnterpriseUnixFTPEntryParser()); } /** * Method checkPermisions. Verify that the parser does NOT set the * permissions. * * @param dir */ private void checkPermisions(FTPFile dir) { assertTrue("Owner should not have read permission.", !dir.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Owner should not have write permission.", !dir.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Owner should not have execute permission.", !dir.hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("Group should not have read permission.", !dir.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Group should not have write permission.", !dir.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Group should not have execute permission.", !dir.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("World should not have read permission.", !dir.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("World should not have write permission.", !dir.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("World should not have execute permission.", !dir.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java0000644000175000017500000004045311347053246032011 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.Calendar; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: UnixFTPEntryParserTest.java 629276 2008-02-19 23:31:25Z rwinston $ */ public class UnixFTPEntryParserTest extends FTPParseTestFramework { private static final String[] badsamples = { "zrwxr-xr-x 2 root root 4096 Mar 2 15:13 zxbox", "dxrwr-xr-x 2 root root 4096 Aug 24 2001 zxjdbc", "drwxr-xr-x 2 root root 4096 Jam 4 00:03 zziplib", "drwxr-xr-x 2 root 99 4096 Feb 23 30:01 zzplayer", "drwxr-xr-x 2 root root 4096 Aug 36 2001 zztpp", "-rw-r--r-- 1 14 staff 80284 Aug 22 zxJDBC-1.2.3.tar.gz", "-rw-r--r-- 1 14 staff 119:26 Aug 22 2000 zxJDBC-1.2.3.zip", /*"-rw-r--r-- 1 ftp no group 83853 Jan 22 2001 zxJDBC-1.2.4.tar.gz",*/ "-rw-r--r-- 1ftp nogroup 126552 Jan 22 2001 zxJDBC-1.2.4.zip", "-rw-r--r-- 1 root root 190144 2001-04-27 zxJDBC-2.0.1b1.zip", "-rw-r--r-- 1 root root 111325 Apr -7 18:79 zxJDBC-2.0.1b1.tar.gz" }; private static final String[] goodsamples = { "-rw-r--r-- 1 500 500 21 Aug 8 14:14 JB3-TES1.gz", "-rwxr-xr-x 2 root root 4096 Mar 2 15:13 zxbox", "drwxr-xr-x 2 root root 4096 Aug 24 2001 zxjdbc", "drwxr-xr-x 2 root root 4096 Jan 4 00:03 zziplib", "drwxr-xr-x 2 root 99 4096 Feb 23 2001 zzplayer", "drwxr-xr-x 2 root root 4096 Aug 6 2001 zztpp", "drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog", "lrw-r--r-- 1 14 14 80284 Aug 22 2000 zxJDBC-1.2.3.tar.gz", "frw-r--r-- 1 14 staff 119926 Aug 22 2000 zxJDBC-1.2.3.zip", "crw-r--r-- 1 ftp nogroup 83853 Jan 22 2001 zxJDBC-1.2.4.tar.gz", "brw-r--r-- 1 ftp nogroup 126552 Jan 22 2001 zxJDBC-1.2.4.zip", "-rw-r--r-- 1 root root 111325 Apr 27 2001 zxJDBC-2.0.1b1.tar.gz", "-rw-r--r-- 1 root root 190144 Apr 27 2001 zxJDBC-2.0.1b1.zip", "-rwxr-xr-x 2 500 500 166 Nov 2 2001 73131-testtes1.afp", "-rw-r--r-- 1 500 500 166 Nov 9 2001 73131-testtes1.AFP", "-rw-r--r-- 1 500 500 166 Nov 12 2001 73131-testtes2.afp", "-rw-r--r-- 1 500 500 166 Nov 12 2001 73131-testtes2.AFP", "-rw-r--r-- 1 500 500 2040000 Aug 5 07:35 testRemoteUPCopyNIX", "-rw-r--r-- 1 500 500 2040000 Aug 5 07:31 testRemoteUPDCopyNIX", "-rw-r--r-- 1 500 500 2040000 Aug 5 07:31 testRemoteUPVCopyNIX", "-rw-r--r-T 1 500 500 0 Mar 25 08:20 testSticky", "-rwxr-xr-t 1 500 500 0 Mar 25 08:21 testStickyExec", "-rwSr-Sr-- 1 500 500 0 Mar 25 08:22 testSuid", "-rwsr-sr-- 1 500 500 0 Mar 25 08:23 testSuidExec", "-rwsr-sr-- 1 500 500 0 Mar 25 0:23 testSuidExec2", "drwxrwx---+ 23 500 500 0 Jan 10 13:09 testACL", "-rw-r--r-- 1 1 3518644 May 25 12:12 std", "lrwxrwxrwx 1 neeme neeme 23 Mar 2 18:06 macros -> ./../../global/macros/.", "-rw-r--r-- 1 ftp group with spaces in it as allowed in cygwin see bug 38634 83853 Jan 22 2001 zxJDBC-1.2.4.tar.gz", "crw-r----- 1 root kmem 0, 27 Jan 30 11:42 kmem", //FreeBSD device "crw------- 1 root sys 109,767 Jul 2 2004 pci@1c,600000:devctl", //Solaris device "-rwxrwx--- 1 ftp ftp-admin 816026400 Oct 5 2008 bloplab 7 cd1.img", // NET-294 }; /** * @see junit.framework.TestCase#TestCase(String) */ public UnixFTPEntryParserTest(String name) { super(name); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ @Override protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ @Override protected String[] getGoodListing() { return (goodsamples); } /** */ public void testNumericDateFormat() { String testNumericDF = "-rw-r----- 1 neeme neeme 346 2005-04-08 11:22 services.vsp"; String testNumericDF2 = "lrwxrwxrwx 1 neeme neeme 23 2005-03-02 18:06 macros -> ./../../global/macros/."; UnixFTPEntryParser parser = new UnixFTPEntryParser(UnixFTPEntryParser.NUMERIC_DATE_CONFIG); FTPFile f = parser.parseFTPEntry(testNumericDF); assertNotNull("Failed to parse " + testNumericDF, f); Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(Calendar.YEAR, 2005); cal.set(Calendar.MONTH, Calendar.APRIL); cal.set(Calendar.DATE, 8); cal.set(Calendar.HOUR_OF_DAY, 11); cal.set(Calendar.MINUTE, 22); assertEquals(cal.getTime(), f.getTimestamp().getTime()); FTPFile f2 = parser.parseFTPEntry(testNumericDF2); assertNotNull("Failed to parse " + testNumericDF2, f2); assertEquals("symbolic link", "./../../global/macros/.", f2.getLink()); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { return (new UnixFTPEntryParser()); } public void testOwnerNameWithSpaces() { FTPFile f = getParser().parseFTPEntry("drwxr-xr-x 2 john smith group 4096 Mar 2 15:13 zxbox"); assertNotNull(f); assertEquals("john smith", f.getUser()); } public void testOwnerAndGroupNameWithSpaces() { FTPFile f = getParser().parseFTPEntry("drwxr-xr-x 2 john smith test group 4096 Mar 2 15:13 zxbox"); assertNotNull(f); assertEquals("john smith", f.getUser()); assertEquals("test group", f.getGroup()); } public void testNET294() { FTPFile f = getParser().parseFTPEntry( "-rwxrwx--- 1 ftp ftp-admin 816026400 Oct 5 2008 bloplab 7 cd1.img"); assertNotNull(f); assertEquals("ftp", f.getUser()); assertEquals("ftp-admin", f.getGroup()); assertEquals(816026400L,f.getSize()); assertNotNull("Timestamp should not be null",f.getTimestamp()); assertEquals(2008,f.getTimestamp().get(Calendar.YEAR)); assertEquals("bloplab 7 cd1.img",f.getName()); } public void testGroupNameWithSpaces() { FTPFile f = getParser().parseFTPEntry("drwx------ 4 maxm Domain Users 512 Oct 2 10:59 .metadata"); assertNotNull(f); assertEquals("maxm", f.getUser()); assertEquals("Domain Users", f.getGroup()); } public void testTrailingSpaces() { FTPFile f = getParser().parseFTPEntry("drwxr-xr-x 2 john smith group 4096 Mar 2 15:13 zxbox "); assertNotNull(f); assertEquals(f.getName(), "zxbox "); } public void testNameWIthPunctuation() { FTPFile f = getParser().parseFTPEntry("drwx------ 4 maxm Domain Users 512 Oct 2 10:59 abc(test)123.pdf"); assertNotNull(f); assertEquals(f.getName(), "abc(test)123.pdf"); } public void testNoSpacesBeforeFileSize() { FTPFile f = getParser().parseFTPEntry("drwxr-x---+1464 chrism chrism 41472 Feb 25 13:17 20090225"); assertNotNull(f); assertEquals(f.getSize(), 41472); assertEquals(f.getType(), FTPFile.DIRECTORY_TYPE); assertEquals(f.getUser(), "chrism"); assertEquals(f.getGroup(), "chrism"); assertEquals(f.getHardLinkCount(), 1464); } public void testCorrectGroupNameParsing() { FTPFile f = getParser().parseFTPEntry("-rw-r--r-- 1 ftpuser ftpusers 12414535 Mar 17 11:07 test 1999 abc.pdf"); assertNotNull(f); assertEquals(f.getHardLinkCount(), 1); assertEquals(f.getUser(), "ftpuser"); assertEquals(f.getGroup(), "ftpusers"); assertEquals(f.getSize(), 12414535); assertEquals(f.getName(), "test 1999 abc.pdf"); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.DAY_OF_MONTH, 17); cal.set(Calendar.HOUR_OF_DAY, 11); cal.set(Calendar.MINUTE, 7); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); assertEquals(f.getTimestamp().get(Calendar.MONTH), cal.get(Calendar.MONTH)); assertEquals(f.getTimestamp().get(Calendar.DAY_OF_MONTH), cal.get(Calendar.DAY_OF_MONTH)); assertEquals(f.getTimestamp().get(Calendar.HOUR_OF_DAY), cal.get(Calendar.HOUR_OF_DAY)); assertEquals(f.getTimestamp().get(Calendar.MINUTE), cal.get(Calendar.MINUTE)); assertEquals(f.getTimestamp().get(Calendar.SECOND), cal.get(Calendar.SECOND)); } public void testFilenamesWithEmbeddedNumbers() { FTPFile f = getParser().parseFTPEntry("-rw-rw-rw- 1 user group 5840 Mar 19 09:34 123 456 abc.csv"); assertEquals(f.getName(), "123 456 abc.csv"); assertEquals(f.getSize(), 5840); assertEquals(f.getUser(), "user"); assertEquals(f.getGroup(), "group"); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { FTPFile f = getParser().parseFTPEntry("drwxr-xr-x 2 user group 4096 Mar 2 15:13 zxbox"); assertNotNull("Could not parse entry.", f); assertTrue("Should have been a directory.", f.isDirectory()); checkPermissions(f); assertEquals(2, f.getHardLinkCount()); assertEquals("user", f.getUser()); assertEquals("group", f.getGroup()); assertEquals("zxbox", f.getName()); assertEquals(4096, f.getSize()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.DATE, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); if (f.getTimestamp().getTime().before(cal.getTime())) { cal.add(Calendar.YEAR, -1); } cal.set(Calendar.DATE, 2); cal.set(Calendar.HOUR_OF_DAY, 15); cal.set(Calendar.MINUTE, 13); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp() .getTime())); } /** * Method checkPermissions. * Verify that the persmissions were properly set. * @param f */ private void checkPermissions(FTPFile f) { assertTrue("Should have user read permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should have user write permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Should have user execute permission.", f.hasPermission( FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("Should have group read permission.", f.hasPermission( FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should NOT have group write permission.", !f.hasPermission( FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Should have group execute permission.", f.hasPermission( FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)); assertTrue("Should have world read permission.", f.hasPermission( FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION)); assertTrue("Should NOT have world write permission.", !f.hasPermission( FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION)); assertTrue("Should have world execute permission.", f.hasPermission( FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile f = getParser() .parseFTPEntry( "-rwxr-xr-x 2 user my group 500 5000000000 Mar 2 15:13 zxbox"); assertNotNull("Could not parse entry.", f); assertTrue("Should have been a file.", f.isFile()); checkPermissions(f); assertEquals(2, f.getHardLinkCount()); assertEquals("user", f.getUser()); assertEquals("my group 500", f.getGroup()); assertEquals("zxbox", f.getName()); assertEquals(5000000000L, f.getSize()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.MARCH); cal.set(Calendar.DATE, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); if (f.getTimestamp().getTime().before(cal.getTime())) { cal.add(Calendar.YEAR, -1); } cal.set(Calendar.DATE, 2); cal.set(Calendar.HOUR_OF_DAY, 15); cal.set(Calendar.MINUTE, 13); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime())); } /* * @param test * @param f */ @Override protected void doAdditionalGoodTests(String test, FTPFile f) { String link = f.getLink(); if (null != link) { int linklen = link.length(); if (linklen > 0) { assertEquals(link, test.substring(test.length() - linklen)); assertEquals(f.getType(), FTPFile.SYMBOLIC_LINK_TYPE); } } int type = f.getType(); switch (test.charAt(0)) { case 'd': assertEquals("Type of "+ test, type, FTPFile.DIRECTORY_TYPE); break; case 'l': assertEquals("Type of "+ test, type, FTPFile.SYMBOLIC_LINK_TYPE); break; case 'b': case 'c': assertEquals(0, f.getHardLinkCount()); //$FALL-THROUGH$ TODO this needs to be fixed if a device type is introduced case 'f': case '-': assertEquals("Type of "+ test, type, FTPFile.FILE_TYPE); break; default: assertEquals("Type of "+ test, type, FTPFile.UNKNOWN_TYPE); } for (int access = FTPFile.USER_ACCESS; access <= FTPFile.WORLD_ACCESS; access++) { for (int perm = FTPFile.READ_PERMISSION; perm <= FTPFile.EXECUTE_PERMISSION; perm++) { int pos = 3*access + perm + 1; char permchar = test.charAt(pos); assertEquals("Permission " + test.substring(1,10), Boolean.valueOf(f.hasPermission(access, perm)), Boolean.valueOf(permchar != '-' && !Character.isUpperCase(permchar))); } } assertNotNull("Expected to find a timestamp",f.getTimestamp()); // Perhaps check date range (need to ensure all good examples qualify) // assertTrue(test,f.getTimestamp().get(Calendar.YEAR)>=2000); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParserTest.java0000644000175000017500000001074511347047772032503 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.Calendar; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Rory Winston * @version $Id: NetwareFTPEntryParserTest.java 492109 2007-01-03 11:24:57Z rwinston $ */ public class NetwareFTPEntryParserTest extends FTPParseTestFramework { private static final String[] badsamples = { "a [-----F--] SCION_SYS 512 Apr 13 23:52 SYS", "d [----AF--] 0 512 10-04-2001 _ADMIN" }; private static final String [] goodsamples = { "d [-----F--] SCION_SYS 512 Apr 13 23:52 SYS", "d [----AF--] 0 512 Feb 22 17:32 _ADMIN", "d [-W---F--] SCION_VOL2 512 Apr 13 23:12 VOL2", "- [RWCEAFMS] rwinston 19968 Mar 12 15:20 Executive Summary.doc", "d [RWCEAFMS] rwinston 512 Nov 24 2005 Favorites" }; /** * @see junit.framework.TestCase#TestCase(String) */ public NetwareFTPEntryParserTest(String name) { super(name); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ @Override protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ @Override protected String[] getGoodListing() { return (goodsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { return (new NetwareFTPEntryParser()); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { String reply = "d [-W---F--] testUser 512 Apr 13 23:12 testFile"; FTPFile f = getParser().parseFTPEntry(reply); assertNotNull("Could not parse file", f); assertEquals("testFile", f.getName()); assertEquals(512L, f.getSize()); assertEquals("testUser", f.getUser()); assertTrue("Directory flag is not set!", f.isDirectory()); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, 3); cal.set(Calendar.DAY_OF_MONTH, 13); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 12); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.YEAR, f.getTimestamp().get(Calendar.YEAR)); assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp() .getTime())); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { String reply = "- [R-CEAFMS] rwinston 19968 Mar 12 15:20 Document name with spaces.doc"; FTPFile f = getParser().parseFTPEntry(reply); assertNotNull("Could not parse file", f); assertEquals("Document name with spaces.doc", f.getName()); assertEquals(19968L, f.getSize()); assertEquals("rwinston", f.getUser()); assertTrue("File flag is not set!", f.isFile()); assertTrue(f.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION)); assertFalse(f.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION)); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java0000644000175000017500000002373411416064646031541 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.ArrayList; import java.util.List; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * Changed on August 31, 2006
* Test suite addapted to new MVSFTPEntryParser.java. * @author Henrik Sorensen * * Created on Apr 6, 2005
* @author William Noto * @version $Id: MVSFTPEntryParserTest.java,v 1.16 2005/01/02 03:17:50 scohen Exp $ */ public class MVSFTPEntryParserTest extends FTPParseTestFramework { private static final String[] goodsamplesDatasetList = { /* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ // "Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname", "SAVE00 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.D061704", "SAVE01 3390 2004/06/23 1 1 FB 128 6144 PO INCOMING.RPTBM024.D061704", "SAVE02 3390 2004/06/23 1 1 FB 128 6144 PO-E INCOMING.RPTBM025.D061704", "PSMLC1 3390 2005/04/04 1 1 VB 27994 27998 PS file3.I", "PSMLB9 3390 2005/04/04 1 1 VB 27994 27998 PS file4.I.BU", "PSMLB6 3390 2005/04/05 1 1 VB 27994 27998 PS file3.I.BU", "PSMLC6 3390 2005/04/05 1 1 VB 27994 27998 PS file6.I", "PSMLB7 3390 2005/04/04 1 1 VB 27994 27998 PS file7.O", "PSMLC6 3390 2005/04/05 1 1 VB 27994 27998 PS file7.O.BU", "FPFS49 3390 2004/06/23 1 1 FB 128 6144 PO-E INCOMING.RPTBM026.D061704", "FPFS41 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM056.D061704", "FPFS25 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.WTM204.D061704", }; private static final String[] goodsamplesMemberList = {/* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ "Name VV.MM Created Changed Size Init Mod Id", "SAVE03 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", "SAVE04 ", // no statistics "TBSHELF1 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", "TBSHELF2 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", "TBSHELF3 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", "TBSHELF4 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", }; private static final String[] goodsamplesJES1List = { /* no header for JES1 (JES Interface level 1) */ /* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ "IBMUSER1 JOB01906 OUTPUT 3 Spool Files", }; private static final String[] goodsamplesJES2List = { /* JES2 (JES Interface level 2) */ /* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ //"JOBNAME JOBID OWNER STATUS CLASS", "IBMUSER2 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool files", "IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files", }; private static final String[] badsamples = { "MigratedP201.$FTXPBI1.$CF2ITB.$AAB0402.I", "PSMLC133902005/04/041VB2799427998PSfile1.I", "file2.O", }; /** * @see junit.framework.TestCase#TestCase(String) */ public MVSFTPEntryParserTest(String name) { super(name); } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getBadListings() */ @Override protected String[] getBadListing() { return badsamples; } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getGoodListings() */ @Override protected String[] getGoodListing() { return goodsamplesDatasetList; } protected List getAllGoodListings() { List l = new ArrayList(); l.add(goodsamplesDatasetList); l.add(goodsamplesMemberList); l.add(goodsamplesJES1List); l.add(goodsamplesJES2List); return l; } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { return new MVSFTPEntryParser(); } /* * note the testGoodListing has to be the first test invoked, because * some FTPFile entries are saved for the later tests * * (non-Javadoc) * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testGoodListing() */ @Override public void testGoodListing() throws Exception { String[] goodsamples = getGoodListing(); MVSFTPEntryParser parser = new MVSFTPEntryParser(); parser.setType(MVSFTPEntryParser.FILE_LIST_TYPE); parser.setRegex(MVSFTPEntryParser.FILE_LIST_REGEX); for (String test : goodsamples) { FTPFile f = parser.parseFTPEntry(test); assertNotNull("Failed to parse " + test, f); doAdditionalGoodTests(test, f); } } public void testMemberListing() throws Exception { MVSFTPEntryParser parser = new MVSFTPEntryParser(); parser.setType(MVSFTPEntryParser.MEMBER_LIST_TYPE); parser.setRegex(MVSFTPEntryParser.MEMBER_LIST_REGEX); for (String test : goodsamplesMemberList) { FTPFile f = parser.parseFTPEntry(test); assertNotNull("Failed to parse " + test, f); doAdditionalGoodTests(test, f); } } public void testJesLevel1Listing() { MVSFTPEntryParser parser = new MVSFTPEntryParser(); parser.setType(MVSFTPEntryParser.JES_LEVEL_1_LIST_TYPE); parser.setRegex(MVSFTPEntryParser.JES_LEVEL_1_LIST_REGEX); for (String test : goodsamplesJES1List) { FTPFile f = parser.parseFTPEntry(test); assertNotNull("Failed to parse " + test, f); doAdditionalGoodTests(test, f); } } public void testJesLevel2Listing() { MVSFTPEntryParser parser = new MVSFTPEntryParser(); parser.setType(MVSFTPEntryParser.JES_LEVEL_2_LIST_TYPE); parser.setRegex(MVSFTPEntryParser.JES_LEVEL_2_LIST_REGEX); for (String test : goodsamplesJES2List) { FTPFile f = parser.parseFTPEntry(test); assertNotNull("Failed to parse " + test, f); doAdditionalGoodTests(test, f); } } @Override public void testParseFieldsOnDirectory() throws Exception { MVSFTPEntryParser parser = new MVSFTPEntryParser(); parser.setType(MVSFTPEntryParser.FILE_LIST_TYPE); parser.setRegex(MVSFTPEntryParser.FILE_LIST_REGEX); FTPFile file = parser .parseFTPEntry("SAVE01 3390 2004/06/23 1 1 FB 128 6144 PO INCOMING.RPTBM024.D061704"); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a directory.", file.isDirectory()); assertEquals("INCOMING.RPTBM024.D061704", file.getName()); file = parser .parseFTPEntry("SAVE02 3390 2004/06/23 1 1 FB 128 6144 PO-E INCOMING.RPTBM025.D061704"); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a directory.", file.isDirectory()); assertEquals("INCOMING.RPTBM025.D061704", file.getName()); } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile file = null; MVSFTPEntryParser parser = new MVSFTPEntryParser(); parser.setRegex(MVSFTPEntryParser.FILE_LIST_REGEX); parser.setType(MVSFTPEntryParser.FILE_LIST_TYPE); file = parser.parseFTPEntry("SAVE00 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.D061704"); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a file.", file.isFile()); assertEquals("INCOMING.RPTBM023.D061704", file.getName()); assertNull("Timestamp should not have been set.", file.getTimestamp()); parser.setType(MVSFTPEntryParser.MEMBER_LIST_TYPE); parser.setRegex(MVSFTPEntryParser.MEMBER_LIST_REGEX); file = parser.parseFTPEntry("SAVE03 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001"); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a file.", file.isFile()); assertEquals("SAVE03", file.getName()); assertNotNull("Timestamp should have been set.", file.getTimestamp()); file = parser.parseFTPEntry("SAVE04 "); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a file.", file.isFile()); assertEquals("SAVE04", file.getName()); assertNull("Timestamp should not have been set.", file.getTimestamp()); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/NTFTPEntryParserTest.java0000644000175000017500000002407411456020116031377 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.util.Calendar; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: NTFTPEntryParserTest.java 629276 2008-02-19 23:31:25Z rwinston $ */ public class NTFTPEntryParserTest extends CompositeFTPParseTestFramework { private static final String [][] goodsamples = { { // DOS-style tests "05-26-95 10:57AM 143712 $LDR$", "05-20-97 03:31PM 681 .bash_history", "12-05-96 05:03PM absoft2", "11-14-97 04:21PM 953 AUDITOR3.INI", "05-22-97 08:08AM 828 AUTOEXEC.BAK", "01-22-98 01:52PM 795 AUTOEXEC.BAT", "05-13-97 01:46PM 828 AUTOEXEC.DOS", "12-03-96 06:38AM 403 AUTOTOOL.LOG", "12-03-96 06:38AM 123xyz", "01-20-97 03:48PM bin", "05-26-1995 10:57AM 143712 $LDR$", // 24hr clock as used on Windows_CE "12-05-96 17:03 absoft2", "05-22-97 08:08 828 AUTOEXEC.BAK", "01-01-98 05:00 Network", "01-01-98 05:00 StorageCard", "09-13-10 20:08 Recycled", "09-06-06 19:00 69 desktop.ini", "09-13-10 13:08 23 Control Panel.lnk", "09-13-10 13:08 My Documents", "09-13-10 13:08 Program Files", "09-13-10 13:08 Temp", "09-13-10 13:08 Windows", }, { // Unix-style tests "-rw-r--r-- 1 root root 111325 Apr 27 2001 zxJDBC-2.0.1b1.tar.gz", "-rw-r--r-- 1 root root 190144 Apr 27 2001 zxJDBC-2.0.1b1.zip", "-rwxr-xr-x 2 500 500 166 Nov 2 2001 73131-testtes1.afp", "-rw-r--r-- 1 500 500 166 Nov 9 2001 73131-testtes1.AFP", "drwx------ 4 maxm Domain Users 512 Oct 2 10:59 .metadata", } }; private static final String[][] badsamples = { { // DOS-style tests "20-05-97 03:31PM 681 .bash_history", " 0 DIR 05-19-97 12:56 local", " 0 DIR 05-12-97 16:52 Maintenance Desktop", }, { // Unix-style tests "drwxr-xr-x 2 root 99 4096Feb 23 30:01 zzplayer", } }; private static final String directoryBeginningWithNumber = "12-03-96 06:38AM 123xyz"; /** * @see junit.framework.TestCase#TestCase(String) */ public NTFTPEntryParserTest (String name) { super(name); } /** * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getGoodListings() */ @Override protected String[][] getGoodListings() { return goodsamples; } /** * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getBadListings() */ @Override protected String[][] getBadListings() { return badsamples; } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new NTFTPEntryParser(), new UnixFTPEntryParser() }); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { FTPFile dir = getParser().parseFTPEntry("12-05-96 05:03PM absoft2"); assertNotNull("Could not parse entry.", dir); assertEquals("Thu Dec 05 17:03:00 1996", df.format(dir.getTimestamp().getTime())); assertTrue("Should have been a directory.", dir.isDirectory()); assertEquals("absoft2", dir.getName()); assertEquals(0, dir.getSize()); dir = getParser().parseFTPEntry("12-03-96 06:38AM 123456"); assertNotNull("Could not parse entry.", dir); assertTrue("Should have been a directory.", dir.isDirectory()); assertEquals("123456", dir.getName()); assertEquals(0, dir.getSize()); } public void testParseLeadingDigits() { FTPFile file = getParser().parseFTPEntry("05-22-97 12:08AM 5000000000 10 years and under"); assertNotNull("Could not parse entry", file); assertEquals("10 years and under", file.getName()); assertEquals(5000000000L, file.getSize()); Calendar timestamp = file.getTimestamp(); assertNotNull("Could not parse time",timestamp); assertEquals("Thu May 22 00:08:00 1997",df.format(timestamp.getTime())); FTPFile dir = getParser().parseFTPEntry("12-03-96 06:38PM 10 years and under"); assertNotNull("Could not parse entry", dir); assertEquals("10 years and under", dir.getName()); timestamp = dir.getTimestamp(); assertNotNull("Could not parse time",timestamp); assertEquals("Tue Dec 03 18:38:00 1996",df.format(timestamp.getTime())); } public void testNET339() { // TODO enable when NET-339 is fixed FTPFile file = getParser().parseFTPEntry("05-22-97 12:08 5000000000 10 years and under"); assertNotNull("Could not parse entry", file); assertEquals("10 years and under", file.getName()); assertEquals(5000000000L, file.getSize()); Calendar timestamp = file.getTimestamp(); assertNotNull("Could not parse time",timestamp); assertEquals("Thu May 22 12:08:00 1997",df.format(timestamp.getTime())); FTPFile dir = getParser().parseFTPEntry("12-03-96 06:38 10 years and under"); assertNotNull("Could not parse entry", dir); assertEquals("10 years and under", dir.getName()); timestamp = dir.getTimestamp(); assertNotNull("Could not parse time",timestamp); assertEquals("Tue Dec 03 06:38:00 1996",df.format(timestamp.getTime())); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile f = getParser().parseFTPEntry("05-22-97 12:08AM 5000000000 AUTOEXEC.BAK"); assertNotNull("Could not parse entry.", f); assertEquals("Thu May 22 00:08:00 1997", df.format(f.getTimestamp().getTime())); assertTrue("Should have been a file.", f.isFile()); assertEquals("AUTOEXEC.BAK", f.getName()); assertEquals(5000000000L, f.getSize()); // test an NT-unix style listing that does NOT have a leading zero // on the hour. f = getParser().parseFTPEntry( "-rw-rw-r-- 1 mqm mqm 17707 Mar 12 3:33 killmq.sh.log"); assertNotNull("Could not parse entry.", f); Calendar cal = Calendar.getInstance(); cal.setTime(f.getTimestamp().getTime()); assertEquals("hour", 3, cal.get(Calendar.HOUR)); assertTrue("Should have been a file.", f.isFile()); assertEquals(17707, f.getSize()); } @Override protected void doAdditionalGoodTests(String test, FTPFile f) { if (test.indexOf("") >= 0) { assertEquals("directory.type", FTPFile.DIRECTORY_TYPE, f.getType()); } } /** * test condition reported as bug 20259. * directory with name beginning with a numeric character * was not parsing correctly * * @throws Exception */ public void testDirectoryBeginningWithNumber() throws Exception { FTPFile f = getParser().parseFTPEntry(directoryBeginningWithNumber); assertEquals("name", "123xyz", f.getName()); } public void testDirectoryBeginningWithNumberFollowedBySpaces() throws Exception { FTPFile f = getParser().parseFTPEntry("12-03-96 06:38AM 123 xyz"); assertEquals("name", "123 xyz", f.getName()); f = getParser().parseFTPEntry("12-03-96 06:38AM 123 abc xyz"); assertNotNull(f); assertEquals("name", "123 abc xyz", f.getName()); } /** * Test that group names with embedded spaces can be handled correctly * */ public void testGroupNameWithSpaces() { FTPFile f = getParser().parseFTPEntry("drwx------ 4 maxm Domain Users 512 Oct 2 10:59 .metadata"); assertNotNull(f); assertEquals("maxm", f.getUser()); assertEquals("Domain Users", f.getGroup()); } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/CompositeFTPParseTestFramework.java0000644000175000017500000001053610776231260033500 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author MarioIvankovits * @version $Id: CompositeFTPParseTestFramework.java 155429 2005-02-26 13:13:04Z dirkv $ */ public abstract class CompositeFTPParseTestFramework extends FTPParseTestFramework { /** * @see junit.framework.TestCase#TestCase(String) */ public CompositeFTPParseTestFramework(String name) { super(name); } /** * @see FTPParseTestFramework#getGoodListing() */ @Override protected String[] getGoodListing() { return (getGoodListings()[0]); } /** * Method getBadListing. * Implementors must provide multiple listing that contains failures and * must force the composite parser to switch the FtpEntryParser * * @return String[] */ protected abstract String[][] getBadListings(); /** * Method getGoodListing. * Implementors must provide multiple listing that passes and * must force the composite parser to switch the FtpEntryParser * * @return String[] */ protected abstract String[][] getGoodListings(); /** * @see FTPParseTestFramework#getBadListing() */ @Override protected String[] getBadListing() { return (getBadListings()[0]); } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testGoodListing() */ public void testConsistentListing() throws Exception { String goodsamples[][] = getGoodListings(); for (int i = 0; i < goodsamples.length; i++) { FTPFileEntryParser parser = getParser(); for (int j = 0; j < goodsamples[i].length; j++) { String test = goodsamples[i][j]; FTPFile f = parser.parseFTPEntry(test); assertNotNull("Failed to parse " + test, f); doAdditionalGoodTests(test, f); } } } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testGoodListing() */ @Override public void testBadListing() throws Exception { String badsamples[][] = getBadListings(); for (int i = 0; i < badsamples.length; i++) { FTPFileEntryParser parser = getParser(); for (int j = 0; j < badsamples[i].length; j++) { String test = badsamples[i][j]; FTPFile f = parser.parseFTPEntry(test); assertNull("Should have Failed to parse " + test, nullFileOrNullDate(f)); doAdditionalBadTests(test, f); } } } // even though all these listings are good using one parser // or the other, this tests that a parser that has succeeded // on one format will fail if another format is substituted. public void testInconsistentListing() throws Exception { String goodsamples[][] = getGoodListings(); FTPFileEntryParser parser = getParser(); for (int i = 0; i < goodsamples.length; i++) { String test = goodsamples[i][0]; FTPFile f = parser.parseFTPEntry(test); switch (i) { case 0: assertNotNull("Failed to parse " + test, f); break; case 1: assertNull("Should have failed to parse " + test, f); break; } } } } commons-net-2.2/src/test/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParserTest.java0000644000175000017500000003220111347047772031532 0ustar twernertwerner/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.commons.net.ftp.parser; import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.apache.commons.net.ftp.FTPListParseEngine; /** * @author Steve Cohen * @author Stephane ESTE-GRACIAS * @version $Id: VMSFTPEntryParserTest.java 657169 2008-05-16 19:07:02Z sebb $ */ public class VMSFTPEntryParserTest extends FTPParseTestFramework { private static final String[] badsamples = { "1-JUN.LIS;2 9/9 JUN-2-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)", "1-JUN.LIS;2 a/9 2-JUN-98 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)", "DATA.DIR; 1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (,RWED,RWED,RE)", "120196.TXT;1 118/126 14-APR-1997 12:45:27 PM [GROUP,OWNER] (RWED,,RWED,RE)", "30CHARBAR.TXT;1 11/18 2-JUN-1998 08:38:42 [GROUP-1,OWNER] (RWED,RWED,RWED,RE)", "A.;2 18/18 1-JUL-1998 08:43:20 [GROUP,OWNER] (RWED2,RWED,RWED,RE)", "AA.;2 152/153 13-FED-1997 08:13:43 [GROUP,OWNER] (RWED,RWED,RWED,RE)", "Directory USER1:[TEMP]\r\n\r\n", "\r\nTotal 14 files" }; private static final String[] goodsamples = { "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", "1-JUN.LIS;3 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)", "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)", "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [TRANSLATED] (,RWED,RWED,RE)", "120196.TXT;1 118/126 14-APR-1997 12:45:27 [GROUP,OWNER] (RWED,,RWED,RE)", "30CHARBAR.TXT;1 11/18 2-JUN-1998 08:38:42 [GROUP,OWNER] (RWED,RWED,RWED,RE)", "A.;2 18/18 1-JUL-1998 08:43:20 [GROUP,OWNER] (RWED,RWED,RWED,RE)", "AA.;2 152/153 13-FEB-1997 08:13:43 [GROUP,OWNER] (RWED,RWED,RWED,RE)", "UCX$REXECD_STARTUP.LOG;1098\r\n 4/15 24-FEB-2003 13:17:24 [POSTWARE,LP] (RWED,RWED,RE,)", "UNARCHIVE.COM;1 2/15 7-JUL-1997 16:37:45 [POSTWARE,LP] (RWE,RWE,RWE,RE)", "UNXMERGE.COM;15 1/15 20-AUG-1996 13:59:50 [POSTWARE,LP] (RWE,RWE,RWE,RE)", "UNXTEMP.COM;7 1/15 15-AUG-1996 14:10:38 [POSTWARE,LP] (RWE,RWE,RWE,RE)", "UNZIP_AND_ATTACH_FILES.COM;12\r\n 14/15 24-JUL-2002 14:35:40 [TRANSLATED] (RWE,RWE,RWE,RE)", "UNZIP_AND_ATTACH_FILES.SAV;1\r\n 14/15 17-JAN-2002 11:13:53 [POSTWARE,LP] (RWE,RWED,RWE,RE)", "FREEWARE40.DIR;1 27/36 16-FEB-1999 10:01:46 [AP_HTTPD,APACHE$WWW (RWE,RWE,RE,RE)", "1-JUN.LIS;1 9/9 2-jun-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", }; private static final String fullListing = "Directory USER1:[TEMP]\r\n\r\n"+ "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)\r\n"+ "2-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)\r\n"+ "3-JUN.LIS;1 9/9 3-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)\r\n"+ "3-JUN.LIS;4 9/9 7-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)\r\n"+ "3-JUN.LIS;2 9/9 4-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)\r\n"+ "3-JUN.LIS;3 9/9 6-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,)\r\n"+ "\r\nTotal 6 files"; /** * @see junit.framework.TestCase#TestCase(String) */ public VMSFTPEntryParserTest(String name) { super(name); } /** * Test the parsing of the whole list. * @throws IOException */ public void testWholeListParse() throws IOException { VMSFTPEntryParser parser = new VMSFTPEntryParser(); parser.configure(null); FTPListParseEngine engine = new FTPListParseEngine(parser); engine.readServerList( new ByteArrayInputStream(fullListing.getBytes()), null); // use default encoding FTPFile[] files = engine.getFiles(); assertEquals(6, files.length); assertFileInListing(files, "2-JUN.LIS"); assertFileInListing(files, "3-JUN.LIS"); assertFileInListing(files, "1-JUN.LIS"); assertFileNotInListing(files, "1-JUN.LIS;1"); } /** * Test the parsing of the whole list. * @throws IOException */ public void testWholeListParseWithVersioning() throws IOException { VMSFTPEntryParser parser = new VMSVersioningFTPEntryParser(); parser.configure(null); FTPListParseEngine engine = new FTPListParseEngine(parser); engine.readServerList( new ByteArrayInputStream(fullListing.getBytes()), null); // use default encoding FTPFile[] files = engine.getFiles(); assertEquals(3, files.length); assertFileInListing(files, "1-JUN.LIS;1"); assertFileInListing(files, "2-JUN.LIS;1"); assertFileInListing(files, "3-JUN.LIS;4"); assertFileNotInListing(files, "3-JUN.LIS;1"); assertFileNotInListing(files, "3-JUN.LIS"); } public void assertFileInListing(FTPFile[] listing, String name) { for (int i = 0; i < listing.length; i++) { if (name.equals(listing[i].getName())) { return; } } fail("File " + name + " not found in supplied listing"); } public void assertFileNotInListing(FTPFile[] listing, String name) { for (int i = 0; i < listing.length; i++) { if (name.equals(listing[i].getName())) { fail("Unexpected File " + name + " found in supplied listing"); } } } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ @Override public void testParseFieldsOnDirectory() throws Exception { FTPFile dir = getParser().parseFTPEntry("DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)"); assertTrue("Should be a directory.", dir.isDirectory()); assertEquals("DATA.DIR", dir.getName()); assertEquals(512, dir.getSize()); assertEquals("Tue Jun 02 07:32:04 1998", df.format(dir.getTimestamp().getTime())); assertEquals("GROUP", dir.getGroup()); assertEquals("OWNER", dir.getUser()); checkPermisions(dir, 0775); dir = getParser().parseFTPEntry("DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [TRANSLATED] (RWED,RWED,,RE)"); assertTrue("Should be a directory.", dir.isDirectory()); assertEquals("DATA.DIR", dir.getName()); assertEquals(512, dir.getSize()); assertEquals("Tue Jun 02 07:32:04 1998", df.format(dir.getTimestamp().getTime())); assertEquals(null, dir.getGroup()); assertEquals("TRANSLATED", dir.getUser()); checkPermisions(dir, 0705); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ @Override public void testParseFieldsOnFile() throws Exception { FTPFile file = getParser().parseFTPEntry("1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RW,R)"); assertTrue("Should be a file.", file.isFile()); assertEquals("1-JUN.LIS", file.getName()); assertEquals(9 * 512, file.getSize()); assertEquals("Tue Jun 02 07:32:04 1998", df.format(file.getTimestamp().getTime())); assertEquals("GROUP", file.getGroup()); assertEquals("OWNER", file.getUser()); checkPermisions(file, 0764); file = getParser().parseFTPEntry("1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [TRANSLATED] (RWED,RD,,)"); assertTrue("Should be a file.", file.isFile()); assertEquals("1-JUN.LIS", file.getName()); assertEquals(9 * 512, file.getSize()); assertEquals("Tue Jun 02 07:32:04 1998", df.format(file.getTimestamp().getTime())); assertEquals(null, file.getGroup()); assertEquals("TRANSLATED", file.getUser()); checkPermisions(file, 0400); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ @Override protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ @Override protected String[] getGoodListing() { return (goodsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ @Override protected FTPFileEntryParser getParser() { ConfigurableFTPFileEntryParserImpl parser = new VMSFTPEntryParser(); parser.configure(null); return parser; } protected FTPFileEntryParser getVersioningParser() { ConfigurableFTPFileEntryParserImpl parser = new VMSVersioningFTPEntryParser(); parser.configure(null); return parser; } /** * Method checkPermisions. * Verify that the VMS parser does NOT set the permissions. * @param dir */ private void checkPermisions(FTPFile dir, int octalPerm) { int permMask = 1<<8; assertTrue("Owner should not have read permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION)); permMask >>= 1; assertTrue("Owner should not have write permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION)); permMask >>= 1; assertTrue("Owner should not have execute permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION)); permMask >>= 1; assertTrue("Group should not have read permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION)); permMask >>= 1; assertTrue("Group should not have write permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION)); permMask >>= 1; assertTrue("Group should not have execute permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)); permMask >>= 1; assertTrue("World should not have read permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION)); permMask >>= 1; assertTrue("World should not have write permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION)); permMask >>= 1; assertTrue("World should not have execute permission.", ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); } } commons-net-2.2/src/changes/0000755000175000017500000000000011617452470015760 5ustar twernertwernercommons-net-2.2/src/changes/changes.xml0000644000175000017500000010702211467354053020115 0ustar twernertwerner Changes Rory Winston FromNetASCIIInputStream can throw a NullPointerException FTPClient.remoteAppend(String filename) uses STOR instead of APPE Incorrect parsing of timestamp on Windows CE Fix parsing to allow for new-style DOS listing using 24hr clock rather than AM/PM ftp.FTPClient.initiateListParsing(String parserKey, String pathname) can call createFileEntryParser with null systemName. Fix this by adding getSystemType() which does not return null, and deprecating getSystemName(). Add support for FTPFileFilter filters. New classes FTPFileFilter, FTPFileFilters, new methods: FTPListParseEngine#getFiles(FTPFileFilter filter) FTPClient.listFiles(String pathname, FTPFileFilter filter) Optionally enable EPSV with IPv4; Only send EPRT with IPv6. Fix incorrect port used with EPRT. Allow activeMaxPort == activeMinPort in getActivePort() method. FromNetASCIIInputStream.read(byte[], int, int) may change length passed to superclass if not doing conversion Testcase to show WindowSizeOptionHandler is working OK The method VMSFTPEntryParser.parseFileList(InputStream listStream) should not be present. Partial fix - marked method as deprecated and to be removed Telnet EOR is "consumed" by TelnetInputStream when in BINARY transmission. Send notification to TelnetNotificationHandler. TelnetInoutStream#__read() bug in the __receiveState handling for the _STATE_IAC state. SocketClient should ensure input and output streams are closed FTP: initiateListParsing should not cache entryParser Improvement to isInRange method in SubnetUtil.SubnetInfo class FTPClient.listFiles() corrupts file name in certain circumstances Telnet spyStream NullPointerException Deprecated the following unused fields from org.apache.commons.net.ftp.FTPSClient: KEYSTORE_ALGORITHM, PROVIDER, STORE_TYPE, TRUSTSTORE_ALGORITHM Fix site reports Add support for setting external host ip/port range Add fix and testcase for DotTerminatedMessageReader Add support for IPv6 EPRT/EPSV Fix SubnetUtils for /32 subnets and add inclusive host count flag Fix NPE when listHiddenFiles was on UNIXFTPEntryParser didn't preserve trailing whitespace in files method SubnetUtils.SubnetInfo.isInRange(addr) returns incorrect result Method createServerSocket of FTPSSocketFactory never called and thus UseClientMode is incorrect in a secured ftp transfer using active mode. Fix inconsistent command list in FTPCommand DefaultFTPFileEntryParserFactory did not work with Netware FTP server returning "NETWARE TYPE: L8" FTP.getReplyStrings() returned array of null Strings UnixFTPEntryParser regex did not match some directory entries SubnetUtils.SubnetInfo.isInRange(...) returned incorrect values SubnetUtils.SubnetInfo.isInRange(...) behaviour not documented dev="rwinston" type="fix" SubnetUtils did not handle /31 and /32 CIDRs well UnixFTPEntryParser failed to parse entry in certain conditions FTPClient.listFiles() corrupted file name in certain circumstances Moved class "ThreadContainer" from Threader.java into its own source file FTPSClient should accept a pre-configured SSLContext SubnetUtils / SubNetInfo toString() implementations Improve NNTPClient handling of invalid articles Refactor examples package. Javadoc fixes, improvements, and refactoring. Apply MFMT patch Fix copying of reply lines collection Fix incorrect NNTP constant Restore socket state after CCC command Example code in FTPClient doesn't compile Fix inconsistent handling of socket read/write buffer size UnixFTPEntryParser fails to parse some entries One of the "connect" method in class org.apache.commons.net.SocketClient doesn't handle connection timeout properly Add null check in TelnetClient::disconnect(). Remove deprecated FTPFileIterator and FTPFileList classes. Add connection timeout functionality to SocketClient. Make the KeyManager and TrustManager settable (niklas@protocol7.com). Patch FTPSClient to set default SSLServerSocketFactory. Thanks niklas@protocol7.com Patch to prevent TFTPClient dropping last packet. Thanks palm@poplarware.com Change isConnected() method to delegate to underlying socket connection. FTPS (TLS and SSL) is now supported. Thanks to Jose Juan Montiel, Paul Ferraro, and Satoshi Ishigami. Commons::Net now uses Maven 2. The project.xml has been replaced with a pom.xml, and the source tree layout has been changed accordingly. Removed old ftp2 proposal directories. Commons::Net now uses JDK regex functionality, saving on an extra [oro] dependency. There are now no external dependencies required. Various syntactic issues (FindBugs issues, JDK 5.0 generics support) Applied Rob Hasselbaum's rhasselbaum -> alumni.ithaca.edu patch for PR 38688 fixing a TelnetInputStream hang. Exposed control connection of FTP class via _controlInput_ and _controlOutput_ protected member variables in response to PR 38309 reported by josejuan.montiel@gmail.com. Reverted PR 32859 patch to TFTPClient because it caused final packets to not be sent. Make FTPClient extend SocketClient instead of TelnetClient. From jhindsley@providerlink.com Adds an "e" symbolic link flag to the Unix FTP parser. From denisgaebler@netscape.net Allow hidden files to be listed. Thanks to mario@ops.co.at Remove reflective check for Socket::isConnected() (no longer needed) Added WindowSizeOptionHandler for TelnetClient. Thanks to yuvalkashtan@gmail.com Refactored *Client classes under net/ package into separate subpackages, and move PrintCommandListener out of the examples/ package. Added an ant target to the Maven build to generate an FTP-only jar file, for clients who wish to use only FTP-based functionality. Custom SocketFactory interface has been replaced with the JDK SocketFactory implementation. Added ServerSocketFactory instance to SocketClient. Removed redundant FTP.IMAGE_FILE_TYPE flag. Added heavily updated MVSFTPEntryParser from henrik.sorensen@balcab.ch Removed deprecated classes FTPFileListParser, FTPFileListParserImpl, and DefaultFTPFileListParser. Also removed associated deprecated methods from FTPClient. Added encoding to FingerClient. From Ulrich Mayring. Catch BindException in RCommandClient::connect(). Add encoding specifier to SMTPClient. Add setters for socket send/receive buffer size to SocketClient. Fix PASV specifiers that broke previously. From Chris Eagle. Catch NPE in FTP parser factory method. Don't bind a UDP socket to NTP protocol port. Better handling of user and group names with embedded spaces in FTP listings. Add configurable multiline parsing. Add fix for broken leap year date parsing. Add SubnetUtils class (suggested by Kenny McLeod) Add Unix-type handling for UNKNOWN Type: L8 syst() message systems. Allow FTPTimestampParserImpl to take a predefined Calendar instance representing current time. Replace Exception with IOException VMS file permission parsing TelnetInputStream swallows interruptedexception as IOException the data connection socket is not closed when an IOException occurred ParserInitializationException when connecting to a Unix FTP server: comparison string must be upper case FTPFileEntryParserImpl.preParse() doesn't remove unparsable entries at the end of the file list Applied patches for defect 37113. Code incompatible with jdk 1.3. Original patch submitted by Andrea Rombald Applied patches for defect 37522. updated project.xml to correct compatibility level. Fixed typo in method name. FTP.removeCommandListener() was missing the L. Problem reported by Per.Lindberger@linkon.se. Applied fix for PR 33942 and PR 31793. Original patch submitted by mario@ops.co.at TFTPClient was ignoring final ACK (PR 32859). Thanks to perttu.auramo@ekahau.com Applied fix for ACL parsing in the FTP client (PR 33972). Submitted by robertalasch@yahoo.com Added missing NTP/SNTP unit tests to the codebase. Applied fix for POP3Client returning empty reply strings (PR 34133). Thanks to sammy_c@lineone.net NTP port parameter was being ignored (PR 34219). Fixed by felix.eichhorn@3soft.de An FTP parser for MVS was added. Submitted by wnoto@openfinance.com Added functionality for extensible parsing of FTP responses, using a configurable format string. This should enable the FTP client to operate across many different locales and date formats. Applied patch for PR 31793. Thanks to mario@ops.co.at Added message threading functionality to the NNTP client. Added return code 521 to FTPReply.java - this should obviate the need for the Ant FTP task to manually declare it. Add explicit notify() in TelnetInputStream::read(), so available() returns an accurate value. Thanks to tpalkot@gmail.com. Added SNTP/NTP components into the Commons-Net codebase, courtesy of Jason Matthews. Added POP3 test suite, courtesy of Mike George mike.george@comcast.net. Applied fix for FTPClient returning null for certain timestamp formats (BUG #30737) Build.xml fixes - dont include example classes in redistributable .jar, remove test dependency from javadoc target, and exclude private members from generated javadoc. Fixed bug in TFTPClient::setMaxTimeout(), spotted by steve@widge.net Some changes to facilitate compilation under JDK 5.0 Return correct NNTP article count when high and low watermarks are 0. Spotted by jmordax@terra.es Remove trailing null byte in TFTP packets. Thanks to gerard.dens@alcatel.be Many javadoc fixes. Allow FTPClient to set transfer buffer size. Ensure consistent handling of encoding throughout FTPClient operations. Patch submitted by leif@tanukisoftware.com. Fix TelnetClient zombie thread issue Fixed regression from migration to new parsers. Most of the new parsers parsed the file size as an integer instead of a long. Changed all of them to set the size to long. This problem was detected by the reporter of: http://issues.apache.org/bugzilla/show_bug.cgi?id=30345 fixed bug in the way FTPClient.listFiles worked when a directory was not specified. Current directory was not being 'remembered'. This was most problematic in the dependent ftp task of Ant. fixed handling of certain unusual "special" file types in the Unix parser. changed code that rendered package uncompilable under JDK 1.2 Mario Ivankovits mario@ops.co.at added functionality supporting correct handling of the "dirstyle" attribute of NT and OS400 servers that allows them to mimic Unix ftp servers. and a bug fix affecting handling of sticky and suid bits on Unix FTP servers. Mario Ivankovits mario@ops.co.at added parser for OS400. Added a functional junit test testing list parsing against real servers and fix several bugs found through this test. Ted Wise ctwise@bellsouth.net provided a patch to add the XHDR extended NNTP command. Deprecated FTPFileListParser interface, DefaultFTPFileListParser class, and the FTPClient.listFiles methods that accepted an FTPFileListParser parameter. These deprecated classes and methods will be removed in version 2.0. Added org.apache.commons.net.parser.FTPFileEntryParserFactory interface and a default implementation: DefaultFTPFileEntryParserFactory. This addition facilitates the autodetection of which FTPFileEntryParser to use to generate listings. FTPClient.listFiles methods were added that implement autodetection. Rory Winston Rory.Winston@telewest.co.uk provided patches to add the following extended NNTP commands to NNTPClient: XOVER, AUTHINFO USER, AUTHINFO PASS, and LIST ACTIVE. Changed connection hooks for FTP, SMTP, POP3, and NNTP classes to force use of an 8-bit US-ASCII superset (ISO-8859-1) for protocol communication. This was necessary because InputStreamReader and OutputStreamWriter use the default client-side character set encoding. fasselin@ca.ibm.com reported failure of SMTP on OS/390 which has EBCDIC as the native character set. Applied variation of fix suggested by Matthieu Recouly matthieu.recouly@laposte.net so that UnixFTPEntryParser may handle listings of the form: "drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog" where the space between user name and group is omitted. Applied patch from Stephane Este-Gracias sestegra@free.fr that fixes the parsing of VMS listings by VMSFTPEntryParser.. If the buffer queue run full, the run() method sometimes hangs forever. Changed wait() to wait(100) as with other changes in TelnetInputStream. Fix submitted From: J. Matysiak ( j.matysiak@cenit.de ). FTP.smnt(String dir) was not passing on the dir to the SMNT command as an argument. Added a link to the FAQ currently hosted on the Apache Wiki. Changed package private NNTP._reader and NNTP._writer member variables to protected NNTP._reader_ and NNTP._writer_ variables as suggested by issue report 16995 to facilitate extending NNTPClient functionality in subclasses. Changed name of FTPClient.__openDataConnection() to FTPClient._openDataConnection_() to remain consistent with the convention in the code that protected members are of the form _foo_. At some point __openDataConnection() had been changed from private to protected. Added terminal option support to the telnet client with tests. From Bruno D'Avanzo ( b.davanzo@inwind.it ). New parsers merged with mainline with support for old list parsers. Added a migration document for moving from NetComponents to Commons/Net. Moved the ftp2 tree with tests to a proposal directory and setup a build for that code. This can grow in this area so users don't think it is production ready. Cleaned up license header on some source. Moved .io and .util to .net.io and .net.util in preparation for 1.0 release. Fixed typo in NNTP.removeProtocolCommandListener() method name. It was missing an L. From: joev@atg.com. Various site updates including this changes doc and publish date information. Patch for restarting FTP file transfers. The offset was not being sent immediately before the data transfer command on account. The bug was apparently introduced in NetComponents when it was decided to always send a PORT command before each data transfer to avoid socket reuse problems on Windows. From: Tapan Karecha ( tapan@india.hp.com ). Applied a fix for potential deadlock in TelnetInputStream by changing a wait() to a wait(100). From: Tapan Karecha ( tapan@india.hp.com ). FTP examples now use passive ftp connections. commons-net-2.2/src/changes/release-notes.vm0000644000175000017500000000663211416121546021073 0ustar twernertwerner## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you 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. Apache ${project.name} ${version} RELEASE NOTES ## Hack to improve layout: replace all pairs of spaces with a single new-line $release.description.replaceAll(" ", " ") #if ($release.getActions().size() == 0) No changes defined in this version. #else Changes in this version include: #if ($release.getActions('add').size() !=0) New features: #foreach($actionItem in $release.getActions('add')) ## Use replaceAll to fix up LF-only line ends on Windows. #set($action=$actionItem.getAction().replaceAll("\n"," ")) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o#if($!issue != "") $issue: #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end #if ($release.getActions('fix').size() !=0) Fixed Bugs: #foreach($actionItem in $release.getActions('fix')) ## Use replaceAll to fix up LF-only line ends on Windows. #set($action=$actionItem.getAction().replaceAll("\n"," ")) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o#if($!issue != "") $issue: #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end #if ($release.getActions('update').size() !=0) Changes: #foreach($actionItem in $release.getActions('update')) ## Use replaceAll to fix up LF-only line ends on Windows. #set($action=$actionItem.getAction().replaceAll("\n"," ")) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o#if($!issue != "") $issue: #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end #if ($release.getActions('remove').size() !=0) Removed: #foreach($actionItem in $release.getActions('remove')) ## Use replaceAll to fix up LF-only line ends on Windows. #set($action=$actionItem.getAction().replaceAll("\n"," ")) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o#if($!issue != "") $issue. #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end ## End of main loop #end For complete information on ${project.name}, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache ${project.name} website: ${project.url} commons-net-2.2/NOTICE.txt0000644000175000017500000000025511347701605015302 0ustar twernertwernerApache Commons Net Copyright 2001-2010 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/). commons-net-2.2/RELEASE-NOTES.txt0000644000175000017500000001112711470614641016267 0ustar twernertwerner Apache Commons Net 2.2 RELEASE NOTES This is primarily a maintenance release, but it also includes new features and enhancements. Users of version 2.0 are encouraged to upgrade to 2.2, as this release includes some important bug fixes. See the detailed list of changes below for full description of all bug fixes and enhancements. Changes in this version include: New features: o NET-338: ftp.FTPClient.initiateListParsing(String parserKey, String pathname) can call createFileEntryParser with null systemName. Fix this by adding getSystemType() which does not return null, and deprecating getSystemName(). o NET-244: Add support for FTPFileFilter filters. New classes FTPFileFilter, FTPFileFilters, new methods: FTPListParseEngine#getFiles(FTPFileFilter filter) FTPClient.listFiles(String pathname, FTPFileFilter filter) o NET-74: Testcase to show WindowSizeOptionHandler is working OK o NET-263: SubnetUtils / SubNetInfo toString() implementations o Javadoc fixes, improvements, and refactoring. Fixed Bugs: o NET-334: FromNetASCIIInputStream can throw a NullPointerException o NET-341: FTPClient.remoteAppend(String filename) uses STOR instead of APPE o NET-339: Incorrect parsing of timestamp on Windows CE Fix parsing to allow for new-style DOS listing using 24hr clock rather than AM/PM o NET-313: Optionally enable EPSV with IPv4; Only send EPRT with IPv6. Fix incorrect port used with EPRT. Allow activeMaxPort == activeMinPort in getActivePort() method. o NET-328: FromNetASCIIInputStream.read(byte[], int, int) may change length passed to superclass if not doing conversion o NET-330: The method VMSFTPEntryParser.parseFileList(InputStream listStream) should not be present. Partial fix - marked method as deprecated and to be removed o NET-180: Telnet EOR is "consumed" by TelnetInputStream when in BINARY transmission. Send notification to TelnetNotificationHandler. o NET-329: TelnetInoutStream#__read() bug in the __receiveState handling for the _STATE_IAC state. o NET-283: SocketClient should ensure input and output streams are closed o NET-302: FTP: initiateListParsing should not cache entryParser o NET-282: Improvement to isInRange method in SubnetUtil.SubnetInfo class o NET-266: FTPClient.listFiles() corrupts file name in certain circumstances o NET-264: Telnet spyStream NullPointerException o Fix site reports o NET-285: Add support for setting external host ip/port range o NET-290: Add fix and testcase for DotTerminatedMessageReader o NET-288: Add support for IPv6 EPRT/EPSV o NET-305: Fix SubnetUtils for /32 subnets and add inclusive host count flag o NET-300: Fix NPE when listHiddenFiles was on o NET-215: UNIXFTPEntryParser didn't preserve trailing whitespace in files o NET-236: method SubnetUtils.SubnetInfo.isInRange(addr) returns incorrect result o NET-242: Method createServerSocket of FTPSSocketFactory never called and thus UseClientMode is incorrect in a secured ftp transfer using active mode. o NET-248: Fix inconsistent command list in FTPCommand o NET-250: DefaultFTPFileEntryParserFactory did not work with Netware FTP server returning "NETWARE TYPE: L8" o NET-257: FTP.getReplyStrings() returned array of null Strings o NET-259: UnixFTPEntryParser regex did not match some directory entries o NET-260: SubnetUtils.SubnetInfo.isInRange(...) returned incorrect values o NET-265: UnixFTPEntryParser failed to parse entry in certain conditions o NET-266: FTPClient.listFiles() corrupted file name in certain circumstances o NET-256: FTPSClient should accept a pre-configured SSLContext o Improve NNTPClient handling of invalid articles o NET-245: Apply MFMT patch o NET-279: Fix copying of reply lines collection o NET-277: Fix incorrect NNTP constant o NET-274: Restore socket state after CCC command o NET-275: Example code in FTPClient doesn't compile o Fix inconsistent handling of socket read/write buffer size o NET-294: UnixFTPEntryParser fails to parse some entries Changes: o Deprecated the following unused fields from org.apache.commons.net.ftp.FTPSClient: KEYSTORE_ALGORITHM, PROVIDER, STORE_TYPE, TRUSTSTORE_ALGORITHM o NET-261: SubnetUtils.SubnetInfo.isInRange(...) behaviour not documented o NET-251: Moved class "ThreadContainer" from Threader.java into its own source file o Refactor examples package. For complete information on Commons Net, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons Net website: http://commons.apache.org/net/ commons-net-2.2/LICENSE.txt0000644000175000017500000002613610210072740015376 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. commons-net-2.2/doap_net.rdf0000644000175000017500000000435411354467470016061 0ustar twernertwerner Apache Jakarta Commons Net Java Apache Commons Net commons-net 2005-12-03 2.0 commons-net-2.2/pom.xml0000644000175000017500000003013011470614641015070 0ustar twernertwerner org.apache.commons commons-parent 17 4.0.0 commons-net commons-net 2.2 Commons Net A collection of network utilities and protocol implementations. http://commons.apache.org/net/ jira http://issues.apache.org/jira/browse/NET 2001 scm:svn:http://svn.apache.org/repos/asf/commons/proper/net/trunk scm:svn:https://svn.apache.org/repos/asf/commons/proper/net/trunk http://svn.apache.org/viewvc/commons/proper/net/trunk Jeffrey D. Brekke brekke Jeff.Brekke@qg.com Quad/Graphics, Inc. Steve Cohen scohen scohen@apache.org javactivity.org Bruno D'Avanzo brudav bruno.davanzo@hp.com Hewlett-Packard Daniel F. Savarese dfs dfs@apache.org <a href="http://www.savarese.com/">Savarese Software Research</a> Rory Winston rwinston rwinston@apache.org Rob Hasselbaum rhasselbaum@alumni.ithaca.edu Mario Ivankovits mario@ops.co.at Tapan Karecha tapan@india.hp.com Winston Ojeda Winston.Ojeda@qg.com Quad/Graphics, Inc. Ted Wise ctwise@bellsouth.net junit junit 4.8.2 test 1.5 1.5 net 2.2 RC3 (Requires Java 1.5 or later) 1.4.1 (Requires Java 1.3 or later) NET 12310487 org.apache.maven.plugins maven-compiler-plugin **/examples/**/*.java org.apache.maven.plugins maven-surefire-plugin **/*FunctionalTest.java **/*POP3*.java **/TestSetupParameters.java maven-assembly-plugin src/assembly/bin.xml src/assembly/src.xml gnu maven-antrun-plugin package run org.codehaus.mojo build-helper-maven-plugin 1.2 attach-artifacts package attach-artifact target/commons-net-ftp-${project.version}.jar jar ftp org.apache.maven.plugins maven-changes-plugin 2.3 %URL%/%ISSUE% src/changes ${basedir}/src/test/java **/*Test.java org.apache.maven.plugins maven-changes-plugin 2.3 %URL%/%ISSUE% src/changes changes-report jira-report org.codehaus.mojo findbugs-maven-plugin org.codehaus.mojo clirr-maven-plugin 2.2.2 2.0 info rc apache.website Apache Commons Release Candidate Staging Site ${commons.deployment.protocol}://people.apache.org/www/people.apache.org/builds/commons/${commons.componentid}/${commons.release.version}/${commons.rc.version}/site commons-net-2.2/README0000644000175000017500000000026410542533771014443 0ustar twernertwerner o Building To build, you must have Maven 2 installed. Maven can be downloaded from http://maven.apache.org/. o Documentation You can build the documentation with: mvn site