📄 nntphandler.java
字号:
void idleClose() { if (getLogger() != null) { getLogger().error("NNTP Connection has idled out."); } try { if (socket != null) { socket.close(); } } catch (Exception e) { // ignored } finally { socket = null; } synchronized (this) { // Interrupt the thread to recover from internal hangs if (handlerThread != null) { handlerThread.interrupt(); handlerThread = null; } } } /** * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket) */ public void handleConnection( Socket connection ) throws IOException { try { this.socket = connection; synchronized (this) { handlerThread = Thread.currentThread(); } remoteIP = socket.getInetAddress().getHostAddress(); remoteHost = socket.getInetAddress().getHostName(); in = new BufferedInputStream(socket.getInputStream(), 1024); // An ASCII encoding can be used because all transmissions other // that those in the message body command are guaranteed // to be ASCII reader = new BufferedReader(new InputStreamReader(in, "ASCII"), 512); outs = new BufferedOutputStream(socket.getOutputStream(), 1024); writer = new InternetPrintWriter(outs, true); } catch (Exception e) { StringBuffer exceptionBuffer = new StringBuffer(256) .append("Cannot open connection from ") .append(remoteHost) .append(" (") .append(remoteIP) .append("): ") .append(e.getMessage()); String exceptionString = exceptionBuffer.toString(); getLogger().error(exceptionString, e ); } try { // section 7.1 if ( theConfigData.getNNTPRepository().isReadOnly() ) { StringBuffer respBuffer = new StringBuffer(128) .append("201 ") .append(theConfigData.getHelloName()) .append(" NNTP Service Ready, posting prohibited"); writeLoggedFlushedResponse(respBuffer.toString()); } else { StringBuffer respBuffer = new StringBuffer(128) .append("200 ") .append(theConfigData.getHelloName()) .append(" NNTP Service Ready, posting permitted"); writeLoggedFlushedResponse(respBuffer.toString()); } theWatchdog.start(); while (parseCommand(reader.readLine())) { theWatchdog.reset(); } theWatchdog.stop(); getLogger().info("Connection closed"); } catch (Exception e) { // If the connection has been idled out, the // socket will be closed and null. Do NOT // log the exception or attempt to send the // closing connection message if (socket != null) { try { doQUIT(null); } catch (Throwable t) {} getLogger().error( "Exception during connection:" + e.getMessage(), e ); } } finally { resetHandler(); } } /** * Resets the handler data to a basic state. */ private void resetHandler() { // Clear the Watchdog if (theWatchdog != null) { if (theWatchdog instanceof Disposable) { ((Disposable)theWatchdog).dispose(); } theWatchdog = null; } // Clear the streams try { if (reader != null) { reader.close(); } } catch (IOException ioe) { getLogger().warn("NNTPHandler: Unexpected exception occurred while closing reader: " + ioe); } finally { reader = null; } in = null; if (writer != null) { writer.close(); writer = null; } outs = null; remoteHost = null; remoteIP = null; try { if (socket != null) { socket.close(); } } catch (IOException ioe) { getLogger().warn("NNTPHandler: Unexpected exception occurred while closing socket: " + ioe); } finally { socket = null; } synchronized (this) { handlerThread = null; } // Clear the selected group, article info group = null; currentArticleNumber = -1; // Clear the authentication info user = null; password = null; isAlreadyAuthenticated = false; // Clear the config data theConfigData = null; } /** * This method parses NNTP commands read off the wire in handleConnection. * Actual processing of the command (possibly including additional back and * forth communication with the client) is delegated to one of a number of * command specific handler methods. The primary purpose of this method is * to parse the raw command string to determine exactly which handler should * be called. It returns true if expecting additional commands, false otherwise. * * @param commandRaw the raw command string passed in over the socket * * @return whether additional commands are expected. */ private boolean parseCommand(String commandRaw) { if (commandRaw == null) { return false; } if (getLogger().isDebugEnabled()) { getLogger().debug("Command received: " + commandRaw); } String command = commandRaw.trim(); String argument = null; int spaceIndex = command.indexOf(" "); if (spaceIndex >= 0) { argument = command.substring(spaceIndex + 1); command = command.substring(0, spaceIndex); } command = command.toUpperCase(Locale.US); boolean returnValue = true; if (!isAuthorized(command) ) { writeLoggedFlushedResponse("480 User is not authenticated"); getLogger().debug("Command not allowed."); return returnValue; } if ((command.equals(COMMAND_MODE)) && (argument != null)) { if (argument.toUpperCase(Locale.US).equals(MODE_TYPE_READER)) { doMODEREADER(argument); } else if (argument.toUpperCase(Locale.US).equals(MODE_TYPE_STREAM)) { doMODESTREAM(argument); } else { writeLoggedFlushedResponse("500 Command not understood"); } } else if ( command.equals(COMMAND_LIST)) { doLIST(argument); } else if ( command.equals(COMMAND_GROUP) ) { doGROUP(argument); } else if ( command.equals(COMMAND_NEXT) ) { doNEXT(argument); } else if ( command.equals(COMMAND_LAST) ) { doLAST(argument); } else if ( command.equals(COMMAND_ARTICLE) ) { doARTICLE(argument); } else if ( command.equals(COMMAND_HEAD) ) { doHEAD(argument); } else if ( command.equals(COMMAND_BODY) ) { doBODY(argument); } else if ( command.equals(COMMAND_STAT) ) { doSTAT(argument); } else if ( command.equals(COMMAND_POST) ) { doPOST(argument); } else if ( command.equals(COMMAND_IHAVE) ) { doIHAVE(argument); } else if ( command.equals(COMMAND_QUIT) ) { doQUIT(argument); returnValue = false; } else if ( command.equals(COMMAND_DATE) ) { doDATE(argument); } else if ( command.equals(COMMAND_HELP) ) { doHELP(argument); } else if ( command.equals(COMMAND_NEWGROUPS) ) { doNEWGROUPS(argument); } else if ( command.equals(COMMAND_NEWNEWS) ) { doNEWNEWS(argument); } else if ( command.equals(COMMAND_LISTGROUP) ) { doLISTGROUP(argument); } else if ( command.equals(COMMAND_OVER) ) { doOVER(argument); } else if ( command.equals(COMMAND_XOVER) ) { doXOVER(argument); } else if ( command.equals(COMMAND_HDR) ) { doHDR(argument); } else if ( command.equals(COMMAND_XHDR) ) { doXHDR(argument); } else if ( command.equals(COMMAND_AUTHINFO) ) { doAUTHINFO(argument); } else if ( command.equals(COMMAND_SLAVE) ) { doSLAVE(argument); } else if ( command.equals(COMMAND_PAT) ) { doPAT(argument); } else { doUnknownCommand(command, argument); } return returnValue; } /** * Handles an unrecognized command, logging that. * * @param command the command received from the client * @param argument the argument passed in with the command */ private void doUnknownCommand(String command, String argument) { if (getLogger().isDebugEnabled()) { StringBuffer logBuffer = new StringBuffer(128) .append("Received unknown command ") .append(command) .append(" with argument ") .append(argument); getLogger().debug(logBuffer.toString()); } writeLoggedFlushedResponse("500 Unknown command"); } /** * Implements only the originnal AUTHINFO. * for simple and generic AUTHINFO, 501 is sent back. This is as * per article 3.1.3 of RFC 2980 * * @param argument the argument passed in with the AUTHINFO command */ private void doAUTHINFO(String argument) { String command = null; String value = null; if (argument != null) { int spaceIndex = argument.indexOf(" "); if (spaceIndex >= 0) { command = argument.substring(0, spaceIndex); value = argument.substring(spaceIndex + 1); } } if (command == null) { writeLoggedFlushedResponse("501 Syntax error"); return; } command = command.toUpperCase(Locale.US); if ( command.equals(AUTHINFO_PARAM_USER) ) { // Reject re-authentication if ( isAlreadyAuthenticated ) { writeLoggedFlushedResponse("482 Already authenticated - rejecting new credentials"); } // Reject doubly sent user if (user != null) { user = null; password = null; isAlreadyAuthenticated = false; writeLoggedFlushedResponse("482 User already specified - rejecting new user"); return; } user = value; writeLoggedFlushedResponse("381 More authentication information required"); } else if ( command.equals(AUTHINFO_PARAM_PASS) ) { // Reject password sent before user if (user == null) { writeLoggedFlushedResponse("482 User not yet specified. Rejecting user."); return; } // Reject doubly sent password if (password != null) { user = null; password = null; isAlreadyAuthenticated = false; writeLoggedFlushedResponse("482 Password already specified - rejecting new password"); return; } password = value; isAlreadyAuthenticated = isAuthenticated(); if ( isAlreadyAuthenticated ) { writeLoggedFlushedResponse("281 Authentication accepted"); } else { writeLoggedFlushedResponse("482 Authentication rejected"); // Clear bad authentication user = null; password = null; } } else { writeLoggedFlushedResponse("501 Syntax error"); return; } } /** * Lists the articles posted since the date passed in as * an argument. * * @param argument the argument passed in with the NEWNEWS command. * Should be a wildmat followed by a date. */ private void doNEWNEWS(String argument) { // see section 11.4 String wildmat = "*"; if (argument != null) { int spaceIndex = argument.indexOf(" ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -