/** * This file is part of Waarp Project. * * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the * COPYRIGHT.txt in the distribution for a full listing of individual contributors. * * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Waarp . If not, see * <http://www.gnu.org/licenses/>. */ package org.waarp.common.command; import org.waarp.common.exception.InvalidArgumentException; /** * Reply code references by different RFC. * * @author Frederic Bregier * */ public enum ReplyCode { /** * unofficial reply code for no value */ REPLY_000_SPECIAL_NOSTATUS(0), /** * 110 Restart marker reply. In this case, the text is exact and not left to the particular * implementation), it must read: MARK yyyy (mmmm Where yyyy is User-process data stream marker, * and mmmm server's equivalent marker (note the spaces between markers and "="). */ REPLY_110_RESTART_MARKER_REPLY(110), /** * 120 Service ready in nnn minutes. */ REPLY_120_SERVICE_READY_IN_NNN_MINUTES(120), /** * 125 Data connection already open), transfer starting. */ REPLY_125_DATA_CONNECTION_ALREADY_OPEN(125), /** * 150 File status okay), about to open data connection. */ REPLY_150_FILE_STATUS_OKAY(150), /** * 200 Command okay. */ REPLY_200_COMMAND_OKAY(200), /** * 202 Command not implemented, superfluous at this site. */ REPLY_202_COMMAND_NOT_IMPLEMENTED(202), /** * 211 System status, or system help reply. */ REPLY_211_SYSTEM_STATUS_REPLY(211), /** * 212 Directory status. */ REPLY_212_DIRECTORY_STATUS(212), /** * 213 File status. */ REPLY_213_FILE_STATUS(213), /** * 214 Help message. On how to use the server or the meaning of a particular non-standard * command. This reply is useful only to the human user. */ REPLY_214_HELP_MESSAGE( 214, "This FTP server refers to RFC 959, RFC 775, RFC 2389 and RFC 3659"), /** * 215 NAME system type. Where NAME is an official system name from the list in the Assigned * Numbers document. */ REPLY_215_NAME_SYSTEM_TYPE(215), /** * 220 Service ready for new user. */ REPLY_220_SERVICE_READY(220), /** * Service closing control connection. Logged out if appropriate. */ REPLY_221_CLOSING_CONTROL_CONNECTION(221), /** * 225 Data connection open), no transfer in progress. */ REPLY_225_DATA_CONNECTION_OPEN_NO_TRANSFER_IN_PROGRESS(225), /** * Closing data connection. Requested file action successful (for example, file transfer or file * abort). */ REPLY_226_CLOSING_DATA_CONNECTION(226), /** * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ REPLY_227_ENTERING_PASSIVE_MODE(227), /** * 229 Entering Extended Passive Mode (|n|addr|port|). */ REPLY_229_ENTERING_PASSIVE_MODE(229), /** * 230 User logged in, proceed. */ REPLY_230_USER_LOGGED_IN(230), /** * 232 User logged in, authorized by security data exchange. */ REPLY_232_USER_LOGGED_IN(232), /** * 234 Security data exchange complete. */ REPLY_234_SECURITY_DATA_EXCHANGE_COMPLETE(234), /** * 250 Requested file action okay, completed. */ REPLY_250_REQUESTED_FILE_ACTION_OKAY(250), /** * 257 "PATHNAME" created. */ REPLY_257_PATHNAME_CREATED(257), /** * 331 User name okay, need password. */ REPLY_331_USER_NAME_OKAY_NEED_PASSWORD(331), /** * 332 Need account for login. */ REPLY_332_NEED_ACCOUNT_FOR_LOGIN(332), /** * 350 Requested file action pending further information. */ REPLY_350_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFORMATION(350), /** * 421 Service not available, closing control connection. This may be a reply to any command if * the service knows it must shut down. */ REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION(421), /** * 425 Can't open data connection. */ REPLY_425_CANT_OPEN_DATA_CONNECTION(425), /** * 426 Connection closed), transfer aborted. */ REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED(426), /** * 431 Need some unavailable resource to process security. */ REPLY_431_NEED_UNAVAILABLE_RESOURCE_TO_PROCESS_SECURITY(431), /** * 450 Requested file action not taken. File unavailable (e.g., file busy). */ REPLY_450_REQUESTED_FILE_ACTION_NOT_TAKEN(450), /** * 451 Requested action aborted: local error in processing. */ REPLY_451_REQUESTED_ACTION_ABORTED(451), /** * 452 Requested action not taken. Insufficient storage space in system. */ REPLY_452_REQUESTED_ACTION_NOT_TAKEN(452), /** * 500 Syntax error, command unrecognized. This may include errors such as command line too * long. */ REPLY_500_SYNTAX_ERROR_COMMAND_UNRECOGNIZED(500), /** * 501 Syntax error in parameters or arguments. */ REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS(501), /** * 502 Command not implemented. */ REPLY_502_COMMAND_NOT_IMPLEMENTED(502), /** * 503 Bad sequence of commands. */ REPLY_503_BAD_SEQUENCE_OF_COMMANDS(503), /** * 504 Command not implemented for that parameter. */ REPLY_504_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER(504), /** * 522 Extended Port Failure - unknown network protocol. */ REPLY_522_EXTENDED_PORT_FAILURE_UNKNOWN_NETWORK_PROTOCOL(522), /** * 530 Not logged in. */ REPLY_530_NOT_LOGGED_IN(530), /** * 532 Need account for storing files. */ REPLY_532_NEED_ACCOUNT_FOR_STORING_FILES(532), /** * 533 Command protection level denied for policy reasons. */ REPLY_533_COMMAND_PROTECTION_LEVEL_DENIED_FOR_POLICY_REASONS(533), /** * 534 Request denied for policy reasons. */ REPLY_534_REQUEST_DENIED_FOR_POLICY_REASONS(534), /** * 535 Failed security check (hash, sequence, etc). */ REPLY_535_FAILED_SECURITY_CHECK(535), /** * 536 Requested PROT level not supported by mechanism. */ REPLY_536_REQUESTED_PROT_LEVEL_NOT_SUPPORTED(536), /** * 550 Requested action not taken. File unavailable (e.g., file not found, no access). */ REPLY_550_REQUESTED_ACTION_NOT_TAKEN(550), /** * 551 Requested action aborted: page type unknown. */ REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN(551), /** * 552 Requested file action aborted. Exceeded storage allocation (for current directory or * dataset). */ REPLY_552_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE(552), /** * 553 Requested action not taken. File name not allowed. */ REPLY_553_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED(553); /** * Numerical code */ private int code; /** * Message associated */ private String mesg; /** * LF */ public static final String LF = "\n"; /** * CR NUL */ public static final String CRNUL = "\r\0"; /** * CR LF<br> * A User Telnet MUST be able to send any of the forms: CR LF, CR NUL, and LF. A User Telnet on * an ASCII host SHOULD have a user-controllable mode to send either CR LF or CR NUL when the * user presses the "end-of-line" key, and CR LF SHOULD be the default. */ public static final String CRLF = "\r\n"; /** * Construct a Reply code from specific message * * @param code * @param mesg */ private ReplyCode(int code, String mesg) { this.code = code; this.mesg = getFinalMsg(code, mesg); } /** * Return the final message formatted as needed from the code and the message * * @param code * @param msg * @return the final formatted message */ public static String getFinalMsg(int code, String msg) { StringBuilder builder = new StringBuilder(); builder.append(code); if (msg.indexOf('\n') == -1) { builder.append(' ').append(msg).append(ReplyCode.CRLF); } else { String[] lines = msg.split("\n"); // first line builder.append('-').append(lines[0]).append(ReplyCode.CRLF); // next lines for (int i = 1; i < lines.length - 1; i++) { int firstBlank = lines[i].indexOf(' '); if (firstBlank > 0) { String firstParam = lines[i].substring(0, firstBlank); boolean isInt = false; try { Integer.parseInt(firstParam); isInt = true; } catch (NumberFormatException e) { // not a number } if (isInt) { builder.append(" "); } } builder.append(lines[i]).append(ReplyCode.CRLF); } // last line builder.append(code).append(' ').append(lines[lines.length - 1]).append(ReplyCode.CRLF); } return builder.toString(); } /** * Construct a Reply Code from its name in Enum structure * * @param code */ private ReplyCode(int code) { this.code = code; mesg = name().substring(6).replace('_', ' ') + ReplyCode.CRLF; } /** * @return the code */ public int getCode() { return code; } /** * @return the mesg */ public String getMesg() { return mesg; } /** * * @param code * @return the associated ReplyCode from the given numerical code * @throws InvalidArgumentException */ public static ReplyCode getReplyCode(int code) throws InvalidArgumentException { switch (code) { case 0: return REPLY_000_SPECIAL_NOSTATUS; case 110: return REPLY_110_RESTART_MARKER_REPLY; case 120: return REPLY_120_SERVICE_READY_IN_NNN_MINUTES; case 125: return REPLY_125_DATA_CONNECTION_ALREADY_OPEN; case 150: return REPLY_150_FILE_STATUS_OKAY; case 200: return REPLY_200_COMMAND_OKAY; case 202: return REPLY_202_COMMAND_NOT_IMPLEMENTED; case 211: return REPLY_211_SYSTEM_STATUS_REPLY; case 212: return REPLY_212_DIRECTORY_STATUS; case 213: return REPLY_213_FILE_STATUS; case 214: return REPLY_214_HELP_MESSAGE; case 215: return REPLY_215_NAME_SYSTEM_TYPE; case 220: return REPLY_220_SERVICE_READY; case 221: return REPLY_221_CLOSING_CONTROL_CONNECTION; case 225: return REPLY_225_DATA_CONNECTION_OPEN_NO_TRANSFER_IN_PROGRESS; case 226: return REPLY_226_CLOSING_DATA_CONNECTION; case 227: return REPLY_227_ENTERING_PASSIVE_MODE; case 229: return REPLY_229_ENTERING_PASSIVE_MODE; case 230: return REPLY_230_USER_LOGGED_IN; case 232: return REPLY_232_USER_LOGGED_IN; case 234: return REPLY_234_SECURITY_DATA_EXCHANGE_COMPLETE; case 250: return REPLY_250_REQUESTED_FILE_ACTION_OKAY; case 257: return REPLY_257_PATHNAME_CREATED; case 331: return REPLY_331_USER_NAME_OKAY_NEED_PASSWORD; case 332: return REPLY_332_NEED_ACCOUNT_FOR_LOGIN; case 350: return REPLY_350_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFORMATION; case 421: return REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION; case 425: return REPLY_425_CANT_OPEN_DATA_CONNECTION; case 426: return REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED; case 431: return REPLY_431_NEED_UNAVAILABLE_RESOURCE_TO_PROCESS_SECURITY; case 450: return REPLY_450_REQUESTED_FILE_ACTION_NOT_TAKEN; case 451: return REPLY_451_REQUESTED_ACTION_ABORTED; case 452: return REPLY_452_REQUESTED_ACTION_NOT_TAKEN; case 500: return REPLY_500_SYNTAX_ERROR_COMMAND_UNRECOGNIZED; case 501: return REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS; case 502: return REPLY_502_COMMAND_NOT_IMPLEMENTED; case 503: return REPLY_503_BAD_SEQUENCE_OF_COMMANDS; case 504: return REPLY_504_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER; case 522: return REPLY_522_EXTENDED_PORT_FAILURE_UNKNOWN_NETWORK_PROTOCOL; case 530: return REPLY_530_NOT_LOGGED_IN; case 532: return REPLY_532_NEED_ACCOUNT_FOR_STORING_FILES; case 533: return REPLY_533_COMMAND_PROTECTION_LEVEL_DENIED_FOR_POLICY_REASONS; case 534: return REPLY_534_REQUEST_DENIED_FOR_POLICY_REASONS; case 535: return REPLY_535_FAILED_SECURITY_CHECK; case 536: return REPLY_536_REQUESTED_PROT_LEVEL_NOT_SUPPORTED; case 550: return REPLY_550_REQUESTED_ACTION_NOT_TAKEN; case 551: return REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN; case 552: return REPLY_552_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE; case 553: return REPLY_553_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED; default: throw new InvalidArgumentException("Unknown ReplyCode " + code); } } }