commons-net-1.4.1/ 40755 0 0 0 10344341135 11004 5ustar 0 0 commons-net-1.4.1/src/ 40755 0 0 0 10344341134 11572 5ustar 0 0 commons-net-1.4.1/src/java/ 40755 0 0 0 10344341134 12513 5ustar 0 0 commons-net-1.4.1/src/java/examples/ 40755 0 0 0 10344341135 14332 5ustar 0 0 commons-net-1.4.1/src/java/examples/nntp/ 40755 0 0 0 10344341135 15311 5ustar 0 0 commons-net-1.4.1/src/java/examples/ntp/ 40755 0 0 0 10344341135 15133 5ustar 0 0 commons-net-1.4.1/src/java/org/ 40755 0 0 0 10344341134 13302 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/ 40755 0 0 0 10344341134 14523 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/ 40755 0 0 0 10344341134 16176 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/ 40755 0 0 0 10344341135 16765 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/io/ 40755 0 0 0 10344341135 17374 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/bsd/ 40755 0 0 0 10344341134 17534 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/pop3/ 40755 0 0 0 10344341135 17646 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/telnet/ 40755 0 0 0 10344341135 20260 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/ftp/ 40755 0 0 0 10344341135 17556 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/ 40755 0 0 0 10344341134 21051 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/nntp/ 40755 0 0 0 10344341135 17744 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/tftp/ 40755 0 0 0 10344341135 17742 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/ntp/ 40755 0 0 0 10344341135 17566 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/util/ 40755 0 0 0 10344341134 17741 5ustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/smtp/ 40755 0 0 0 10344341135 17750 5ustar 0 0 commons-net-1.4.1/src/test/ 40755 0 0 0 10344341134 12551 5ustar 0 0 commons-net-1.4.1/src/test/org/ 40755 0 0 0 10344341134 13340 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/ 40755 0 0 0 10344341134 14561 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/ 40755 0 0 0 10344341134 16234 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/ 40755 0 0 0 10344341135 17023 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/telnet/ 40755 0 0 0 10344341135 20316 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/ftp/ 40755 0 0 0 10344341135 17614 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/ 40755 0 0 0 10344341135 21110 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/pop3/ 40755 0 0 0 10344341134 17703 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/time/ 40755 0 0 0 10344341134 17760 5ustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/ntp/ 40755 0 0 0 10344341135 17624 5ustar 0 0 commons-net-1.4.1/LICENSE.txt100644 0 0 26136 10344341134 12753 0ustar 0 0 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-1.4.1/maven.xml100644 0 0 10411 10344341134 12745 0ustar 0 0 commons-net-1.4.1/project.xml100644 0 0 14133 10344341134 13312 0ustar 0 0 3 Jakarta Commons Net commons-net 1.4.1 1997 Jakarta Commons Net /images/net-logo-white.png http://jakarta.apache.org/commons/${pom.artifactId.substring(8)}/ org.apache.commons.${pom.artifactId.substring(8)} The Apache Software Foundation http://jakarta.apache.org http://jakarta.apache.org/images/original-jakarta-logo.gif The Apache Software License, Version 2.0 /LICENSE.txt repo jakarta http://issues.apache.org/bugzilla/ jakarta.apache.org /www/jakarta.apache.org/commons/${pom.artifactId.substring(8)}/ /www/jakarta.apache.org/builds/jakarta-commons/${pom.artifactId.substring(8)}/ scm:svn:http://svn.apache.org/repos/asf/jakarta/commons/proper/${pom.artifactId.substring(8)}/trunk http://svn.apache.org/repos/asf/jakarta/commons/proper/${pom.artifactId.substring(8)}/trunk Commons Dev List commons-dev-subscribe@jakarta.apache.org commons-dev-unsubscribe@jakarta.apache.org http://mail-archives.apache.org/eyebrowse/SummarizeList?listName=commons-dev@jakarta.apache.org Commons User List commons-user-subscribe@jakarta.apache.org commons-user-unsubscribe@jakarta.apache.org http://mail-archives.apache.org/eyebrowse/SummarizeList?listName=commons-user@jakarta.apache.org 1.0.0 1.0.0 NET_1_0_0 1.1.0 1.1.0 NET_1_1_0 1.2.0 1.2.0 NET_1_2_0 1.2.1 1.2.1 NET_1_2_1 1.2.2 1.2.2 NET_1_2_2 1.3.0 1.3.0 NET_1_3_0 1.4.0 1.4.0 NET_1_4_0 1.4.1 1.4.1 NET_1_4_1 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 savarese.org Rory Winston rwinston rwinston@apache.org 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 oro 2.0.8 statcvs maven-statcvs-plugin 2.5 plugin commons-dev@jakarta.apache.org src/java ${basedir} META-INF NOTICE.txt src/test **/*Test.java **/*FunctionalTest.java **/*POP3*.java maven-changes-plugin maven-tasklist-plugin maven-statcvs-plugin maven-junit-report-plugin maven-jdepend-plugin maven-jcoverage-plugin maven-checkstyle-plugin maven-simian-plugin maven-javadoc-plugin maven-jxr-plugin maven-license-plugin commons-net-1.4.1/project.properties100644 0 0 2165 10344341134 14670 0ustar 0 0 # Copyright 2003-2005 The Apache Software Foundation # # 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. maven.checkstyle.javadoc.scope = protected maven.checkstyle.format = turbine maven.changelog.factory=org.apache.maven.svnlib.SvnChangeLogFactory maven.jar.excludes=**/examples/** maven.compile.target=1.2 # commons site L&F maven.xdoc.jsl=../commons-build/commons-site.jsl maven.xdoc.date=left maven.xdoc.version=${pom.currentVersion} maven.xdoc.developmentProcessUrl=http://jakarta.apache.org/commons/charter.html maven.xdoc.poweredby.image=maven-feather.png maven.javadoc.links=http://java.sun.com/j2se/1.3/docs/api/ commons-net-1.4.1/build.xml100644 0 0 13453 10344341134 12747 0ustar 0 0 ================================= WARNING ================================ Junit isn't present in your ${ANT_HOME}/lib directory. Tests not executed. ========================================================================== commons-net-1.4.1/src/java/examples/rshell.java100644 0 0 6022 10344341134 16562 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import org.apache.commons.net.bsd.RCommandClient; /*** * 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-1.4.1/src/java/examples/weatherTelnet.java100644 0 0 4064 10344341134 20110 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import org.apache.commons.net.telnet.TelnetClient; /*** * 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-1.4.1/src/java/examples/messages.java100644 0 0 7755 10344341134 17116 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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 messages { 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-1.4.1/src/java/examples/nntp/NNTPUtils.java100644 0 0 4657 10344341134 20064 0ustar 0 0 package examples.nntp; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; 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 Article[] getArticleInfo(NNTPClient client, int lowArticleNumber, int highArticleNumber) throws IOException { Reader reader = null; Article[] articles = null; 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(); articles = new Article[count]; int index = 0; while (st.hasMoreTokens()) { StringTokenizer stt = new StringTokenizer(st.nextToken(), "\t"); 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[index++] = article; } } 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; StringBuffer sb = null; BufferedReader bufReader = new BufferedReader(reader); sb = new StringBuffer(); 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-1.4.1/src/java/examples/nntp/ExtendedNNTPOps.java100644 0 0 5226 10344341134 21177 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples.nntp; import java.io.IOException; import java.io.PrintWriter; import org.apache.commons.net.nntp.Article; import org.apache.commons.net.nntp.NNTPClient; import org.apache.commons.net.nntp.NewsgroupInfo; import examples.PrintCommandListener; /** * 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); int lowArticleNumber = testGroup.getFirstArticle(); int highArticleNumber = lowArticleNumber + 100; Article[] articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber); for (int i = 0; i < articles.length; ++i) { System.out.println(articles[i].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-1.4.1/src/java/examples/nntp/MessageThreading.java100644 0 0 4341 10344341134 21464 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples.nntp; import java.io.IOException; import java.io.PrintWriter; import java.net.SocketException; 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; import examples.PrintCommandListener; 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); if(!client.authenticate(user, password)) { System.out.println("Authentication failed for user " + user + "!"); System.exit(1); } NewsgroupInfo group = new NewsgroupInfo(); client.selectNewsgroup("comp.lang.lisp", group); int lowArticleNumber = group.getFirstArticle(); int highArticleNumber = lowArticleNumber + 100; System.out.println("Retrieving articles between [" + lowArticleNumber + "] and [" + highArticleNumber + "]"); Article[] 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-1.4.1/src/java/examples/nntp/newsgroups.java100644 0 0 4524 10344341134 20471 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 newsgroups { 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-1.4.1/src/java/examples/nntp/post.java100644 0 0 11274 10344341135 17263 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.io.Util; import org.apache.commons.net.nntp.NNTPClient; import org.apache.commons.net.nntp.NNTPReply; import org.apache.commons.net.nntp.SimpleNNTPHeader; import examples.PrintCommandListener; /*** * 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 post { 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-1.4.1/src/java/examples/tftp.java100644 0 0 17720 10344341134 16275 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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 tftp { 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-1.4.1/src/java/examples/ftp.java100644 0 0 12435 10344341134 16107 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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.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 ftp { 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-1.4.1/src/java/examples/finger.java100644 0 0 10266 10344341134 16570 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import org.apache.commons.net.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-1.4.1/src/java/examples/fwhois.java100644 0 0 4447 10344341134 16601 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import org.apache.commons.net.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-1.4.1/src/java/examples/PrintCommandListener.java100644 0 0 2732 10344341134 21376 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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. *

***/ public class PrintCommandListener implements ProtocolCommandListener { private 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-1.4.1/src/java/examples/server2serverFTP.java100644 0 0 14517 10344341134 20512 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import java.io.PrintWriter; import java.net.InetAddress; 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 server2serverFTP { 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-1.4.1/src/java/examples/echo.java100644 0 0 12132 10344341134 16226 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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.EchoTCPClient; import org.apache.commons.net.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-1.4.1/src/java/examples/IOUtil.java100644 0 0 6206 10344341134 16442 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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-1.4.1/src/java/examples/mail.java100644 0 0 10441 10344341134 16233 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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.Enumeration; import java.util.Vector; 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 mail { public final static void main(String[] args) { String sender, recipient, subject, filename, server, cc; Vector ccList = new Vector(); 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.addElement(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); en = ccList.elements(); while (en.hasMoreElements()) client.addRecipient((String)en.nextElement()); 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-1.4.1/src/java/examples/chargen.java100644 0 0 10752 10344341134 16725 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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.CharGenTCPClient; import org.apache.commons.net.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-1.4.1/src/java/examples/ntp/NTPClient.java100644 0 0 16653 10344341135 17726 0ustar 0 0 package examples.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ 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(NtpV3Packet.NTP_PORT); 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-1.4.1/src/java/examples/ntp/TimeClient.java100644 0 0 5357 10344341135 20142 0ustar 0 0 package examples.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ import java.io.IOException; import java.net.InetAddress; import org.apache.commons.net.TimeTCPClient; import org.apache.commons.net.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-1.4.1/src/java/examples/TelnetClientExample.java100644 0 0 31565 10344341135 21232 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; 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-1.4.1/src/java/examples/daytime.java100644 0 0 5304 10344341135 16730 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import java.net.InetAddress; import org.apache.commons.net.DaytimeTCPClient; import org.apache.commons.net.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-1.4.1/src/java/examples/rlogin.java100644 0 0 6671 10344341135 16576 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import org.apache.commons.net.bsd.RLoginClient; /*** * 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-1.4.1/src/java/examples/rdate.java100644 0 0 5515 10344341135 16377 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import java.net.InetAddress; import org.apache.commons.net.TimeTCPClient; import org.apache.commons.net.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-1.4.1/src/java/examples/rexec.java100644 0 0 5475 10344341135 16413 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package examples; import java.io.IOException; import org.apache.commons.net.bsd.RExecClient; /*** * 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-1.4.1/src/java/org/apache/commons/net/io/DotTerminatedMessageWriter.java100644 0 0 14415 10344341134 25625 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ 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. ***/ 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. ***/ 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. ***/ 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. ***/ 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/io/CopyStreamException.java100644 0 0 4630 10344341134 24303 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z rwinston $ */ public class CopyStreamException extends IOException { private long totalBytesTransferred; private 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-1.4.1/src/java/org/apache/commons/net/io/SocketInputStream.java100644 0 0 4057 10344341134 23765 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 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. ***/ public void close() throws IOException { super.close(); __socket.close(); } } commons-net-1.4.1/src/java/org/apache/commons/net/io/ToNetASCIIInputStream.java100644 0 0 11550 10344341134 24353 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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'; } // else 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. ***/ 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. ***/ 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. ***/ public boolean markSupported() { return false; } public int available() throws IOException { int result; result = in.available(); if (__status == __LAST_WAS_NL) return (result + 1); return result; } } commons-net-1.4.1/src/java/org/apache/commons/net/io/Util.java100644 0 0 33237 10344341134 21300 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/io/CopyStreamEvent.java100644 0 0 6166 10344341134 23434 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z rwinston $ */ public class CopyStreamEvent extends EventObject { /** * Constant used to indicate the stream size is unknown. */ public static final long UNKNOWN_STREAM_SIZE = -1; private int bytesTransferred; private long totalBytesTransferred; private 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-1.4.1/src/java/org/apache/commons/net/io/CopyStreamAdapter.java100644 0 0 11213 10344341134 23740 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.io; import java.util.Enumeration; 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 165675 2005-05-02 20:09:55Z rwinston $ */ public class CopyStreamAdapter implements CopyStreamListener { private 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) { Enumeration listeners; CopyStreamEvent event; listeners = internalListeners.getListeners(); event = new CopyStreamEvent(this, totalBytesTransferred, bytesTransferred, streamSize); while (listeners.hasMoreElements()) { ((CopyStreamListener) (listeners.nextElement())). 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-1.4.1/src/java/org/apache/commons/net/io/CopyStreamListener.java100644 0 0 5764 10344341134 24143 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z 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-1.4.1/src/java/org/apache/commons/net/io/SocketOutputStream.java100644 0 0 5365 10344341134 24171 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 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. ***/ 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. ***/ public void close() throws IOException { super.close(); __socket.close(); } } commons-net-1.4.1/src/java/org/apache/commons/net/io/FromNetASCIIInputStream.java100644 0 0 14152 10344341134 24675 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ 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. ***/ public int read(byte buffer[], int offset, int length) throws IOException { int ch, off; if (length < 1) return 0; ch = available(); __length = (length > ch ? ch : length); // If nothing is available, block to read only one character if (__length < 1) __length = 1; if (_noConversionRequired) return super.read(buffer, offset, __length); 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 /*** * 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. ***/ public int available() throws IOException { return (buf.length - pos) + in.available(); } } commons-net-1.4.1/src/java/org/apache/commons/net/io/ToNetASCIIOutputStream.java100644 0 0 6475 10344341135 24547 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ 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. ***/ public synchronized void write(byte buffer[], int offset, int length) throws IOException { while (length-- > 0) write(buffer[offset++]); } } commons-net-1.4.1/src/java/org/apache/commons/net/io/FromNetASCIIOutputStream.java100644 0 0 11472 10344341135 25101 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ 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. ***/ 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. ***/ public synchronized void close() throws IOException { if (FromNetASCIIInputStream._noConversionRequired) { super.close(); return ; } if (__lastWasCR) out.write('\r'); super.close(); } } commons-net-1.4.1/src/java/org/apache/commons/net/io/DotTerminatedMessageReader.java100644 0 0 21321 10344341135 25546 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z rwinston $ */ public final class DotTerminatedMessageReader extends Reader { private static final String LS; private static final char[] LS_CHARS; static { LS = System.getProperty("line.separator"); LS_CHARS = LS.toCharArray(); } 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); 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. */ 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 { 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. */ 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. */ 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. */ 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. */ public void close() throws IOException { synchronized (lock) { if (internalReader == null) { return; } if (!eof) { while (read() != -1) { ; } } eof = true; atBeginning = false; pos = internalBuffer.length; internalReader = null; } } } commons-net-1.4.1/src/java/org/apache/commons/net/bsd/RLoginClient.java100644 0 0 12457 10344341134 23056 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/bsd/RCommandClient.java100644 0 0 40525 10344341134 23361 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 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. 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 = _socketFactory_.createServerSocket(localPort, 1, getLocalAddress()); } catch (SocketException e) { continue; } break; } if (localPort < MIN_CLIENT_PORT) 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 (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. ***/ 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. ***/ public void connect(String hostname, int port) throws SocketException, IOException { 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. ***/ 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. ***/ public void connect(String hostname, 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(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-1.4.1/src/java/org/apache/commons/net/bsd/RExecClient.java100644 0 0 24244 10344341134 22667 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.bsd; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import org.apache.commons.net.io.SocketInputStream; import org.apache.commons.net.SocketClient; import java.io.OutputStream; /*** * 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 = _socketFactory_.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) { StringBuffer buffer = new StringBuffer(); 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/pop3/POP3Reply.java100644 0 0 2032 10344341134 22337 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 int OK = 0; /*** The reply code indicating failure of an operation. ***/ public static int ERROR = 1; // Cannot be instantiated. private POP3Reply() {} } commons-net-1.4.1/src/java/org/apache/commons/net/pop3/POP3.java100644 0 0 26321 10344341134 21352 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.lang.StringBuffer; 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 . ***/ 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. ***/ 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; StringBuffer buffer = new StringBuffer(256); en = _replyLines.elements(); while (en.hasMoreElements()) { buffer.append((String)en.nextElement()); buffer.append(SocketClient.NETASCII_EOL); } return buffer.toString(); } } commons-net-1.4.1/src/java/org/apache/commons/net/pop3/POP3MessageInfo.java100644 0 0 5102 10344341134 23445 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 { 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-1.4.1/src/java/org/apache/commons/net/pop3/POP3Client.java100644 0 0 51353 10344341134 22514 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; StringBuffer buffer, digestBuffer; MessageDigest md5; if (getState() != AUTHORIZATION_STATE) return false; md5 = MessageDigest.getInstance("MD5"); timestamp += secret; digest = md5.digest(timestamp.getBytes()); digestBuffer = new StringBuffer(128); for (i = 0; i < digest.length; i++) digestBuffer.append(Integer.toHexString(digest[i] & 0xff)); buffer = new StringBuffer(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((String)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((String)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-1.4.1/src/java/org/apache/commons/net/pop3/POP3Command.java100644 0 0 4377 10344341135 22641 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/telnet/TelnetNotificationHandler.java100644 0 0 3660 10344341134 26324 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; /*** * 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); } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java100644 0 0 10055 10344341134 26344 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 String termType = null; /*** * 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 ***/ 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] = (int) termType.charAt(ii); } return response; } } return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

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

* @return always null (no response to subnegotiation) ***/ public int[] startSubnegotiationRemote() { return null; } } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/SuppressGAOptionHandler.java100644 0 0 5415 10344341134 25747 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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) ***/ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

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

* @return always null (no response to subnegotiation) ***/ public int[] startSubnegotiationRemote() { return null; } } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/TelnetClient.java100644 0 0 21445 10344341134 23637 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ public void disconnect() throws IOException { __input.close(); __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. *

* @throws InterruptedException * @throws IllegalArgumentException * @throws IOException *

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

* @return true if AYT received a response, false otherwise ***/ 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. *

* @throws InvalidTelnetOptionException *

* @param opthand - option handler to be registered. ***/ public void addOptionHandler(TelnetOptionHandler opthand) throws InvalidTelnetOptionException { super.addOptionHandler(opthand); } /* open TelnetOptionHandler functionality (end)*/ /*** * Unregisters a TelnetOptionHandler. *

* @throws InvalidTelnetOptionException *

* @param optcode - Code of the option to be unregistered. ***/ 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 ***/ public void registerNotifHandler(TelnetNotificationHandler notifhand) { super.registerNotifHandler(notifhand); } /*** * Unregisters the current notification handler. *

***/ 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-1.4.1/src/java/org/apache/commons/net/telnet/Telnet.java100644 0 0 106040 10344341134 22513 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 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 (Exception 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 (Exception 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 DO request. *

* @throws IOException - Exception in I/O. *

* @param option - option code to be set. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - option code to be set. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - option code to be set. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - option code to be set. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param suboption - subnegotiation data received * @param suboptionLength - length of data received ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param subn - subnegotiation data to be sent ***/ 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 (Exception e) { System.err.println("Exception notifying:" + e.getMessage()); } } } } /* Code Section added for supporting AYT (end)*/ /*** * Called upon connection. *

* @throws IOException - Exception in I/O. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param option - Option code. ***/ 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. *

* @throws IOException - Exception in I/O. *

* @param b - byte to send ***/ 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. *

* @throws IOException - Exception in I/O. * @throws IllegalArgumentException - Illegal argument * @throws InterruptedException - Interrupted during wait. *

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

* @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. *

* @throws InvalidTelnetOptionException - The option code is invalid. *

* @param opthand - option handler to be registered. ***/ 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. *

* @throws InvalidTelnetOptionException - The option code is invalid. *

* @param optcode - Code of the option to be unregistered. ***/ 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) { if (spyStream != null) { try { if (ch != (int) '\r') { spyStream.write(ch); if (ch == (int) '\n') { spyStream.write((int) '\r'); } spyStream.flush(); } } catch (Exception 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))) { if (spyStream != null) { try { spyStream.write(ch); spyStream.flush(); } catch (Exception 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-1.4.1/src/java/org/apache/commons/net/telnet/TelnetOutputStream.java100644 0 0 7551 10344341134 25057 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; import java.io.IOException; import java.io.OutputStream; /*** * *

* *

*

* @author Daniel F. Savarese ***/ final class TelnetOutputStream extends OutputStream { private TelnetClient __client; 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. ***/ 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. ***/ 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. ***/ public void write(byte buffer[], int offset, int length) throws IOException { synchronized (__client) { while (length-- > 0) write(buffer[offset++]); } } /*** Flushes the stream. ***/ public void flush() throws IOException { __client._flushOutputStream(); } /*** Closes the stream. ***/ public void close() throws IOException { __client._closeOutputStream(); } } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/InvalidTelnetOptionException.java100644 0 0 3037 10344341134 27034 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 int optionCode = -1; /*** * Error message ***/ private 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. ***/ public String getMessage() { return (msg + ": " + optionCode); } } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/TelnetInputStream.java100644 0 0 44564 10344341134 24703 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 { 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 int[] __queue; private TelnetClient __client; private Thread __thread; private IOException __ioException; /* TERMINAL-TYPE option (start)*/ private 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; // 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. private int __read() throws IOException { int ch; _loop: while (true) { // Exit only when we reach end of stream. if ((ch = super.read()) < 0) return -1; 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)*/ _mainSwitch: 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 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; default: break; } __receiveState = _STATE_DATA; continue; 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) { if(__threaded) { __queue.notify(); try { __queue.wait(); } catch (InterruptedException e) { throw e; } } } // 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; } } 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 -1 if at end of file if (__hasReachedEOF) return -1; // 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 IOException("Fatal thread interruption during read."); } } else { //__alreadyread = false; __readIsWaiting = true; int ch; do { try { if ((ch = __read()) < 0) if(ch != -2) return (ch); } catch (InterruptedIOException e) { synchronized (__queue) { __ioException = e; __queue.notifyAll(); try { __queue.wait(100); } catch (InterruptedException interrupted) { } } return (-1); } try { if(ch != -2) { __processChar(ch); } } catch (InterruptedException e) { if (__isClosed) return (-1); } } while (super.available() > 0); __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. ***/ 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. ***/ 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()) == -1) return -1; off = offset; do { buffer[offset++] = (byte)ch; } while (--length > 0 && (ch = read()) != -1); //__client._spyRead(buffer, off, offset - off); return (offset - off); } /*** Returns false. Mark is not supported. ***/ public boolean markSupported() { return false; } 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. 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()) < 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-1.4.1/src/java/org/apache/commons/net/telnet/TelnetCommand.java100644 0 0 10703 10344341135 23773 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/telnet/EchoOptionHandler.java100644 0 0 5360 10344341135 24571 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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) ***/ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

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

* @return always null (no response to subnegotiation) ***/ public int[] startSubnegotiationRemote() { return null; } } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/SimpleOptionHandler.java100644 0 0 5671 10344341135 25151 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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) ***/ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) { return null; } /*** * Implements the abstract method of TelnetOptionHandler. *

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

* @return always null (no response to subnegotiation) ***/ public int[] startSubnegotiationRemote() { return null; } } commons-net-1.4.1/src/java/org/apache/commons/net/telnet/TelnetOption.java100644 0 0 14123 10344341135 23665 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 int BINARY = 0; public static int ECHO = 1; public static int PREPARE_TO_RECONNECT = 2; public static int SUPPRESS_GO_AHEAD = 3; public static int APPROXIMATE_MESSAGE_SIZE = 4; public static int STATUS = 5; public static int TIMING_MARK = 6; public static int REMOTE_CONTROLLED_TRANSMISSION = 7; public static int NEGOTIATE_OUTPUT_LINE_WIDTH = 8; public static int NEGOTIATE_OUTPUT_PAGE_SIZE = 9; public static int NEGOTIATE_CARRIAGE_RETURN = 10; public static int NEGOTIATE_HORIZONTAL_TAB_STOP = 11; public static int NEGOTIATE_HORIZONTAL_TAB = 12; public static int NEGOTIATE_FORMFEED = 13; public static int NEGOTIATE_VERTICAL_TAB_STOP = 14; public static int NEGOTIATE_VERTICAL_TAB = 15; public static int NEGOTIATE_LINEFEED = 16; public static int EXTENDED_ASCII = 17; public static int FORCE_LOGOUT = 18; public static int BYTE_MACRO = 19; public static int DATA_ENTRY_TERMINAL = 20; public static int SUPDUP = 21; public static int SUPDUP_OUTPUT = 22; public static int SEND_LOCATION = 23; public static int TERMINAL_TYPE = 24; public static int END_OF_RECORD = 25; public static int TACACS_USER_IDENTIFICATION = 26; public static int OUTPUT_MARKING = 27; public static int TERMINAL_LOCATION_NUMBER = 28; public static int REGIME_3270 = 29; public static int X3_PAD = 30; public static int WINDOW_SIZE = 31; public static int TERMINAL_SPEED = 32; public static int REMOTE_FLOW_CONTROL = 33; public static int LINEMODE = 34; public static int X_DISPLAY_LOCATION = 35; public static int OLD_ENVIRONMENT_VARIABLES = 36; public static int AUTHENTICATION = 37; public static int ENCRYPTION = 38; public static int NEW_ENVIRONMENT_VARIABLES = 39; public static int EXTENDED_OPTIONS_LIST = 255; private static int __FIRST_OPTION = BINARY; private static 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-1.4.1/src/java/org/apache/commons/net/telnet/TelnetOptionHandler.java100644 0 0 17673 10344341135 25200 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/CharGenTCPClient.java100644 0 0 5721 10344341134 22746 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.InputStream; /*** * 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-1.4.1/src/java/org/apache/commons/net/ftp/FTPFile.java100644 0 0 24524 10344341134 21775 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. Because there is no standard representation for * file information on FTP servers, it may not always be possible to * extract all the information that can be represented by FTPFile, or * it may even be possible to extract more information. In cases where * more information can be extracted, you will want to subclass FTPFile * and implement your own {@link org.apache.commons.net.ftp.FTPFileListParser} * to extract the information. * However, most FTP servers return file information in a format that * can be completely parsed by * {@link org.apache.commons.net.ftp.DefaultFTPFileListParser} * and stored in FTPFile. *

*

* @author Daniel F. Savarese * @see FTPFileListParser * @see DefaultFTPFileListParser * @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. ***/ public String toString() { return _rawListing; } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/ParserInitializationException.java100644 0 0 3552 10344341134 30041 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java100644 0 0 22055 10344341134 25253 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 155429 2005-02-26 13:13:04Z dirkv $ * * @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*" + "(\\d+)/\\d+\\s*" +"(\\S+)\\s+(\\S+)\\s+" + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" + "\\([a-zA-Z]*,[a-zA-Z]*,[a-zA-Z]*,[a-zA-Z]*\\)"; /** * 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. ***/ public FTPFile[] parseFileList(InputStream listStream) throws IOException { FTPListParseEngine engine = new FTPListParseEngine(this); engine.readServerList(listStream); 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); try { f.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { return null; // this is a parsing failure too. } 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 //Since I don't need the persmissions on this file (RWED), I'll //leave that for further development. 'Cause it will be a bit //elaborate to do it right with VMSes World, Global and so forth. 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. */ public String readNextEntry(BufferedReader reader) throws IOException { String line = reader.readLine(); StringBuffer entry = new StringBuffer(); 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. */ 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-1.4.1/src/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java100644 0 0 11174 10344341134 25127 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 NT Systems. * * @author Winston Ojeda * @author Steve Cohen * @version $Id: NTFTPEntryParser.java 155429 2005-02-26 13:13:04Z dirkv $ * @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 /** * this is the regular expression used by this parser. */ private static final String REGEX = "(\\S+)\\s+(\\S+)\\s+" + "(

)?\\s*" + "([0-9]+)?\\s+" + "(\\S.*)"; /** * 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); } /** * 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) { return null; // this is a parsing failure too. } 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. */ public FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_NT, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParser.java100644 0 0 3255 10344341134 25510 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java100644 0 0 12750 10344341134 27573 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z rwinston $ * @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-1.4.1/src/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java100644 0 0 4750 10344341134 26777 0ustar 0 0 /* * Copyright 2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java100644 0 0 11141 10344341134 25203 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 155429 2005-02-26 13:13:04Z dirkv $ * @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) { return null; // this is a parsing failure too. } //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. */ protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_OS2, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java100644 0 0 11157 10344341134 27303 0ustar 0 0 /* * Copyright 2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPFileEntryParserImpl; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.MatchResult; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.PatternMatcher; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; /** * 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 PatternMatcher _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(); try { _matcher_ = new Perl5Matcher(); pattern = new Perl5Compiler().compile(regex); } catch (MalformedPatternException e) { throw new IllegalArgumentException ( "Unparseable regex supplied: " + 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; if (_matcher_.matches(s.trim(), this.pattern)) { this.result = _matcher_.getMatch(); } return null != this.result; } /** * Convenience method delegates to the internal MatchResult's groups() * method. * * @return the number of groups() in the internal MatchResult. */ public int getGroupCnt() { if (this.result == null) { return 0; } return this.result.groups(); } /** * 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() { StringBuffer b = new StringBuffer(); for (int i = 1; i <= this.result.groups(); i++) { b.append(i).append(") ").append(this.result.group(i)) .append(System.getProperty("line.separator")); } return b.toString(); } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java100644 0 0 10635 10344341134 25354 0ustar 0 0 /* * Copyright 2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 155429 2005-02-26 13:13:04Z dirkv $ */ 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) { return null; // this is a parsing failure too. } 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. */ protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_OS400, DEFAULT_DATE_FORMAT, null, null, null, null); } } ././@LongLink100644 0 0 145 10344341135 10251 Lustar 0 0 commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.javacommons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java100644 0 0 10107 10344341134 30623 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 FTPTimestampParser timestampParser; /** * Only constructor for this absract 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-1.4.1/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java100644 0 0 17544 10344341134 26360 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; /** * 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. * * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String) */ /* (non-Javadoc) * */ public Calendar parseTimestamp(String timestampStr) throws ParseException { Calendar now = Calendar.getInstance(); now.setTimeZone(this.getServerTimeZone()); Calendar working = Calendar.getInstance(); working.setTimeZone(this.getServerTimeZone()); ParsePosition pp = new ParsePosition(0); Date parsed = null; if (this.recentDateFormat != null) { 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 { 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()); } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java100644 0 0 17506 10344341134 30327 0ustar 0 0 /* * Copyright 2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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}
  • *
