📄 nntpconnection.java
字号:
public boolean modeReader() throws IOException { send(MODE_READER); StatusResponse response = parseResponse(read()); switch (response.status) { case POSTING_ALLOWED: canPost = true; return canPost; case POSTING_NOT_ALLOWED: canPost = false; return canPost; default: throw new NNTPException(response); } } // RFC2980:2.4 The XGTITLE command /** * Returns an iterator over the list of newsgroup descriptions. * @param wildmat if non-null, the newsgroups to match */ public PairIterator xgtitle(String wildmat) throws IOException { StringBuffer buffer = new StringBuffer(XGTITLE); if (wildmat != null) { buffer.append(' '); buffer.append(wildmat); } send(buffer.toString()); StatusResponse response = parseResponse(read()); switch (response.status) { case XGTITLE_LIST_FOLLOWS: PairIterator pi = new PairIterator(this); pendingData = pi; return pi; default: throw new NNTPException(response); } } // RFC2980:2.6 The XHDR command public HeaderIterator xhdr(String header, String range) throws IOException { StringBuffer buffer = new StringBuffer(XHDR); buffer.append(' '); buffer.append(header); if (range != null) { buffer.append(' '); buffer.append(range); } send(buffer.toString()); StatusResponse response = parseResponse(read()); switch (response.status) { case HEAD_FOLLOWS: HeaderIterator hi = new HeaderIterator(this); pendingData = hi; return hi; default: // NO_GROUP_SELECTED // NO_SUCH_ARTICLE throw new NNTPException(response); } } // RFC2980:2.7 The XINDEX command // TODO // RFC2980:2.8 The XOVER command public OverviewIterator xover(Range range) throws IOException { StringBuffer buffer = new StringBuffer(XOVER); if (range != null) { buffer.append(' '); buffer.append(range.toString()); } send(buffer.toString()); StatusResponse response = parseResponse(read()); switch (response.status) { case OVERVIEW_FOLLOWS: OverviewIterator oi = new OverviewIterator(this); pendingData = oi; return oi; default: // NO_GROUP_SELECTED // PERMISSION_DENIED throw new NNTPException(response); } } // RFC2980:2.9 The XPAT command // TODO // RFC2980:2.10 The XPATH command // TODO // RFC2980:2.11 The XROVER command // TODO // RFC2980:2.12 The XTHREAD command // TODO // RFC2980:3.1.1 Original AUTHINFO /** * Basic authentication strategy. * @param username the user to authenticate * @param password the(cleartext) password * @return true on success, false on failure */ public boolean authinfo(String username, String password) throws IOException { StringBuffer buffer = new StringBuffer(AUTHINFO_USER); buffer.append(' '); buffer.append(username); send(buffer.toString()); StatusResponse response = parseResponse(read()); switch (response.status) { case AUTHINFO_OK: return true; case SEND_AUTHINFOPASS: buffer.setLength(0); buffer.append(AUTHINFO_PASS); buffer.append(' '); buffer.append(password); send(buffer.toString()); response = parseResponse(read()); switch (response.status) { case AUTHINFO_OK: return true; case PERMISSION_DENIED: return false; default: throw new NNTPException(response); } default: // AUTHINFO_REJECTED throw new NNTPException(response); } } // RFC2980:3.1.2 AUTHINFO SIMPLE /** * Implementation of NNTP simple authentication. * Note that use of this authentication strategy is highly deprecated, * only use on servers that won't accept any other form of authentication. */ public boolean authinfoSimple(String username, String password) throws IOException { send(AUTHINFO_SIMPLE); StatusResponse response = parseResponse(read()); switch (response.status) { case SEND_AUTHINFO_SIMPLE: StringBuffer buffer = new StringBuffer(username); buffer.append(' '); buffer.append(password); send(buffer.toString()); response = parseResponse(read()); switch (response.status) { case AUTHINFO_SIMPLE_OK: return true; case AUTHINFO_SIMPLE_DENIED: return false; default:throw new NNTPException(response); } default: throw new NNTPException(response); } } // RFC2980:3.1.3 AUTHINFO GENERIC /** * Authenticates the connection using the specified SASL mechanism, * username and password. * @param mechanism a SASL authentication mechanism, e.g. LOGIN, PLAIN, * CRAM-MD5, GSSAPI * @param username the authentication principal * @param password the authentication credentials */ public boolean authinfoGeneric(String mechanism, String username, String password) throws IOException { String[] m = new String[] { mechanism }; CallbackHandler ch = new SaslCallbackHandler(username, password); // Avoid lengthy callback procedure for GNU Crypto HashMap p = new HashMap(); p.put("gnu.crypto.sasl.username", username); p.put("gnu.crypto.sasl.password", password); SaslClient sasl = Sasl.createSaslClient(m, null, "smtp", socket.getInetAddress().getHostName(), p, ch); if (sasl == null) { return false; } StringBuffer cmd = new StringBuffer(AUTHINFO_GENERIC); cmd.append(' '); cmd.append(mechanism); if (sasl.hasInitialResponse()) { cmd.append(' '); byte[] init = sasl.evaluateChallenge(new byte[0]); cmd.append(new String(init, "US-ASCII")); } send(cmd.toString()); StatusResponse response = parseResponse(read()); switch (response.status) { case AUTHINFO_OK: String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP); if ("auth-int".equalsIgnoreCase(qop) || "auth-conf".equalsIgnoreCase(qop)) { InputStream in = socket.getInputStream(); in = new BufferedInputStream(in); in = new SaslInputStream(sasl, in); in = new CRLFInputStream(in); this.in = new LineInputStream(in); OutputStream out = socket.getOutputStream(); out = new BufferedOutputStream(out); out = new SaslOutputStream(sasl, out); this.out = new CRLFOutputStream(out); } return true; case PERMISSION_DENIED: return false; case COMMAND_NOT_RECOGNIZED: case SYNTAX_ERROR: case INTERNAL_ERROR: default: throw new NNTPException(response); // FIXME how does the server send continuations? } } // RFC2980:3.2 The DATE command /** * Returns the date on the server. */ public Date date() throws IOException { send(DATE); StatusResponse response = parseResponse(read()); switch (response.status) { case DATE_OK: String message = response.getMessage(); try { DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); return df.parse(message); } catch (ParseException e) { throw new IOException("Invalid date: " + message); } default: throw new NNTPException(response); } } // -- Utility functions -- /** * Parse a response object from a response line sent by the server. */ protected StatusResponse parseResponse(String line) throws ProtocolException { return parseResponse(line, false); } /** * Parse a response object from a response line sent by the server. * @param isListGroup whether we are invoking the LISTGROUP command */ protected StatusResponse parseResponse(String line, boolean isListGroup) throws ProtocolException { if (line == null) { throw new ProtocolException(hostname + " closed connection"); } int start = 0, end; short status = -1; String statusText = line; String message = null; end = line.indexOf(' ', start); if (end > start) { statusText = line.substring(start, end); message = line.substring(end + 1); } try { status = Short.parseShort(statusText); } catch (NumberFormatException e) { throw new ProtocolException(line); } StatusResponse response; switch (status) { case ARTICLE_FOLLOWS: case HEAD_FOLLOWS: case BODY_FOLLOWS: case ARTICLE_RETRIEVED: case GROUP_SELECTED: /* The LISTGROUP command returns a list of articles with a 211, * instead of the newsgroup totals returned with the GROUP command. * Check for this case. */ if (status != GROUP_SELECTED || isListGroup) { try { ArticleResponse aresponse = new ArticleResponse(status, message); // article number start = end + 1; end = line.indexOf(' ', start); if (end > start) { aresponse.articleNumber = Integer.parseInt(line.substring(start, end)); } // message-id start = end + 1; end = line.indexOf(' ', start); if (end > start) { aresponse.messageId = line.substring(start, end); } else { aresponse.messageId = line.substring(start); } response = aresponse; } catch (NumberFormatException e) { // This will happen for XHDR response = new StatusResponse(status, message); } break; } // This is the normal case for GROUP_SELECTED GroupResponse gresponse = new GroupResponse(status, message); try { // count start = end + 1; end = line.indexOf(' ', start); if (end > start) { gresponse.count = Integer.parseInt(line.substring(start, end)); } // first start = end + 1; end = line.indexOf(' ', start); if (end > start) { gresponse.first = Integer.parseInt(line.substring(start, end)); } // last start = end + 1; end = line.indexOf(' ', start); if (end > start) { gresponse.last = Integer.parseInt(line.substring(start, end)); } // group start = end + 1; end = line.indexOf(' ', start); if (end > start) { gresponse.group = line.substring(start, end); } else { gresponse.group = line.substring(start); } } catch (NumberFormatException e) { throw new ProtocolException(line); } response = gresponse; break; default: response = new StatusResponse(status, message); } return response; } /** * Send a single line to the server. * @param line the line to send */ protected void send(String line) throws IOException { if (pendingData != null) { // Clear pending data pendingData.readToEOF(); pendingData = null; } logger.log(NNTP_TRACE, ">" + line); byte[] data = line.getBytes(US_ASCII); out.write(data); out.writeln(); out.flush(); } /** * Read a single line from the server. * @return a line of text */ protected String read() throws IOException { String line = in.readLine(); if (line == null) { logger.log(NNTP_TRACE, "<EOF"); } else { logger.log(NNTP_TRACE, "<" + line); } return line; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -