File Source: IdentClient.java
/*
P/P * Method: com.dmdirc.addons.identd.IdentClient__static_init
*/
1 /*
2 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 package com.dmdirc.addons.identd;
24
25 import com.dmdirc.Server;
26 import com.dmdirc.ServerManager;
27 import com.dmdirc.config.ConfigManager;
28 import com.dmdirc.config.IdentityManager;
29 import com.dmdirc.logger.ErrorLevel;
30 import com.dmdirc.logger.Logger;
31
32 import java.io.BufferedReader;
33 import java.io.InputStreamReader;
34 import java.io.IOException;
35 import java.io.PrintWriter;
36 import java.net.Socket;
37
38 /**
39 * The IdentClient responds to an ident request.
40 *
41 * @author Shane "Dataforce" Mc Cormack
42 */
43 public final class IdentClient implements Runnable {
44 /** The IdentdServer that owns this Client. */
45 private final IdentdServer myServer;
46 /** The Socket that we are in charge of. */
47 private final Socket mySocket;
48 /** The Thread in use for this client. */
49 private volatile Thread myThread;
50 /** The plugin that owns us. */
51 private final IdentdPlugin myPlugin;
52
53 /**
54 * Create the IdentClient.
55 *
56 * @param server The server that owns this
57 * @param socket The socket we are handing
58 */
/*
P/P * Method: void com.dmdirc.addons.identd.IdentClient(IdentdServer, Socket, IdentdPlugin)
*
* Postconditions:
* this.myPlugin == plugin
* init'ed(this.myPlugin)
* this.myServer == server
* init'ed(this.myServer)
* this.mySocket == socket
* init'ed(this.mySocket)
* this.myThread == &new Thread(IdentClient#1)
* new Thread(IdentClient#1) num objects == 1
*/
59 public IdentClient(final IdentdServer server, final Socket socket, final IdentdPlugin plugin) {
60 myServer = server;
61 mySocket = socket;
62 myPlugin = plugin;
63
64 myThread = new Thread(this);
65 myThread.start();
66 }
67
68 /**
69 * Process this connection.
70 */
71 @Override
72 public void run() {
/*
P/P * Method: void run()
*
* Preconditions:
* this.myServer != null
* this.myServer.clientList != null
* (soft) this.mySocket != null
* (soft) init'ed(this.myThread)
*
* Presumptions:
* init'ed(com.dmdirc.logger.ErrorLevel.HIGH)
*
* Postconditions:
* com/dmdirc/ServerManager.me == One-of{old com/dmdirc/ServerManager.me, &new ServerManager(getServerManager#1)}
* new ArrayList(ServerManager#1) num objects <= 1
* new ServerManager(getServerManager#1) num objects <= 1
* init'ed(new ServerManager(getServerManager#1).servers)
*/
73 final Thread thisThread = Thread.currentThread();
74 PrintWriter out = null;
75 BufferedReader in = null;
76 try {
77 out = new PrintWriter(mySocket.getOutputStream(), true);
78 in = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
79 final String inputLine;
80 if ((inputLine = in.readLine()) != null) {
81 out.println(getIdentResponse(inputLine, IdentityManager.getGlobalConfig()));
82 }
83 } catch (IOException e) {
84 if (thisThread == myThread) {
85 Logger.userError(ErrorLevel.HIGH ,"ClientSocket Error: "+e.getMessage());
86 }
87 } finally {
88 try {
89 out.close();
90 in.close();
91 mySocket.close();
92 } catch (IOException e) { }
93 }
94 myServer.delClient(this);
95 }
96
97 /**
98 * Get the ident response for a given line.
99 * Complies with rfc1413 (http://www.faqs.org/rfcs/rfc1413.html)
100 *
101 * @param input Line to generate response for
102 * @param config The config manager to use for settings
103 * @return the ident response for the given line
104 */
105 protected String getIdentResponse(final String input, final ConfigManager config) {
/*
P/P * Method: String getIdentResponse(String, ConfigManager)
*
* Preconditions:
* input != null
*
* Postconditions:
* com/dmdirc/ServerManager.me == One-of{old com/dmdirc/ServerManager.me, &new ServerManager(getServerManager#1)}
* init'ed(return_value)
* new ArrayList(ServerManager#1) num objects == 0
* new ServerManager(getServerManager#1) num objects == 0
* init'ed(new ServerManager(getServerManager#1).servers)
*/
106 final String unescapedInput = unescapeString(input);
107 final String[] bits = unescapedInput.replaceAll("\\s+", "").split(",", 2);
108 if (bits.length < 2) {
109 return String.format("%s : ERROR : X-INVALID-INPUT", escapeString(unescapedInput));
110 }
111 final int myPort;
112 final int theirPort;
113 try {
114 myPort = Integer.parseInt(bits[0].trim());
115 theirPort = Integer.parseInt(bits[1].trim());
116 } catch (NumberFormatException e) {
117 return String.format("%s , %s : ERROR : X-INVALID-INPUT", escapeString(bits[0]), escapeString(bits[1]));
118 }
119
120 if (myPort > 65535 || myPort < 1 || theirPort > 65535 || theirPort < 1) {
121 return String.format("%d , %d : ERROR : INVALID-PORT", myPort, theirPort);
122 }
123
124 final Server server = getServerByPort(myPort);
125 if (!config.getOptionBool(myPlugin.getDomain(), "advanced.alwaysOn") && (server == null || config.getOptionBool(myPlugin.getDomain(), "advanced.isNoUser"))) {
126 return String.format("%d , %d : ERROR : NO-USER", myPort, theirPort);
127 }
128
129 if (config.getOptionBool(myPlugin.getDomain(), "advanced.isHiddenUser")) {
130 return String.format("%d , %d : ERROR : HIDDEN-USER", myPort, theirPort);
131 }
132
133 final String osName = System.getProperty("os.name").toLowerCase();
134 final String os;
135 final String username;
136
137 final String customSystem = config.getOption(myPlugin.getDomain(), "advanced.customSystem");
138 if (config.getOptionBool(myPlugin.getDomain(), "advanced.useCustomSystem") && customSystem != null && customSystem.length() > 0 && customSystem.length() < 513) {
139 os = customSystem;
140 } else {
141 // Tad excessive maybe, but complete!
142 // Based on: http://mindprod.com/jgloss/properties.html
143 // and the SYSTEM NAMES section of rfc1340 (http://www.faqs.org/rfcs/rfc1340.html)
144 if (osName.startsWith("windows")) { os = "WIN32"; }
145 else if (osName.startsWith("mac")) { os = "MACOS"; }
146 else if (osName.startsWith("linux")) { os = "UNIX"; }
147 else if (osName.indexOf("bsd") > -1) { os = "UNIX-BSD"; }
148 else if ("os/2".equals(osName)) { os = "OS/2"; }
149 else if (osName.indexOf("unix") > -1) { os = "UNIX"; }
150 else if ("irix".equals(osName)) { os = "IRIX"; }
151 else { os = "UNKNOWN"; }
152 }
153
154 final String customName = config.getOption(myPlugin.getDomain(), "general.customName");
155 if (config.getOptionBool(myPlugin.getDomain(), "general.useCustomName") && customName != null && customName.length() > 0 && customName.length() < 513) {
156 username = customName;
157 } else if (server != null && config.getOptionBool(myPlugin.getDomain(), "general.useNickname")) {
158 username = server.getParser().getMyNickname();
159 } else if (server != null && config.getOptionBool(myPlugin.getDomain(), "general.useUsername")) {
160 username = server.getParser().getMyUsername();
161 } else {
162 username = System.getProperty("user.name");
163 }
164
165 return String.format("%d , %d : USERID : %s : %s", myPort, theirPort, escapeString(os), escapeString(username));
166 }
167
168 /**
169 * Escape special chars.
170 *
171 * @param str String to escape
172 * @return Escaped string.
173 */
174 public static String escapeString(final String str) {
/*
P/P * Method: String escapeString(String)
*
* Preconditions:
* str != null
*
* Postconditions:
* return_value != null
*/
175 return str.replaceAll("\\\\", "\\\\\\\\").replaceAll(":", "\\\\:").replaceAll(",", "\\\\,").replaceAll(" ", "\\\\ ");
176 }
177
178 /**
179 * Unescape special chars.
180 *
181 * @param str String to escape
182 * @return Escaped string.
183 */
184 public static String unescapeString(final String str) {
/*
P/P * Method: String unescapeString(String)
*
* Preconditions:
* str != null
*
* Postconditions:
* return_value != null
*/
185 return str.replaceAll("\\\\:", ":").replaceAll("\\\\ ", " ").replaceAll("\\\\,", ",").replaceAll("\\\\\\\\", "\\\\");
186 }
187
188 /**
189 * Close this IdentClient.
190 */
191 public void close() {
/*
P/P * Method: void close()
*
* Preconditions:
* init'ed(this.myThread)
* (soft) this.mySocket != null
*
* Postconditions:
* this.myThread == null
*
* Test Vectors:
* this.myThread: Addr_Set{null}, Inverse{null}
*/
192 if (myThread != null) {
193 final Thread tmpThread = myThread;
194 myThread = null;
195 if (tmpThread != null) { tmpThread.interrupt(); }
196 try { mySocket.close(); } catch (IOException e) { }
197 }
198 }
199
200 /**
201 * Retrieves the server that is bound to the specified local port.
202 *
203 * @param port Port to check for
204 * @return The server instance listening on the given port
205 */
206 protected static Server getServerByPort(final int port) {
/*
P/P * Method: Server getServerByPort(int)
*
* Preconditions:
* init'ed(com/dmdirc/ServerManager.me)
*
* Presumptions:
* java.util.Iterator:next(...)@207 != null
* server.parser@207 != null
*
* Postconditions:
* com/dmdirc/ServerManager.me == One-of{old com/dmdirc/ServerManager.me, &new ServerManager(getServerManager#1)}
* com/dmdirc/ServerManager.me != null
* init'ed(return_value)
* new ArrayList(ServerManager#1) num objects <= 1
* new ServerManager(getServerManager#1) num objects == new ArrayList(ServerManager#1) num objects
* new ServerManager(getServerManager#1).servers == &new ArrayList(ServerManager#1)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@207: {0}, {1}
*/
207 for (Server server : ServerManager.getServerManager().getServers()) {
208 if (server.getParser().getLocalPort() == port) {
209 return server;
210 }
211 }
212 return null;
213 }
214
215 }
216
SofCheck Inspector Build Version : 2.17854
| IdentClient.java |
2009-Jun-25 01:54:24 |
| IdentClient.class |
2009-Sep-02 17:04:15 |