* @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) { Class parserClass = null; FTPFileEntryParser parser = null; try { parserClass = Class.forName(key); parser = (FTPFileEntryParser) parserClass.newInstance(); } catch (ClassNotFoundException e) { String ukey = null; if (null != key) { ukey = key.toUpperCase(); } 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) { parser = createOS400FTPEntryParser(); } else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0) { parser = createMVSEntryParser(); } else { throw new ParserInitializationException("Unknown parser type: " + key); } } catch (ClassCastException e) { throw new ParserInitializationException(parserClass.getName() + " does not implement the interface " + "org.apache.commons.net.ftp.FTPFileEntryParser.", 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 (FTPFileEntryParser) new UnixFTPEntryParser(); } public FTPFileEntryParser createVMSVersioningFTPEntryParser() { return (FTPFileEntryParser) new VMSVersioningFTPEntryParser(); } 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 (FTPFileEntryParser) 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-1.4.1/src/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java100644 0 0 23351 10344341134 25531 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 161712 2005-04-18 02:57:04Z scohen $ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { /** * months abbreviations looked for by this parser. Also used * to determine which month is matched by the parser */ private static final String DEFAULT_MONTHS = "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"; 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) */ private static final String REGEX = "([bcdlfmpSs-])" +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s+" + "(\\d+)\\s+" + "(\\S+)\\s+" + "(?:(\\S+)\\s+)?" + "(\\d+)\\s+" /* numeric or standard format date */ + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S+\\s+\\S+))\\s+" /* year (for non-recent standard format) or time (for numeric or recent standard format */ + "(\\d+(?::\\d+)?)\\s+" + "(\\S*)(\\s*.*)"; /** * 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) { return null; // this is a parsing failure too. } // bcdlfmpSs- switch (typeStr.charAt(0)) { case 'd': type = FTPFile.DIRECTORY_TYPE; break; case 'l': type = FTPFile.SYMBOLIC_LINK_TYPE; break; case 'b': case 'c': isDevice = true; // break; - fall through 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. */ protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_UNIX, DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null, null); } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java100644 0 0 14600 10344341134 27314 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.MatchResult; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; /** * 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 155429 2005-02-26 13:13:04Z dirkv $ * * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser { private Perl5Matcher _preparse_matcher_; private Pattern _preparse_pattern_; private static final String PRE_PARSE_REGEX = "(.*);([0-9]+)\\s*.*"; /** * Constructor for a VMSFTPEntryParser object. Sets the versioning member * to the supplied value. * * @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_ = new Perl5Compiler().compile(PRE_PARSE_REGEX); } catch (MalformedPatternException e) { throw new IllegalArgumentException ( "Unparseable regex supplied: " + PRE_PARSE_REGEX); } } private class NameVersion { String name; int versionNumber; NameVersion(String name, String vers) { this.name = name; this.versionNumber = Integer.parseInt(vers); } } /** * 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 */ public List preParse(List original) { original = super.preParse(original); HashMap existingEntries = new HashMap(); ListIterator iter = original.listIterator(); while (iter.hasNext()) { String entry = ((String)iter.next()).trim(); MatchResult result = null; if (_preparse_matcher_.matches(entry, _preparse_pattern_)) { result = _preparse_matcher_.getMatch(); String name = result.group(1); String version = result.group(2); NameVersion nv = new NameVersion(name, version); NameVersion existing = (NameVersion) existingEntries.get(name); if (null != existing) { if (nv.versionNumber < existing.versionNumber) { iter.remove(); // removal removes 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 = ((String)iter.previous()).trim(); MatchResult result = null; if (_preparse_matcher_.matches(entry, _preparse_pattern_)) { result = _preparse_matcher_.getMatch(); String name = result.group(1); String version = result.group(2); NameVersion nv = new NameVersion(name, version); NameVersion existing = (NameVersion) existingEntries.get(name); if (null != existing) { if (nv.versionNumber < existing.versionNumber) { iter.remove(); // removal removes from original list. } } } } return original; } protected boolean isVersioning() { return true; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java100644 0 0 10457 10344341134 25256 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; /** * Implementation of FTPFileEntryParser and FTPFileListParser for IBM MVS Systems. * * @author Jeff Nadler * @author William Noto * @version $Id$ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) */ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { /** * This is the regular expression used by this parser. */ private static final String REGEX = "(.*)\\s+([^\\s]+)\\s*"; /** * Although this parser is now ignoring dates, someone may someday * figure out a way to accomodate this and this appears to be the * format used. For now, it won't be used. * SMC 2005/04/08 */ static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd"; // 2001/11/09 // This is not at all the tightest possible regexp for MVS LIST // output, but I'm not a mainframe guru so I have little idea what the // range of valid values are. I just needed to get the filename (Dsname); // note that no other FTPFile fields can be filled in with the results of // a LIST on MVS. The 'Referred' date seems to be 'last accessed date' // and not 'last modified date' so I didn't bother parsing it. // // Of course it works perfectly as-is and it distinguishes header lines from // file results so that's the important thing. // // This parser should be used when SYST returns: // 'MVS is the operating system of this server. FTP Server is running on z/OS.' // // Also note that there is no concept of directories in MVS, just datasets, // which have names composed of four dot separated names of up to 8 chars. // As a result, FTPFile.FILE_TYPE is always used. -JN 6/2004 jnadlersrcginc // Sample LIST results from MVS: // //Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname //FPFS42 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.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 /** * The sole constructor for a MVSFTPEntryParser 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 MVSFTPEntryParser() { super(REGEX); } /** * Parses a line of an 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, 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 = null; if (matches(entry)) { f = new FTPFile(); String dataSetName = group(2); f.setType(FTPFile.FILE_TYPE); f.setName(dataSetName); return (f); } return null; } /* * @return */ protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_MVS, DEFAULT_DATE_FORMAT, null, null, null, null); } } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java100644 0 0 4527 10344341134 26762 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/ftp/FTP.java100644 0 0 171410 10344341134 21212 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; 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; import org.apache.commons.net.telnet.TelnetClient; /*** * FTP provides the basic the functionality necessary to implement your * own FTP client. It extends org.apache.commons.net.TelnetClient * simply because it saves the writing of extra code to handle the FTP * control connection which always remains open during an FTP session and * uses the Telnet protocol. Aggregation would require writing new * wrapper methods and wouldn't leverage the functionality already * present in org.apache.commons.net.SocketClient. *

* 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 * @see FTPClient * @see FTPConnectionClosedException * @see org.apache.commons.net.MalformedServerReplyException ***/ public class FTP extends TelnetClient { /*** 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 IMAGE_FILE_TYPE = 2; /*** * 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 = "ABILNTCFRPSBC"; private StringBuffer __commandBuffer; BufferedReader _controlInput; BufferedWriter _controlOutput; int _replyCode; Vector _replyLines; boolean _newReplyString; String _replyString; String _controlEncoding; /*** * 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() { setDefaultPort(DEFAULT_PORT); __commandBuffer = new StringBuffer(); _replyLines = new Vector(); _newReplyString = false; _replyString = null; _commandSupport_ = new ProtocolCommandSupport(this); _controlEncoding = DEFAULT_CONTROL_ENCODING; } private void __getReply() throws IOException { int length; _newReplyString = true; _replyLines.setSize(0); 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); 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.addElement(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.addElement(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 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. // line.startsWith(code))); } 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 protected void _connectAction_() throws IOException { super._connectAction_(); _controlInput = new BufferedReader(new InputStreamReader(getInputStream(), getControlEncoding())); _controlOutput = new BufferedWriter(new OutputStreamWriter(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. *

* @exception IOException If an error occurs while disconnecting. ***/ public void disconnect() throws IOException { super.disconnect(); _controlInput = null; _controlOutput = null; _replyLines.setSize(0); _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); 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 using reflection to be backward compatible. * The return value of this method is only meaningful in an java 1.4 environment. * * @param socket * @return true if connected or pre java 1.4 */ private boolean socketIsConnected(Socket socket) { if (socket == null) { return false; } try { Method isConnected = socket.getClass().getMethod("isConnected", null); return ((Boolean) isConnected.invoke(socket, null)).booleanValue(); } catch (NoSuchMethodException e) { return true; } catch (IllegalAccessException e) { return true; } catch (InvocationTargetException e) { return true; } } /*** * 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._commands[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() { String[] lines; lines = new String[_replyLines.size()]; _replyLines.copyInto(lines); return lines; } /*** * 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() { Enumeration en; StringBuffer buffer; if (!_newReplyString) return _replyString; buffer = new StringBuffer(256); en = _replyLines.elements(); while (en.hasMoreElements()) { buffer.append((String)en.nextElement()); 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; StringBuffer info = new StringBuffer(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 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 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 { StringBuffer arg = new StringBuffer(); 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 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); } /*** * 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); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPListParseEngine.java100644 0 0 25355 10344341134 24155 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; 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 155429 2005-02-26 13:13:04Z dirkv $ */ public class FTPListParseEngine { private List entries = new LinkedList(); private ListIterator _internalIterator = entries.listIterator(); FTPFileEntryParser parser = null; public FTPListParseEngine(FTPFileEntryParser parser) { this.parser = parser; } /** * 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. */ 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. */ 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 = (String) this._internalIterator.next(); FTPFile temp = this.parser.parseFTPEntry(entry); tmpResults.add(temp); count--; } return (FTPFile[]) tmpResults.toArray(new FTPFile[0]); } /** * 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 = (String) this._internalIterator.previous(); FTPFile temp = this.parser.parseFTPEntry(entry); tmpResults.add(0,temp); count--; } return (FTPFile[]) tmpResults.toArray(new FTPFile[0]); } /** * 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 { List tmpResults = new LinkedList(); Iterator iter = this.entries.iterator(); while (iter.hasNext()) { String entry = (String) iter.next(); FTPFile temp = this.parser.parseFTPEntry(entry); tmpResults.add(temp); } return (FTPFile[]) tmpResults.toArray(new FTPFile[0]); } /** * 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-1.4.1/src/java/org/apache/commons/net/ftp/FTPFileEntryParser.java100644 0 0 13155 10344341134 24172 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z rwinston $ * @see org.apache.commons.net.ftp.FTPFile * @see org.apache.commons.net.ftp.FTPClient#createFileList */ 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-1.4.1/src/java/org/apache/commons/net/ftp/FTPCommand.java100644 0 0 11531 10344341134 22466 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 ***/ 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; 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; // Cannot be instantiated private FTPCommand() {} 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" }; /** * 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-1.4.1/src/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java100644 0 0 11257 10344341134 25015 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; 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, FTPFileListParser { /** * The constructor for a FTPFileEntryParserImpl object. */ public FTPFileEntryParserImpl() { } /*** * 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 java.io.IOException If an I/O error occurs reading the listStream. ***/ public FTPFile[] parseFileList(InputStream listStream, String encoding) throws IOException { FTPFileList ffl = FTPFileList.create(listStream, this, encoding); return ffl.getFiles(); } /*** * 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 java.io.IOException If an I/O error occurs reading the listStream. * * @deprecated The version of this method which takes an encoding should be used. ***/ public FTPFile[] parseFileList(InputStream listStream) throws IOException { return parseFileList(listStream, null); } /** * 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 is a no-op. * * @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 = (String) it.next(); if (null == parseFTPEntry(entry)) { it.remove(); } else { break; } } return original; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPFileListParser.java100644 0 0 5723 10344341134 23766 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import java.io.IOException; import java.io.InputStream; /*** * FTPFileListParser defines the interface for parsing FTP file listings * and converting that information into an array of * {@link org.apache.commons.net.ftp.FTPFile} instances. * Sometimes you will want to parse unusual listing formats, in which * case you would create your own implementation of FTPFileListParser and * if necessary, subclass FTPFile. *

*

* @author Daniel F. Savarese * @see FTPFile * @see FTPClient#listFiles * @deprecated This interface is deprecated as of version 1.2 and will be * removed in version 2.0 -- use FTPFileEntryParser instead. ***/ public interface FTPFileListParser { /*** * 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. * @param encoding The encoding to use. * @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. ***/ FTPFile[] parseFileList(InputStream listStream, String encoding) throws IOException; /*** * 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. ***/ FTPFile[] parseFileList(InputStream listStream) throws IOException; } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/DefaultFTPFileListParser.java100644 0 0 3165 10344341134 25271 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import org.apache.commons.net.ftp.parser.UnixFTPEntryParser; /** * DefaultFTPFileListParser is the default implementation of * {@link org.apache.commons.net.ftp.FTPFileListParser} * used by {@link org.apache.commons.net.ftp.FTPClient} * to parse file listings. * Sometimes you will want to parse unusual listing formats, in which * case you would create your own implementation of FTPFileListParser and * if necessary, subclass FTPFile. *

* As of version 1.2, this class merely extends UnixFTPEntryParser. * It will be removed in version 2.0. *

* @author Daniel F. Savarese * @see FTPFileListParser * @see FTPFile * @see FTPClient#listFiles * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory * @deprecated This class is deprecated as of version 1.2 and will be * removed in version 2.0 -- use the autodetect mechanism in * DefaultFTPFileEntryParserFactory instead. */ public final class DefaultFTPFileListParser extends UnixFTPEntryParser { } commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPFileIterator.java100644 0 0 27131 10344341134 23504 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import java.util.List; /** * This class implements a bidirectional iterator over an FTPFileList. * Elements may be retrieved one at at time using the hasNext() - next() * syntax familiar from Java 2 collections. Alternatively, entries may * be receieved as an array of any requested number of entries or all of them. * * @author Steve Cohen * @version $Id: FTPFileIterator.java 165675 2005-05-02 20:09:55Z rwinston $ * @see org.apache.commons.net.ftp.FTPFileList * @see org.apache.commons.net.ftp.FTPFileEntryParser * @see org.apache.commons.net.ftp.FTPListParseEngine * @deprecated This class is deprecated as of version 1.2 and will be * removed in version 2.0 - use FTPFileParseEngine instead */ public class FTPFileIterator { /** * a vector of strings, each representing a possibly valid ftp file * entry */ private List rawlines; /** * the parser to which this iterator delegates its parsing duties */ private FTPFileEntryParser parser; /** * constant shorthand for the situation where the raw listing has not * yet been scanned */ private static final int UNINIT = -1; /** * constant shorthand for the situation where the raw listing has been * scanned and found to have no valid entry. */ private static final int DIREMPTY = -2; /** * this iterator's current position within rawlines. */ private int itemptr = 0; /** * number within rawlines of the first valid file entry. */ private int firstGoodEntry = UNINIT; /** * "Package-private" constructor. Only the FTPFileList can * create an iterator, using it's iterator() method. The list * will be iterated with the list's default parser. * * @param rawlist the FTPFileList to be iterated */ FTPFileIterator (FTPFileList rawlist) { this(rawlist, rawlist.getParser()); } /** * "Package-private" constructor. Only the FTPFileList can * create an iterator, using it's iterator() method. The list will be * iterated with a supplied parser * * @param rawlist the FTPFileList to be iterated * @param parser the system specific parser for raw FTP entries. */ FTPFileIterator (FTPFileList rawlist, FTPFileEntryParser parser) { this.rawlines = rawlist.getLines(); this.parser = parser; } /** * Delegates to this object's parser member the job of parsing an * entry. * * @param entry A string containing one entry, as determined by the * parser's getNextEntry() method. * * @return an FTPFile object representing this entry or null if it can't be * parsed as a file */ private FTPFile parseFTPEntry(String entry) { return this.parser.parseFTPEntry(entry); } /** * Skips over any introductory lines and stuff in the listing that does * not represent files, returning the line number of the first entry * that does represent a file. * * @return the line number within rawlines of the first good * entry in the array or DIREMPTY if there are no good entries. */ private int getFirstGoodEntry() { FTPFile entry = null; for (int iter = 0; iter < this.rawlines.size(); iter++) { String line = (String) this.rawlines.get(iter); entry = parseFTPEntry(line); if (null != entry) { return iter; } } return DIREMPTY; } /** * resets iterator to the beginning of the list. */ private void init() { this.itemptr = 0; this.firstGoodEntry = UNINIT; } /** * shorthand for an empty return value. */ private static final FTPFile[] EMPTY = new FTPFile[0]; /** * Returns a list of FTPFile objects for ALL files listed in the server's * LIST output. * * @return a list of FTPFile objects for ALL files listed in the server's * LIST output. */ public FTPFile[] getFiles() { if (this.itemptr != DIREMPTY) { init(); } return getNext(0); } /** * Returns an array of at most quantityRequested FTPFile * objects starting at this iterator's current position within its * associated list. 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 the current position is advanced by * either quantityRequested or the number of entries * available after the iterator, whichever is fewer. * * @param quantityRequested * the maximum number of entries we want to get. A 0 * passed here is a signal to get ALL the entries. * * @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. */ public FTPFile[] getNext(int quantityRequested) { // if we haven't gotten past the initial junk do so. if (this.firstGoodEntry == UNINIT) { this.firstGoodEntry = getFirstGoodEntry(); } if (this.firstGoodEntry == DIREMPTY) { return EMPTY; } int max = this.rawlines.size() - this.firstGoodEntry; // now that we know the maximum we can possibly get, // resolve a 0 request to ask for that many. int howMany = (quantityRequested == 0) ? max : quantityRequested; howMany = (howMany + this.itemptr < this.rawlines.size()) ? howMany : this.rawlines.size() - this.itemptr; FTPFile[] output = new FTPFile[howMany]; for (int i = 0, e = this.firstGoodEntry + this.itemptr ; i < howMany; i++, e++) { output[i] = parseFTPEntry((String) this.rawlines.get(e)); this.itemptr++; } return output; } /** * Method for determining whether getNext() will successfully return a * non-null value. * * @return true if there exist any files after the one currently pointed * to by the internal iterator, false otherwise. */ public boolean hasNext() { int fge = this.firstGoodEntry; if (fge == DIREMPTY) { //directory previously found empty - return false return false; } else if (fge < 0) { // we haven't scanned the list yet so do it first fge = getFirstGoodEntry(); } return fge + this.itemptr < this.rawlines.size(); } /** * Returns a single parsed FTPFile object corresponding to the raw input * line at this iterator's current position. * * After this method is called the internal iterator is advanced by one * element (unless already at end of list). * * @return a single FTPFile object corresponding to the raw input line * at the position of the internal iterator over the list of raw input * lines maintained by this object or null if no such object exists. */ public FTPFile next() { FTPFile[] file = getNext(1); if (file.length > 0) { return file[0]; } else { return null; } } /** * Returns an array of at most quantityRequested FTPFile * objects starting at the position preceding this iterator's current * position within its associated list. If fewer than * quantityRequested such elements are available, the * returned array will have a length equal to the number of entries after * the iterator. If no such entries are found, this array will have a * length of 0. The entries will be ordered in the same order as the * list, not reversed. * * After this method is called the current position is moved back by * either quantityRequested or the number of entries * available before the current position, whichever is fewer. * @param quantityRequested the maximum number of entries we want to get. * A 0 passed here is a signal to get ALL the entries. * @return an array of at most quantityRequested FTPFile * objects starting at the position preceding the current position of * this iterator within its list and at least the number of elements which * exist in the list prior to its current position. */ public FTPFile[] getPrevious(int quantityRequested) { int howMany = quantityRequested; // can't retreat further than we've previously advanced if (howMany > this.itemptr) { howMany = this.itemptr; } FTPFile[] output = new FTPFile[howMany]; for (int i = howMany, e = this.firstGoodEntry + this.itemptr; i > 0;) { output[--i] = parseFTPEntry((String) this.rawlines.get(--e)); this.itemptr--; } return output; } /** * Method for determining whether getPrevious() will successfully return a * non-null value. * * @return true if there exist any files before the one currently pointed * to by the internal iterator, false otherwise. */ public boolean hasPrevious() { int fge = this.firstGoodEntry; if (fge == DIREMPTY) { //directory previously found empty - return false return false; } else if (fge < 0) { // we haven't scanned the list yet so do it first fge = getFirstGoodEntry(); } return this.itemptr > fge; } /** * Returns a single parsed FTPFile object corresponding to the raw input * line at the position preceding that of the internal iterator over * the list of raw lines maintained by this object * * After this method is called the internal iterator is retreated by one * element (unless it is already at beginning of list). * @return a single FTPFile object corresponding to the raw input line * at the position immediately preceding that of the internal iterator * over the list of raw input lines maintained by this object. */ public FTPFile previous() { FTPFile[] file = getPrevious(1); if (file.length > 0) { return file[0]; } else { return null; } } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPReply.java100644 0 0 20341 10344341134 22202 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 ***/ 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; 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; 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; // 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-1.4.1/src/java/org/apache/commons/net/ftp/Configurable.java100644 0 0 2257 10344341134 23123 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 * @return the object being configured after the configuration * @throws IllegalArgumentException if the elements of the * config are somehow inadequate to configure the * Configurable object. */ public void configure( FTPClientConfig config); }commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPClientConfig.java100644 0 0 46136 10344341135 23466 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 MVS-based ftp server is known throughout * the commons-net ftp system. */ public static final String SYST_MVS = "MVS"; private final String serverSystemKey; private String defaultDateFormatStr = null; private String recentDateFormatStr = null; 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 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; } /** *

* 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 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 jakarta-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-1.4.1/src/java/org/apache/commons/net/ftp/FTPClient.java100644 0 0 351402 10344341135 22353 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Vector; 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.IMAGE_FILE_TYPE (which is the same as * FTP.BINARY_FILE_TYPE ). Because there are at lest 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 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 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 * 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. *

* 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=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=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=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}. *

* NOTE: If you experience problems with unwanted firing of

setSoTimeout()
* during periods of client inactivity, this can be alleviated by calling
setReaderThread(false)
. * For more details, see this thread. *

*

* @author Daniel F. Savarese * @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 int __fileType, __fileFormat, __fileStructure, __fileTransferMode; private boolean __remoteVerificationEnabled; private long __restartOffset; private FTPFileEntryParserFactory __parserFactory; private int __bufferSize; // __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; private FTPClientConfig __configuration; /*** * 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; } private void __initDefaults() { __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE; __passiveHost = null; __passivePort = -1; __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; __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 { int i, index, lastIndex; String octet1, octet2; StringBuffer host; reply = reply.substring(reply.indexOf('(') + 1, reply.indexOf(')')).trim(); host = new StringBuffer(24); lastIndex = 0; index = reply.indexOf(','); host.append(reply.substring(lastIndex, index)); for (i = 0; i < 3; i++) { host.append('.'); lastIndex = index + 1; index = reply.indexOf(',', lastIndex); host.append(reply.substring(lastIndex, index)); } lastIndex = index + 1; index = reply.indexOf(',', lastIndex); octet1 = reply.substring(lastIndex, index); octet2 = reply.substring(index + 1); // index and lastIndex now used as temporaries try { index = Integer.parseInt(octet1); lastIndex = Integer.parseInt(octet2); } catch (NumberFormatException e) { throw new MalformedServerReplyException( "Could not parse passive host information.\nServer Reply: " + reply); } index <<= 8; index |= lastIndex; __passiveHost = host.toString(); __passivePort = index; } 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; if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE) { ServerSocket server; server = _socketFactory_.createServerSocket(0, 1, getLocalAddress()); if (!FTPReply.isPositiveCompletion(port(getLocalAddress(), 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); socket = server.accept(); server.close(); } else { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) return null; __parsePassiveModeReply((String)_replyLines.elementAt(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; } 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. ***/ 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 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() } ***/ 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((String)_replyLines.elementAt(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; } /*** * Sets the file type to be transferred. This should be one of * FTP.ASCII_FILE_TYPE , FTP.IMAGE_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. *

* @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.IMAGE_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. *

* @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(stor(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. *

* @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. *

* @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)); } /** * 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((String)_replyLines.elementAt(0)); } /** * 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. ***/ 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 = ((String)_replyLines.elementAt(0)).substring(4); 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; Vector results; if ((socket = _openDataConnection_(FTPCommand.NLST, pathname)) == null) return null; reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding())); results = new Vector(); while ((line = reader.readLine()) != null) results.addElement(line); reader.close(); socket.close(); if (completePendingCommand()) { String[] result; result = new String[results.size()]; results.copyInto(result); return result; } 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 supplied parserKey, obtain a list * of file information for the current working directory or for just a * single file. *

* If key is null, this object will try to autodetect * the system-type/parser-type by calling the SYST command. *

* Under the DefaultFTPFileEntryParserFactory, which is used unless a * different factory has been specified, the key * can be either a recognized System type for which a parser has been * defined, or the fully qualified class name of a class that implements * org.apache.commons.net.ftp.FTPFileEntryParser. *

* This information is obtained through the LIST command. The contents of * the returned array is determined by the FTPFileEntryParser * used. *

* @param parserKey This is a "handle" which the parser factory used * must be able to resolve into a class implementing * FTPFileEntryParser. *

* In the DefaultFTPFileEntryParserFactory, this * may either be a specific key identifying a server type, * which is used to identify a parser type, * or the fully qualified class name of the parser. See * DefaultFTPFileEntryParserFactory.createFileEntryParser * for full details. *

* If this parameter is null, will attempt to generate a key * by running the SYST command. This should cause no problem * with the functionality implemented in the * DefaultFTPFileEntryParserFactory, but may not map so well * to an alternative user-created factory. If that is the * case, calling this routine with a null parameter and a * custom parser factory may not be advisable. *

* @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 parser represented by the * parserKey parameter. *

* 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 * @deprecated use {@link #listFiles() listFiles()} or * {@link #listFiles(String) listFiles(String)} instead and specify the * parser Key in an {@link #FTPClientConfig FTPClientConfig} object instead. */ public FTPFile[] listFiles(String parserKey, String pathname) throws IOException { FTPListParseEngine engine = initiateListParsing(parserKey, pathname); return engine.getFiles(); } /** * 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); } /** * 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) { if (null != parserKey) { // if a parser key was supplied in the parameters, // use that to create the paraser __entryParser = __parserFactory.createFileEntryParser(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); } 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. __entryParser = __parserFactory.createFileEntryParser(getSystemName()); } } } 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, pathname)) == null) { return engine; } engine.readServerList(socket.getInputStream(), getControlEncoding()); socket.close(); completePendingCommand(); return engine; } /*** * 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; } /** * Using a programmer specified FTPFileListParser , obtain a * list of file information for a directory or information for * just a single file. This information is obtained through the LIST * command. The contents of the returned array is determined by the * FTPFileListParser 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. *

* @param parser The FTPFileListParser that should be * used to parse the server file listing. * @param pathname The file or directory to list. * @return The list of file information contained in the given path in * the format determined by the parser parameter. *

* 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. * * @return The list of file information contained in the given path in * the format determined by parserKey parameter. *

* 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 * @since 5 Jan 2004 * @deprecated use listFiles(String parserKey, String pathname) instead */ public FTPFile[] listFiles(FTPFileListParser parser, String pathname) throws IOException { Socket socket; FTPFile[] results; if ((socket = _openDataConnection_(FTPCommand.LIST, pathname)) == null) return new FTPFile[0]; results = parser.parseFileList(socket.getInputStream(), getControlEncoding()); socket.close(); completePendingCommand(); return results; } /** * Using a programmer specified FTPFileListParser , * obtain a list of file information for the current working directory. * This information is obtained through the LIST command. * The contents of the array returned is determined by the * FTPFileListParser used. *

* * @param parser The FTPFileListParser that should be * used to parse the server file listing. * * @return The list of file information contained in the given path in * the format determined by the parser parameter. *

* 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 IOException * @since 5 Jan 2004 * @deprecated use listFiles(String parserKey) instead. */ public FTPFile[] listFiles(FTPFileListParser parser) throws IOException { return listFiles(parser, null); } /** * Using a programmer specified FTPFileEntryParser , * initialize an object containing a raw file information for the * current working 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 parser The FTPFileEntryParser that should be * used to parse each server file listing. * * @return An iteratable 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. *

     *    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.
     *    }
     * 
* * @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 initiateListParsing(FTPFileEntryParser) method instead. * @see FTPFileList */ public FTPFileList createFileList(FTPFileEntryParser parser) throws IOException { return createFileList(null, parser); } /** * Using a programmer specified FTPFileEntryParser , * initialize an object containing a raw file information for a directory * or information for a single file. 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. *

* @param parser The FTPFileEntryParser that should be * used to parse each server file listing. * @param pathname The file or directory to list. * @return An iteratable 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 supplied path 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. * @deprecated - use initiateListParsing(String, FTPFileEntryParser) * method instead. * @see FTPFileList */ public FTPFileList createFileList(String pathname, FTPFileEntryParser parser) throws IOException { Socket socket; if ((socket = _openDataConnection_(FTPCommand.LIST, pathname)) == null) { return null; } FTPFileList list = FTPFileList.create(socket.getInputStream(), parser); socket.close(); completePendingCommand(); return list; } /** * 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; } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPFileListParserImpl.java100644 0 0 4426 10344341135 24610 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import org.apache.commons.net.ftp.parser.RegexFTPFileEntryParserImpl; /** * 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. * * @author Steve Cohen * @see org.apache.commons.net.ftp.parser.RegexFTPFileEntryParserImpl * @deprecated This class is deprecated as of version 1.2 and will be * removed in version 2.0 -- * org.apache.commons.net.ftp.RegexFTPFileEntryParserImpl is its * designated replacement. Class has been renamed, entire * implemenation is in RegexFTPFileEntryParserImpl. * */ public abstract class FTPFileListParserImpl extends RegexFTPFileEntryParserImpl { /** * The constructor for a FTPFileListParserImpl 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 FTPFileListParserImpl(String regex) { super(regex); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPFileList.java100644 0 0 17742 10344341135 22636 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.List; /** * This class encapsulates a listing of files from an FTP server. It is * initialized with an input stream which is read and the input split into * lines, each of which (after some possible initial verbiage) represents * a file on the FTP server. A parser is also supplied, which is used to * iterate through the internal list of lines parsing each into an FTPFile * object which is returned to the caller of the iteration methods. This * parser may be replaced with another, allowing the same list to be parsed * with different parsers. * Parsing takes place on an as-needed basis, basically, the first time a * position is iterated over. This happens at the time of iteration, not * prior to it as the older (FTPClient.listFiles() methods did, * which required a bigger memory hit. * * @author Steve Cohen * @version $Id: FTPFileList.java 165675 2005-05-02 20:09:55Z rwinston $ * @see org.apache.commons.net.ftp.FTPClient#createFileList * @see org.apache.commons.net.ftp.FTPFileIterator * @see org.apache.commons.net.ftp.FTPFileEntryParser * @see org.apache.commons.net.ftp.FTPListParseEngine * @deprecated This class is deprecated as of version 1.2 and will be * removed in version 2.0 -- use FTPFileParseEngine instead. */ public class FTPFileList { /** * storage for the raw lines of input read from the FTP server */ private LinkedList lines = null; /** * the FTPFileEntryParser assigned to be used with this lister */ private FTPFileEntryParser parser; /** * private status code for an empty directory */ private static final int EMPTY_DIR = -2; /** * The only constructor for FTPFileList, private because * construction only invoked at create() * * @param parser a FTPFileEntryParser value that knows * how to parse the entries returned by a particular FTP site. * @param encoding The encoding to use. */ private FTPFileList (FTPFileEntryParser parser, String encoding) { this.parser = parser; this.lines = new LinkedList(); } /** * The only way to create an FTPFileList object. Invokes * the private constructor and then reads the stream supplied stream to * build the intermediate array of "lines" which will later be parsed * into FTPFile object. * * @param stream The input stream created by reading the socket on which * the output of the LIST command was returned * @param parser the default FTPFileEntryParser to be used * by this object. This may later be changed using the init() method. * @param encoding The encoding to use * * @return the FTPFileList created, with an initialized * of unparsed lines of output. Will be null if the listing cannot * be read from the stream. * @exception IOException * Thrown on any failure to read from the socket. */ public static FTPFileList create(InputStream stream, FTPFileEntryParser parser, String encoding) throws IOException { FTPFileList list = new FTPFileList(parser, encoding); list.readStream(stream, encoding); parser.preParse(list.lines); return list; } /** * The only way to create an FTPFileList object. Invokes * the private constructor and then reads the stream supplied stream to * build the intermediate array of "lines" which will later be parsed * into FTPFile object. * * @param stream The input stream created by reading the socket on which * the output of the LIST command was returned * @param parser the default FTPFileEntryParser to be used * by this object. This may later be changed using the init() method. * * @return the FTPFileList created, with an initialized * of unparsed lines of output. Will be null if the listing cannot * be read from the stream. * @exception IOException * Thrown on any failure to read from the socket. * * @deprecated The version of this method which takes an encoding should be used. */ public static FTPFileList create(InputStream stream, FTPFileEntryParser parser) throws IOException { return create(stream, parser, null); } /** * internal method for reading the input into the lines vector. * * @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 */ public void readStream(InputStream stream, String encoding) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(stream, encoding)); String line = this.parser.readNextEntry(reader); while (line != null) { this.lines.add(line); line = this.parser.readNextEntry(reader); } reader.close(); } /** * internal method for reading the input into the lines vector. * * @param stream The socket stream on which the input will be read. * * @exception IOException thrown on any failure to read the stream * * @deprecated The version of this method which takes an encoding should be used. */ public void readStream(InputStream stream) throws IOException { readStream(stream, null); } /** * Accessor for this object's default parser. * * @return this object's default parser. */ FTPFileEntryParser getParser() { return this.parser; } /** * Package private accessor for the collection of raw input lines. * * @return vector containing all the raw input lines returned from the FTP * server */ List getLines() { return this.lines; } /** * create an iterator over this list using the parser with which this list * was initally created * * @return an iterator over this list using the list's default parser. */ public FTPFileIterator iterator() { return new FTPFileIterator(this); } /** * create an iterator over this list using the supplied parser * * @param parser The user-supplied parser with which the list is to be * iterated, may be different from this list's default parser. * * @return an iterator over this list using the supplied parser. */ public FTPFileIterator iterator(FTPFileEntryParser parser) { return new FTPFileIterator(this, parser); } /** * returns an array of FTPFile objects for all the files in the directory * listing * * @return an array of FTPFile objects for all the files in the directory * listinge */ public FTPFile[] getFiles() { return iterator().getFiles(); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/ftp/FTPConnectionClosedException.java100644 0 0 3246 10344341135 26205 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/nntp/Threader.java100644 0 0 33533 10344341134 22470 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.HashMap; import java.util.Iterator; 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 * @return */ public Threadable thread(Threadable[] messages) { if (messages == null) return null; idTable = new HashMap(); // walk through each Threadable element for (int i = 0; i < messages.length; ++i) { if (!messages[i].isDummy()) buildContainer(messages[i]); } 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 = (ThreadContainer) 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 = (ThreadContainer) 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 = (ThreadContainer) 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 = (ThreadContainer) 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 = (ThreadContainer) 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; } } /** * A placeholder utility class, used for constructing a tree of Threadables * Originall 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) 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-1.4.1/src/java/org/apache/commons/net/nntp/Article.java100644 0 0 17306 10344341134 22315 0ustar 0 0 /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2005 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache Commons" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ 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 (String[]) list.toArray(); } /** * 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 (simplifiedSubject == "(no subject)") 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 (Threadable)new Article(); } } commons-net-1.4.1/src/java/org/apache/commons/net/nntp/NNTPCommand.java100644 0 0 5010 10344341134 22755 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/nntp/ArticlePointer.java100644 0 0 2542 10344341134 23632 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/nntp/NNTP.java100644 0 0 123775 10344341134 21541 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.ProtocolCommandSupport; import org.apache.commons.net.ProtocolCommandListener; 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_}. ***/ 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. ***/ 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 { StringBuffer buffer = new StringBuffer(); 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 { StringBuffer buffer = new StringBuffer(); 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 { StringBuffer command = new StringBuffer(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 { StringBuffer command = new StringBuffer("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-1.4.1/src/java/org/apache/commons/net/nntp/NewsgroupInfo.java100644 0 0 10350 10344341134 23527 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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() { StringBuffer buffer = new StringBuffer(); 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-1.4.1/src/java/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java100644 0 0 20040 10344341135 25035 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; StringBuffer buffer; __distributions = null; __newsgroups = null; __isGMT = gmt; buffer = new StringBuffer(); // 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-1.4.1/src/java/org/apache/commons/net/nntp/Threadable.java100644 0 0 2107 10344341135 22737 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/nntp/SimpleNNTPHeader.java100644 0 0 12010 10344341135 23760 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 StringBuffer __newsgroups; private StringBuffer __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 StringBuffer(); __headerFields = new StringBuffer(); __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. ***/ public String toString() { StringBuffer header = new StringBuffer(); 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-1.4.1/src/java/org/apache/commons/net/nntp/NNTPClient.java100644 0 0 146640 10344341135 22675 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.io.DotTerminatedMessageReader; import org.apache.commons.net.io.DotTerminatedMessageWriter; import org.apache.commons.net.io.Util; import org.apache.commons.net.MalformedServerReplyException; /*** * 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(new String(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, new String(lowArticleNumber + "-" + highArticleNumber)); } } /* Emacs configuration * Local variables: ** * mode: java ** * c-basic-offset: 4 ** * indent-tabs-mode: nil ** * End: ** */ commons-net-1.4.1/src/java/org/apache/commons/net/nntp/NNTPReply.java100644 0 0 21646 10344341135 22530 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 { 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; 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; 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 AUTHENTICATION_REQUIRED = CODE_408; 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; 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-1.4.1/src/java/org/apache/commons/net/nntp/NNTPConnectionClosedException.java100644 0 0 3273 10344341135 26521 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPRequestPacket.java100644 0 0 20244 10344341134 24201 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ int _mode; /*** The filename of the request. ***/ 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; int index, length; String mode; StringBuffer buffer; data = datagram.getData(); if (getType() != data[1]) throw new TFTPPacketException("TFTP operator code does not match type."); buffer = new StringBuffer(); index = 2; 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; } mode = buffer.toString().toLowerCase(); length = _modeStrings.length; for (index = 0; index < length; index++) { if (mode.equals(_modeStrings[index])) { _mode = index; break; } } if (index >= length) { throw new TFTPPacketException("Unrecognized TFTP transfer mode: " + mode); // 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. ***/ 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPPacket.java100644 0 0 17601 10344341134 22633 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPClient.java100644 0 0 54650 10344341134 22647 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; break _receivePacket; } else { discardPackets(); if (lastBlock == (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; TFTPPacket sent, received = null; TFTPErrorPacket error; TFTPDataPacket data = new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0); ; TFTPAckPacket ack; beginBufferedOps(); dataLength = lastBlock = hostPort = bytesRead = 0; block = 0; boolean lastAckWait = false; if (mode == TFTP.ASCII_MODE) input = new ToNetASCIIInputStream(input); sent = new TFTPWriteRequestPacket(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(); 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 (lastAckWait) break _sendPacket; else break _receivePacket; } else { discardPackets(); if (lastBlock == (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; } dataLength = TFTPPacket.SEGMENT_SIZE; offset = 4; while (dataLength > 0 && (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0) { offset += bytesRead; dataLength -= bytesRead; } data.setBlockNumber(block); data.setData(_sendBuffer, 4, offset - 4); sent = data; } while (dataLength == 0 || lastAckWait); 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPAckPacket.java100644 0 0 12066 10344341134 23252 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTP.java100644 0 0 25507 10344341134 21507 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPReadRequestPacket.java100644 0 0 5546 10344341134 24765 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java100644 0 0 5557 10344341134 25206 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPErrorPacket.java100644 0 0 15462 10344341135 23651 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; StringBuffer 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 StringBuffer(); 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. ***/ 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPPacketException.java100644 0 0 3216 10344341135 24470 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/tftp/TFTPDataPacket.java100644 0 0 17365 10344341135 23435 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/ntp/TimeStamp.java100644 0 0 41023 10344341134 22450 0ustar 0 0 package org.apache.commons.net.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ import java.util.TimeZone; import java.util.Date; import java.util.Locale; import java.lang.ref.SoftReference; import java.text.SimpleDateFormat; import java.text.DateFormat; /*** * 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: 165675 $ $Date: 2005-05-02 15:09:55 -0500 (Mon, 02 May 2005) $ * @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 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. */ 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. */ 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. */ public String toString() { return toString(ntpTime); } /*** * Left-pad 8-character hex string with 0's * * @param buf - StringBuffer which is appended with leading 0's. * @param l - a long. */ private static void appendHexString(StringBuffer 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) { StringBuffer buf = new StringBuffer(); // 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 = (DateFormat) 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 = (DateFormat) 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)); } /*** * Compares this TimeStamp to another Object. If the Object is a TimeStamp, * this function behaves like compareTo(TimeStamp). Otherwise, * it throws a ClassCastException (as TimeStamps are comparable * only to other TimeStamps). * * @param o the Object to be compared. * @return the value 0 if the argument is a TimeStamp * numerically equal to this TimeStamp; a value less than * 0 if the argument is a TimeStamp numerically * greater than this TimeStamp; and a value greater than * 0 if the argument is a TimeStamp numerically * less than this TimeStamp. * @exception ClassCastException if the argument is not a * TimeStamp. * @see java.lang.Comparable */ public int compareTo(Object o) { return compareTo((TimeStamp) o); } } commons-net-1.4.1/src/java/org/apache/commons/net/ntp/NtpV3Impl.java100644 0 0 37647 10344341134 22362 0ustar 0 0 package org.apache.commons.net.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ 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: 165675 $ $Date: 2005-05-02 15:09:55 -0500 (Mon, 02 May 2005) $ */ 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 byte[] buf = new byte[48]; private 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 (int) (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 (int) 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() { String id = ""; for (int i = 0; i <= 3; i++) { char c = (char) buf[REFERENCE_ID_INDEX + i]; if (c == 0) break; // 0-terminated string id = id + c; } return id; } 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 DatagramPacket getDatagramPacket() { if (dp == null) synchronized(this) { 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. */ public String toString() { return "[" + "version:" + getVersion() + ", mode:" + getMode() + ", poll:" + getPoll() + ", precision:" + getPrecision() + ", delay:" + getRootDelay() + ", dispersion(ms):" + getRootDispersionInMillisDouble() + ", id:" + getReferenceIdString() + ", xmitTime:" + getTransmitTimeStamp().toDateString() + " ]"; } } commons-net-1.4.1/src/java/org/apache/commons/net/ntp/TimeInfo.java100644 0 0 24602 10344341134 22263 0ustar 0 0 package org.apache.commons.net.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ import java.util.List; import java.util.ArrayList; /** * Wrapper class to network time packet messages (NTP, etc) that computes * related timing info and stats. * * @author Jason Mathews, MITRE Corp * * @version $Revision: 165675 $ $Date: 2005-05-02 15:09:55 -0500 (Mon, 02 May 2005) $ */ public class TimeInfo { private NtpV3Packet _message; private List _comments; private Long _delay; private Long _offset; /** * time at which time message packet was received by local machine */ private 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 = new Long(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 = new Long(_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 = new Long(rcvTime - origTime); } else if (xmitNtpTime.ntpValue() != 0) { // rcvTime is 0 just use xmitTime time _offset = new Long(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 = new Long(delayValue); if (origTime > _returnTime) // assert destTime >= origTime _comments.add("Error: OrigTime > DestRcvTime"); _offset = new Long(((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-1.4.1/src/java/org/apache/commons/net/ntp/NTPUDPClient.java100644 0 0 12224 10344341134 22717 0ustar 0 0 package org.apache.commons.net.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ 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: 165675 $ $Date: 2005-05-02 15:09:55 -0500 (Mon, 02 May 2005) $ ***/ 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-1.4.1/src/java/org/apache/commons/net/ntp/NtpV3Packet.java100644 0 0 14216 10344341134 22653 0ustar 0 0 package org.apache.commons.net.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ 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: 165675 $ $Date: 2005-05-02 15:09:55 -0500 (Mon, 02 May 2005) $ */ 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-1.4.1/src/java/org/apache/commons/net/ntp/NtpUtils.java100644 0 0 7226 10344341135 22317 0ustar 0 0 package org.apache.commons.net.ntp; /* * Copyright 2001-2005 The Apache Software Foundation * * 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. */ /*** * Common NtpUtils Helper class. * * @author Jason Mathews, MITRE Corp * * @version $Revision: 165675 $ $Date: 2005-05-02 15:09:55 -0500 (Mon, 02 May 2005) $ */ 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 ""; StringBuffer buf = new StringBuffer(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-1.4.1/src/java/org/apache/commons/net/DaytimeUDPClient.java100644 0 0 5441 10344341134 23034 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; /*** * 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.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 byte[] __dummyData = new byte[1]; // Received dates should be less than 256 bytes private 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-1.4.1/src/java/org/apache/commons/net/ProtocolCommandSupport.java100644 0 0 11012 10344341134 24434 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.Serializable; import java.util.Enumeration; 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 Object __source; private 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) { Enumeration en; ProtocolCommandEvent event; ProtocolCommandListener listener; en = __listeners.getListeners(); event = new ProtocolCommandEvent(__source, command, message); while (en.hasMoreElements()) { listener = (ProtocolCommandListener)en.nextElement(); 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) { Enumeration en; ProtocolCommandEvent event; ProtocolCommandListener listener; en = __listeners.getListeners(); event = new ProtocolCommandEvent(__source, replyCode, message); while (en.hasMoreElements()) { listener = (ProtocolCommandListener)en.nextElement(); 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-1.4.1/src/java/org/apache/commons/net/ProtocolCommandEvent.java100644 0 0 11250 10344341134 24045 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 int __replyCode; private boolean __isCommand; private 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-1.4.1/src/java/org/apache/commons/net/WhoisClient.java100644 0 0 6577 10344341134 22173 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.io.InputStream; /*** * 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-1.4.1/src/java/org/apache/commons/net/DiscardTCPClient.java100644 0 0 4164 10344341134 23010 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.OutputStream; /*** * 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-1.4.1/src/java/org/apache/commons/net/DatagramSocketClient.java100644 0 0 21702 10344341134 23776 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/util/ListenerList.java100644 0 0 2620 10344341134 23322 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.util; import java.io.Serializable; import java.util.Enumeration; import java.util.EventListener; import java.util.Vector; /** * @author Daniel F. Savarese */ public class ListenerList implements Serializable { private Vector __listeners; public ListenerList() { __listeners = new Vector(); } public synchronized void addListener(EventListener listener) { __listeners.addElement(listener); } public synchronized void removeListener(EventListener listener) { __listeners.removeElement(listener); } public synchronized Enumeration getListeners() { return ((Vector)__listeners.clone()).elements(); } public int getListenerCount() { return __listeners.size(); } } commons-net-1.4.1/src/java/org/apache/commons/net/SocketFactory.java100644 0 0 13022 10344341134 22522 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; /*** * The SocketFactory interface provides a means for the programmer to * control the creation of sockets and provide his own Socket * implementations for use by all classes derived from * {@link org.apache.commons.net.SocketClient}. * This allows you to provide your own Socket implementations and * to perform security checks or browser capability requests before * creating a Socket. *

*

* @author Daniel F. Savarese * @see DefaultSocketFactory ***/ public interface 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. ***/ public Socket createSocket(String host, int port) throws UnknownHostException, IOException; /*** * 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. ***/ public Socket createSocket(InetAddress address, int port) throws IOException; /*** * 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. ***/ public Socket createSocket(String host, int port, InetAddress localAddr, int localPort) throws UnknownHostException, IOException; /*** * 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. ***/ public Socket createSocket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException; /*** * 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; /*** * 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; /*** * 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; } commons-net-1.4.1/src/java/org/apache/commons/net/DaytimeTCPClient.java100644 0 0 5610 10344341134 23030 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /*** * 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 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; StringBuffer result = new StringBuffer(__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-1.4.1/src/java/org/apache/commons/net/DefaultDatagramSocketFactory.java100644 0 0 4524 10344341134 25457 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/MalformedServerReplyException.java100644 0 0 3410 10344341134 25712 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/TimeUDPClient.java100644 0 0 10527 10344341134 22357 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.util.Date; /*** * 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.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 byte[] __dummyData = new byte[1]; private 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-1.4.1/src/java/org/apache/commons/net/EchoUDPClient.java100644 0 0 6223 10344341134 22315 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; /*** * 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 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. ***/ public void send(byte[] data, int length, InetAddress host) throws IOException { send(data, length, host, DEFAULT_PORT); } /*** Same as send(data, data.length, host) ***/ 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-1.4.1/src/java/org/apache/commons/net/SocketClient.java100644 0 0 41607 10344341134 22343 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; /** * 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 org.apache.commons.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 = new DefaultSocketFactory(); /** The timeout to use after opening a socket. */ protected int _timeout_; /** The socket used for the connection. */ protected Socket _socket_; /** * A status variable indicating if the client's socket is currently open. */ protected boolean _isConnected_; /** 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_; /** * 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; _isConnected_ = false; _socketFactory_ = __DEFAULT_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(); _isConnected_ = true; } /** * 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(host, port); _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 { _socket_ = _socketFactory_.createSocket(hostname, port); _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 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(host, port, localAddr, localPort); _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 { _socket_ = _socketFactory_.createSocket(hostname, port, localAddr, localPort); _connectAction_(); } /** * 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 { _socket_.close(); _input_.close(); _output_.close(); _socket_ = null; _input_ = null; _output_ = null; _isConnected_ = false; } /** * 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() { return _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); } /** * 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_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; } } commons-net-1.4.1/src/java/org/apache/commons/net/smtp/RelayPath.java100644 0 0 5344 10344341134 22606 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ public String toString() { StringBuffer buffer = new StringBuffer(); Enumeration hosts; buffer.append('<'); hosts = _path.elements(); if (hosts.hasMoreElements()) { buffer.append('@'); buffer.append((String)hosts.nextElement()); while (hosts.hasMoreElements()) { buffer.append(",@"); buffer.append((String)hosts.nextElement()); } buffer.append(':'); } buffer.append(_emailAddress); buffer.append('>'); return buffer.toString(); } } commons-net-1.4.1/src/java/org/apache/commons/net/smtp/SimpleSMTPHeader.java100644 0 0 11132 10344341134 23773 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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. ***/ public String toString() { StringBuffer header = new StringBuffer(); 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-1.4.1/src/java/org/apache/commons/net/smtp/SMTPClient.java100644 0 0 61431 10344341134 22656 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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() { } /*** * 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-1.4.1/src/java/org/apache/commons/net/smtp/SMTPReply.java100644 0 0 15057 10344341135 22537 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/smtp/SMTPCommand.java100644 0 0 6163 10344341135 23000 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/smtp/SMTP.java100644 0 0 73213 10344341135 21521 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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.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; /*** * 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"; private StringBuffer __commandBuffer; BufferedReader _reader; BufferedWriter _writer; int _replyCode; Vector _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 Vector(); _newReplyString = false; _replyString = null; _commandSupport_ = new ProtocolCommandSupport(this); } 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.setSize(0); 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.addElement(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.addElement(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. ***/ protected void _connectAction_() throws IOException { super._connectAction_(); _reader = new BufferedReader(new InputStreamReader(_input_, __DEFAULT_ENCODING)); _writer = new BufferedWriter(new OutputStreamWriter(_output_, __DEFAULT_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. ***/ public void disconnect() throws IOException { super.disconnect(); _reader = null; _writer = null; _replyString = null; _replyLines.setSize(0); _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() { String[] lines; lines = new String[_replyLines.size()]; _replyLines.copyInto(lines); return lines; } /*** * 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() { Enumeration en; StringBuffer buffer; if (!_newReplyString) return _replyString; buffer = new StringBuffer(256); en = _replyLines.elements(); while (en.hasMoreElements()) { buffer.append((String)en.nextElement()); 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-1.4.1/src/java/org/apache/commons/net/smtp/SMTPConnectionClosedException.java100644 0 0 3275 10344341135 26533 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/DatagramSocketFactory.java100644 0 0 4320 10344341134 24144 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/FingerClient.java100644 0 0 13306 10344341134 22320 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedOutputStream; import java.io.DataOutputStream; /*** * 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 StringBuffer __query = new StringBuffer(64); 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; StringBuffer result = new StringBuffer(__buffer.length); BufferedReader input; input = new BufferedReader(new InputStreamReader(getInputStream(longOutput, username))); while (true) { read = input.read(__buffer, 0, __buffer.length); if (read <= 0) break; result.append(__buffer, 0, read); } 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 { DataOutputStream output; __query.setLength(0); if (longOutput) __query.append(__LONG_FLAG); __query.append(username); __query.append(SocketClient.NETASCII_EOL); output = new DataOutputStream(new BufferedOutputStream(_output_, 1024)); output.writeBytes(__query.toString()); 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-1.4.1/src/java/org/apache/commons/net/DefaultSocketFactory.java100644 0 0 13605 10344341134 24036 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; /*** * 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 implements 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. ***/ 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. ***/ 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. ***/ 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. ***/ 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-1.4.1/src/java/org/apache/commons/net/TimeTCPClient.java100644 0 0 7456 10344341134 22344 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.util.Date; import java.io.DataInputStream; /*** * 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 (long)(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-1.4.1/src/java/org/apache/commons/net/EchoTCPClient.java100644 0 0 4355 10344341134 22317 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.InputStream; /*** * 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-1.4.1/src/java/org/apache/commons/net/ProtocolCommandListener.java100644 0 0 3766 10344341135 24547 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/java/org/apache/commons/net/CharGenUDPClient.java100644 0 0 11306 10344341135 22765 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; /*** * 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 byte[] __receiveData; private DatagramPacket __receivePacket; private 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, 512); __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-1.4.1/src/java/org/apache/commons/net/DiscardUDPClient.java100644 0 0 5473 10344341135 23017 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; /*** * 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-1.4.1/src/test/org/apache/commons/net/telnet/SuppressGAOptionHandlerTest.java100644 0 0 4420 10344341134 26640 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; /*** * JUnit test class for SuppressGAOptionHandler *

* @author Bruno D'Avanzo ***/ public class SuppressGAOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(SuppressGAOptionHandlerTest.class); } /*** * setUp for the test. ***/ protected void setUp() { opthand1 = new SuppressGAOptionHandler(); opthand2 = new SuppressGAOptionHandler(true, true, true, true); opthand3 = new SuppressGAOptionHandler(false, false, false, false); } /*** * test of the constructors. ***/ public void testConstructors() { assertEquals(opthand1.getOptionCode(), TelnetOption.SUPPRESS_GO_AHEAD); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ 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. ***/ 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-1.4.1/src/test/org/apache/commons/net/telnet/InvalidTelnetOptionExceptionTest.java100644 0 0 3030 10344341134 27723 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(InvalidTelnetOptionExceptionTest.class); } /*** * setUp for the test. ***/ protected void setUp() { msg1 = new String("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-1.4.1/src/test/org/apache/commons/net/telnet/EchoOptionHandlerTest.java100644 0 0 4321 10344341134 25462 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; /*** * JUnit test class for EchoOptionHandler *

* @author Bruno D'Avanzo ***/ public class EchoOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(EchoOptionHandlerTest.class); } /*** * setUp for the test. ***/ protected void setUp() { opthand1 = new EchoOptionHandler(); opthand2 = new EchoOptionHandler(true, true, true, true); opthand3 = new EchoOptionHandler(false, false, false, false); } /*** * test of the constructors. ***/ public void testConstructors() { assertEquals(opthand1.getOptionCode(), TelnetOption.ECHO); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ 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. ***/ 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-1.4.1/src/test/org/apache/commons/net/telnet/TelnetTestSimpleServer.java100644 0 0 7467 10344341134 25727 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; import java.net.ServerSocket; import java.net.Socket; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; /*** * Simple TCP server. * Waits for connections on a TCP port in a separate thread. *

* @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-1.4.1/src/test/org/apache/commons/net/telnet/SimpleOptionHandlerTest.java100644 0 0 4455 10344341134 26045 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; /*** * JUnit test class for SimpleOptionHandler *

* @author Bruno D'Avanzo ***/ public class SimpleOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(SimpleOptionHandlerTest.class); } /*** * setUp for the test. ***/ 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. ***/ 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. ***/ 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. ***/ 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-1.4.1/src/test/org/apache/commons/net/telnet/TelnetOptionHandlerTestAbstract.java100644 0 0 6340 10344341134 27526 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; import junit.framework.TestCase; /*** * The TelnetOptionHandlerTest is the abstract class for * testing TelnetOptionHandler. It can be used to derive * the actual test classes for TelnetOptionHadler derived * classes, by adding creation of three new option handlers * and testing of the specific subnegotiation behaviour. *

* @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); ***/ 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-1.4.1/src/test/org/apache/commons/net/telnet/TelnetClientTest.java100644 0 0 65621 10344341134 24541 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(TelnetClientTest.class); } /*** * open connections needed for the tests for the test. ***/ 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 */ 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); } } assertTrue(numdo == 2); assertTrue(numdont == 1); assertTrue(numwont == 1); assertTrue(numwill == 0); } /*** * 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) //{ is1.read(buffread1); 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); //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-1.4.1/src/test/org/apache/commons/net/telnet/TelnetOptionTest.java100644 0 0 3114 10344341135 24541 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; import junit.framework.TestCase; /*** * JUnit test class for TelnetOption *

* @author Bruno D'Avanzo ***/ public class TelnetOptionTest extends TestCase { /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(TelnetOptionTest.class); } /*** * 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-1.4.1/src/test/org/apache/commons/net/telnet/TelnetClientFunctionalTest.java100644 0 0 6377 10344341135 26550 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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; /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(TelnetClientFunctionalTest.class); } /*** * test setUp ***/ 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 = new String(); 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-1.4.1/src/test/org/apache/commons/net/telnet/TerminalTypeOptionHandlerTest.java100644 0 0 5767 10344341135 27241 0ustar 0 0 /* * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.telnet; /*** * JUnit test class for TerminalTypeOptionHandler *

* @author Bruno D'Avanzo ***/ public class TerminalTypeOptionHandlerTest extends TelnetOptionHandlerTestAbstract { /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(TerminalTypeOptionHandlerTest.class); } /*** * setUp for the test. ***/ 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. ***/ public void testConstructors() { assertEquals(opthand1.getOptionCode(), TelnetOption.TERMINAL_TYPE); super.testConstructors(); } /*** * test of client-driven subnegotiation. * Checks that no subnegotiation is made. ***/ 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 ***/ 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 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 inputs - Array of answers. ***/ 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 = new String(); 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-1.4.1/src/test/org/apache/commons/net/ftp/parser/CompositeFTPParseTestFramework.java100644 0 0 10143 10344341134 30113 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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() */ 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() */ 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() */ 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, 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; } } } } ././@LongLink100644 0 0 147 10344341135 10253 Lustar 0 0 commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.javacommons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.ja100644 0 0 6542 10344341134 30654 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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()); } 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); 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-1.4.1/src/test/org/apache/commons/net/ftp/parser/OS2FTPEntryParserTest.java100644 0 0 10756 10344341134 26114 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import junit.framework.TestSuite; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: OS2FTPEntryParserTest.java 155429 2005-02-26 13:13:04Z dirkv $ */ 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); } /** * Method suite. * @return TestSuite */ public static TestSuite suite() { return (new TestSuite(OS2FTPEntryParserTest.class)); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ 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() */ 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() */ protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ protected String[] getGoodListing() { return (goodsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ protected FTPFileEntryParser getParser() { ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser(); parser.configure(null); return parser; } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/NTFTPEntryParserTest.java100644 0 0 16000 10344341134 26016 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.util.Calendar; import junit.framework.TestSuite; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: NTFTPEntryParserTest.java 155429 2005-02-26 13:13:04Z dirkv $ */ public class NTFTPEntryParserTest extends CompositeFTPParseTestFramework { private static final String [][] goodsamples = { { "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$", }, { "-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", } }; private static final String[][] badsamples = { { "20-05-97 03:31PM 681 .bash_history", "drwxr-xr-x 2 root 99 4096 Feb 23 30:01 zzplayer", "12-05-96 17:03 absoft2", "05-22-97 08:08 828 AUTOEXEC.BAK", " 0 DIR 05-19-97 12:56 local", " 0 DIR 05-12-97 16:52 Maintenance Desktop", }, { "20-05-97 03:31PM 681 .bash_history", "drwxr-xr-x 2 root 99 4096Feb 23 30:01 zzplayer", "12-05-96 17:03 absoft2", "05-22-97 08:08 828 AUTOEXEC.BAK", " 0 DIR 05-19-97 12:56 local", " 0 DIR 05-12-97 16:52 Maintenance Desktop", } }; 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() */ protected String[][] getGoodListings() { return goodsamples; } /** * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getBadListings() */ protected String[][] getBadListings() { return badsamples; } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ protected FTPFileEntryParser getParser() { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new NTFTPEntryParser(), new UnixFTPEntryParser() }); } /** * Method suite. * * @return TestSuite */ public static TestSuite suite() { return(new TestSuite(NTFTPEntryParserTest.class)); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ 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()); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ 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()); } 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()); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/VMSFTPEntryParserTest.java100644 0 0 31034 10344341134 26146 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.io.ByteArrayInputStream; import java.io.IOException; import junit.framework.TestSuite; 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 155429 2005-02-26 13:13:04Z dirkv $ */ 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())); 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())); 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() */ 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); dir = getParser().parseFTPEntry("DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [TRANSLATED] (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(null, dir.getGroup()); assertEquals("TRANSLATED", dir.getUser()); checkPermisions(dir); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ 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,RWED,RE)"); 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); file = getParser().parseFTPEntry("1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [TRANSLATED] (RWED,RWED,RWED,RE)"); 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); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ protected String[] getGoodListing() { return (goodsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ 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) { 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)); } /** * Method suite. * @return TestSuite */ public static TestSuite suite() { return(new TestSuite(VMSFTPEntryParserTest.class)); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java100644 0 0 25356 10344341134 26436 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.util.Calendar; import junit.framework.TestSuite; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * @author Steve Cohen * @version $Id: UnixFTPEntryParserTest.java 165675 2005-05-02 20:09:55Z 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/." }; /** * @see junit.framework.TestCase#TestCase(String) */ public UnixFTPEntryParserTest(String name) { super(name); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing() */ protected String[] getBadListing() { return (badsamples); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ 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() */ protected FTPFileEntryParser getParser() { return (new UnixFTPEntryParser()); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ 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() */ public void testParseFieldsOnFile() throws Exception { FTPFile f = getParser() .parseFTPEntry( "-rwxr-xr-x 2 user group 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("group", 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())); } /** * Method suite. * @return TestSuite */ public static TestSuite suite() { return (new TestSuite(UnixFTPEntryParserTest.class)); } /* * @param test * @param f */ 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()); 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), f.hasPermission(access, perm), permchar != '-' && !Character.isUpperCase(permchar)); } } } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/AllTests.java100644 0 0 2243 10344341134 23603 0ustar 0 0 /* * Created on Apr 5, 2004 * * To change the template for this generated file go to * Window - Preferences - Java - Code Generation - Code and Comments */ package org.apache.commons.net.ftp.parser; import junit.framework.Test; import junit.framework.TestSuite; /** * @author scohen * * To change the template for this generated type comment go to * Window - Preferences - Java - Code Generation - Code and Comments */ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("Test for org.apache.commons.net.ftp.parser"); //$JUnit-BEGIN$ suite.addTest(FTPTimestampParserImplTest.suite()); suite.addTest(OS2FTPEntryParserTest.suite()); suite.addTest(VMSFTPEntryParserTest.suite()); suite.addTest(UnixFTPEntryParserTest.suite()); suite.addTestSuite(DefaultFTPFileEntryParserFactoryTest.class); suite.addTest(EnterpriseUnixFTPEntryParserTest.suite()); suite.addTest(OS400FTPEntryParserTest.suite()); suite.addTest(NTFTPEntryParserTest.suite()); suite.addTest(MVSFTPEntryParserTest.suite()); //$JUnit-END$ return suite; } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/OS400FTPEntryParserTest.java100644 0 0 13414 10344341134 26250 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import junit.framework.TestSuite; 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 USR 0 45056 Mar 24 14:06 dir1", "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() */ protected String[][] getBadListings() { return badsamples; } /** * @see FTPParseTestFramework#getGoodListing() */ protected String[][] getGoodListings() { return goodsamples; } /** * @see FTPParseTestFramework#getParser() */ protected FTPFileEntryParser getParser() { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new OS400FTPEntryParser(), new UnixFTPEntryParser() }); } /** * @see FTPParseTestFramework#testParseFieldsOnDirectory() */ 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())); } protected void doAdditionalGoodTests(String test, FTPFile f) { if (test.startsWith("d")) { assertEquals("directory.type", FTPFile.DIRECTORY_TYPE, f.getType()); } } /** * @see FTPParseTestFramework#testParseFieldsOnFile() */ 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())); } /** * Method suite. * * @return TestSuite */ public static TestSuite suite() { return(new TestSuite(OS400FTPEntryParserTest.class)); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java100644 0 0 16752 10344341134 30477 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.util.Calendar; import junit.framework.TestSuite; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * Tests the EnterpriseUnixFTPEntryParser * * @version $Id: EnterpriseUnixFTPEntryParserTest.java 165675 2005-05-02 20:09:55Z 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); } /** * Method suite. * * @return TestSuite */ public static TestSuite suite() { return (new TestSuite(EnterpriseUnixFTPEntryParserTest.class)); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory() */ public void testParseFieldsOnDirectory() throws Exception { // Everything is a File for now. } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ 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() */ protected String[] getBadListing() { return (BADSAMPLES); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing() */ protected String[] getGoodListing() { return (GOODSAMPLES); } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ 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-1.4.1/src/test/org/apache/commons/net/ftp/parser/FTPParseTestFramework.java100644 0 0 7776 10344341135 26233 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 165675 2005-05-02 20:09:55Z 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, 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() */ protected void setUp() throws Exception { super.setUp(); parser = getParser(); df = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java100644 0 0 13614 10344341135 27251 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.apache.commons.net.ftp.FTPClientConfig; import junit.framework.TestCase; import junit.framework.TestSuite; /** * @author scohen * * To change the template for this generated type comment go to * Window - Preferences - Java - Code Generation - Code and Comments */ public class FTPTimestampParserImplTest extends TestCase { private static final int TWO_HOURS_OF_MILLISECONDS = 2 * 60 * 60 * 1000; public void testParseTimestamp() { Calendar cal = Calendar.getInstance(); int timeZoneOffset = cal.getTimeZone().getRawOffset(); 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 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", (long)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"); } } /** * Method suite. * * @return TestSuite */ public static TestSuite suite() { return(new TestSuite(FTPTimestampParserImplTest.class)); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java100644 0 0 10327 10344341135 26151 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import junit.framework.TestSuite; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** * Created on Apr 6, 2005
* @author William Noto * @version $Id: NTFTPEntryParserTest.java,v 1.16 2005/01/02 03:17:50 scohen Exp $ */ public class MVSFTPEntryParserTest extends FTPParseTestFramework { private static final String [] goodsamples = { "Migrated file1.I", "Migrated file2.I", "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", "Migrated file6.O", "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", "FPFS42 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.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 [] 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() */ protected String[] getBadListing() { return badsamples; } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getGoodListings() */ protected String[] getGoodListing() { return goodsamples; } /** * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() */ protected FTPFileEntryParser getParser() { return new CompositeFileEntryParser(new FTPFileEntryParser[] { new MVSFTPEntryParser(), }); } /** * Method suite. * * @return TestSuite */ public static TestSuite suite() { return(new TestSuite(MVSFTPEntryParserTest.class)); } public void testParseFieldsOnDirectory() throws Exception { // I don't really know how to test this because the MVS system that I // connect with does not allow me to create directories. } /* (non-Javadoc) * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() */ public void testParseFieldsOnFile() throws Exception { FTPFile file = getParser().parseFTPEntry("Migrated file1.I"); assertNotNull("Could not parse entry.", file); assertTrue("Should have been a file.", file.isFile()); assertEquals("file1.I", file.getName()); FTPFile file2 = getParser().parseFTPEntry("PSMLC1 3390 2005/04/04 1 1 VB 27994 27998 PS file2.I"); assertNotNull("Could not parse entry.", file2); assertTrue("Should have been a file.", file2.isFile()); assertEquals("file2.I", file2.getName()); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/parser/FTPConfigEntryParserTest.java100644 0 0 14104 10344341135 26706 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp.parser; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; 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(); Date refDate = new Date(); 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(); Date refDate = new Date(); 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-1.4.1/src/test/org/apache/commons/net/ftp/ListingFunctionalTest.java100644 0 0 22357 10344341134 25100 0ustar 0 0 /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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 167953 2005-05-03 18:29:42Z dfs $ */ public class ListingFunctionalTest extends TestCase { static final int HOSTNAME = 0; static final int INVALID_PARSERKEY = 2; static final int INVALID_PATH = 3; static final int VALID_FILENAME = 4; static final int VALID_PARSERKEY = 1; 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\\ftp\\drivers" }, { "h71000.www7.hp.com", "vms", "windows", "[.HA!]", "ACLOCAL.M4;1", "[.FREEWARE50.XTERM]" } }; 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]); 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() */ protected void setUp() throws Exception { super.setUp(); client = new FTPClient(); client.connect(hostName); client.login("anonymous", "anonymous"); client.enterLocalPassiveMode(); } /* * @see TestCase#tearDown() */ 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 { List names = Arrays.asList(client.listNames(validPath)); assertTrue(names.toString(), findByName(names, validFilename)); } public void testListNamesWithPathButEmpty() throws IOException { String[] names = client.listNames(invalidPath); assertNull(names); } } commons-net-1.4.1/src/test/org/apache/commons/net/ftp/FTPClientConfigFunctionalTest.java100644 0 0 13377 10344341134 26407 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import junit.framework.TestCase; import java.io.IOException; import java.net.SocketException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /* * 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 */ 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 */ 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 static void main(String[] args) { FTPClientConfigFunctionalTest F = new FTPClientConfigFunctionalTest(); } 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 (Iterator it = sorted.iterator(); it.hasNext();) { FTPFile thisfile = (FTPFile) it.next(); 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-1.4.1/src/test/org/apache/commons/net/ftp/FTPClientConfigTest.java100644 0 0 14143 10344341135 24355 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package 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-1.4.1/src/test/org/apache/commons/net/ftp/AllTests.java100644 0 0 2221 10344341135 22304 0ustar 0 0 /* * Copyright 2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.ftp; import junit.framework.Test; import junit.framework.TestSuite; /** * Test suite for the org.apache.commons.net.ftp package. */ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("Test for org.apache.commons.net.ftp"); //$JUnit-BEGIN$ suite.addTest(ListingFunctionalTest.suite()); suite.addTestSuite(FTPClientConfigTest.class); suite.addTestSuite(FTPClientConfigFunctionalTest.class); //$JUnit-END$ return suite; } } commons-net-1.4.1/src/test/org/apache/commons/net/pop3/POP3ClientCommandsTest.java100644 0 0 35667 10344341134 25106 0ustar 0 0 /** * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.pop3; import junit.framework.TestCase; import junit.framework.TestSuite; import java.net.InetAddress; import java.io.IOException; import java.io.Reader; /** * @author [Net] * @version $Id: POP3ClientCommandsTest.java 165675 2005-05-02 20:09:55Z rwinston $ * * 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); } /** * Method suite. * @return TestSuite */ public static TestSuite suite() { return (new TestSuite(POP3ClientCommandsTest.class)); } 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(); assertTrue(msg2.number == 0); assertTrue(msg2.size == 0); 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]); assertTrue(msg[i].number == i + 1); 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); assertTrue(msg.number == 1); 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(); assertTrue(msg.length == 0); //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]); assertTrue(msg[i].number == i + 1); 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); assertTrue(msg.number == 1); 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(); assertTrue(msg.length == 0); //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-1.4.1/src/test/org/apache/commons/net/pop3/TestSetupParameters.java100644 0 0 3370 10344341134 24632 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.pop3; /** * @author [Net] * @version $Id: TestSetupParameters.java 165675 2005-05-02 20:09:55Z rwinston $ * * 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-1.4.1/src/test/org/apache/commons/net/pop3/POP3ConstructorTest.java100644 0 0 13345 10344341134 24520 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.pop3; import junit.framework.TestCase; import junit.framework.TestSuite; import java.io.Reader; /** * @author [Net] * @version $Id: POP3ConstructorTest.java 165675 2005-05-02 20:09:55Z rwinston $ * * 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); } /** * Method suite. * @return TestSuite */ public static TestSuite suite() { return (new TestSuite(POP3ConstructorTest.class)); } /** * 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-1.4.1/src/test/org/apache/commons/net/pop3/POP3ClientTest.java100644 0 0 11214 10344341134 23402 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.pop3; import junit.framework.TestCase; import junit.framework.TestSuite; import java.net.InetAddress; import java.io.IOException; /** * @author [Net] * @version $Id: POP3ClientTest.java 165675 2005-05-02 20:09:55Z rwinston $ * * 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); } /** * Method suite. * @return TestSuite */ public static TestSuite suite() { return (new TestSuite(POP3ClientTest.class)); } 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-1.4.1/src/test/org/apache/commons/net/pop3/AllTests.java100644 0 0 3462 10344341134 22403 0ustar 0 0 /* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net.pop3; import junit.framework.Test; import junit.framework.TestSuite; /** * @author [Net] * @version $Id: AllTests.java 165675 2005-05-02 20:09:55Z rwinston $ * * 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 AllTests { public static Test suite() { TestSuite suite = new TestSuite("Test for org.apache.commons.net.pop3"); //$JUnit-BEGIN$ suite.addTest(POP3ConstructorTest.suite()); suite.addTest(POP3ClientTest.suite()); suite.addTest(POP3ClientCommandsTest.suite()); //$JUnit-END$ return suite; } } commons-net-1.4.1/src/test/org/apache/commons/net/time/TimeTCPClientTest.java100644 0 0 13605 10344341134 24211 0ustar 0 0 package org.apache.commons.net.time; /* ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ import java.net.InetAddress; import java.util.Calendar; import java.io.IOException; import java.util.TimeZone; import junit.framework.TestCase; import org.apache.commons.net.TimeTCPClient; public class TimeTCPClientTest extends TestCase { private TimeTestSimpleServer server1; private int _port = 3333; // default test port /*** * main for running the test. ***/ public static void main(String[] args) { junit.textui.TestRunner.run(TimeTCPClientTest.class); } /*** * 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; assertTrue(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 { 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 { 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-1.4.1/src/test/org/apache/commons/net/time/TimeTestSimpleServer.java100644 0 0 14274 10344341134 25047 0ustar 0 0 package org.apache.commons.net.time; /* ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ 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: 1.1 $ $Date: 2003/09/24 21:51:48 $ */ 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-1.4.1/src/test/org/apache/commons/net/ntp/TimeStampTest.java100644 0 0 13364 10344341135 23356 0ustar 0 0 package org.apache.commons.net.ntp; /* ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ 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 /*** * main for running the test. ***/ public static void main(String args[]) { junit.textui.TestRunner.run(TimeStampTest.class); } 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); assertTrue("compareTo(1,2)", ts1.compareTo(ts2) == 0); 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)); assertTrue("compareTo(1,3)", ts1.compareTo(ts3) == -1); 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-1.4.1/NOTICE.txt100644 0 0 145 10344341135 12603 0ustar 0 0 This product includes software developed by The Apache Software Foundation (http://www.apache.org/).