File Source: ChannelInfo.java
/*
P/P * Method: com.dmdirc.parser.irc.ChannelInfo__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.parser.irc;
24
25 import java.util.ArrayList;
26 import java.util.Hashtable;
27 import java.util.HashMap;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Queue;
32
33 /**
34 * Contains Channel information.
35 *
36 * @author Shane Mc Cormack
37 * @author Chris Smith
38 * @see IRCParser
39 */
40 public class ChannelInfo {
41 /**
42 * Boolean repreenting the status of names requests.
43 * When this is false, any new names reply will cause current known channelclients to be removed.
44 */
45 private boolean bAddingNames = true;
46
47 /** Unixtimestamp representing time when the channel was created. */
48 private long nCreateTime = 0;
49
50 /** Current known topic in the channel. */
51 private String sTopic = "";
52 /** Last known user to set the topic (Full host where possible). */
53 private String sTopicUser = "";
54 /** Unixtimestamp representing time when the topic was set. */
55 private long nTopicTime = 0;
56
57 /** Known boolean-modes for channel. */
58 private long nModes;
59 /** Reference to the parser object that owns this channel, Used for modes. */
60 private final IRCParser myParser; // Reference to parser object that owns this channel. Used for Modes
61
62 /** Channel Name. */
63 private final String sName;
64
65 /** Hashtable containing references to ChannelClients. */
66 private final Map<String, ChannelClientInfo> hChannelUserList = new Hashtable<String, ChannelClientInfo>();
67 /** Hashtable storing values for modes set in the channel that use parameters. */
68 private final Map<Character, String> hParamModes = new Hashtable<Character, String>();
69 /** Hashtable storing list modes. */
70 private final Map<Character, ArrayList<ChannelListModeItem>> hListModes = new Hashtable<Character, ArrayList<ChannelListModeItem>>();
71 /**
72 * LinkedList storing status of mode adding.
73 * if an item is in this list for a mode, we are expecting new items for the list
74 */
75 private final List<Character> lAddingModes = new LinkedList<Character>();
76 /** Modes waiting to be sent to the server. */
77 private final List<String> lModeQueue = new LinkedList<String>();
78 /** A Map to allow applications to attach misc data to this object */
79 private Map myMap;
80
81 /** Queue of requested list modes */
82 private final Queue<Character> listModeQueue = new LinkedList<Character>();
83 /** Listmode Queue Time */
84 private long listModeQueueTime = System.currentTimeMillis();
85 /** Have we asked the server for the list modes for this channel yet? */
86 private boolean askedForListModes = false;
87 /** Has OnChannelGotListModes ever been called for this channel? */
88 private boolean hasGotListModes = false;
89
90 /**
91 * Create a new channel object.
92 *
93 * @param tParser Refernce to parser that owns this channelclient (used for modes)
94 * @param name Channel name.
95 */
/*
P/P * Method: void com.dmdirc.parser.irc.ChannelInfo(IRCParser, String)
*
* Postconditions:
* this.askedForListModes == 0
* this.hasGotListModes == 0
* this.nCreateTime == 0
* this.nTopicTime == 0
* this.bAddingNames == 1
* new HashMap(ChannelInfo#7) num objects == 1
* new Hashtable(ChannelInfo#1) num objects == 1
* new Hashtable(ChannelInfo#2) num objects == 1
* new Hashtable(ChannelInfo#3) num objects == 1
* new LinkedList(ChannelInfo#4) num objects == 1
* ...
*/
96 public ChannelInfo(final IRCParser tParser, final String name) {
97 myMap = new HashMap<Object, Object>();
98 myParser = tParser;
99 sName = name;
100 }
101
102 /**
103 * Get the listModeQueue.
104 *
105 * @return The listModeQueue
106 */
107 public Queue<Character> getListModeQueue() {
/*
P/P * Method: Queue getListModeQueue()
*
* Preconditions:
* init'ed(this.listModeQueueTime)
* (soft) this.myParser != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
*
* Postconditions:
* return_value == One-of{this.listModeQueue, &new LinkedList(getListModeQueue#1)}
* init'ed(return_value)
* init'ed(this.listModeQueueTime)
* new LinkedList(getListModeQueue#1) num objects <= 1
*/
108 Queue<Character> result = listModeQueue;
109 final long now = System.currentTimeMillis();
110 // Incase of breakage, if getListModeQueue() was last called greater than
111 // 60 seconds ago, we reset the list.
112 if (now-(30*1000) > listModeQueueTime) {
113 result = new LinkedList<Character>();
114 myParser.callDebugInfo(IRCParser.DEBUG_LMQ, "Resetting LMQ");
115 }
116 listModeQueueTime = now;
117 return result;
118 }
119
120 /**
121 * Ask the server for all the list modes for this channel.
122 */
123 public void requestListModes() {
/*
P/P * Method: void requestListModes()
*
* Preconditions:
* this.hChannelUserList != null
* this.myParser != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.h005Info != null
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.hPrefixModes != null
* (soft) this.myParser.myCallbackManager != null
* ...
*
* Presumptions:
* java.util.Iterator:next(...)@159 != null
* java.util.Map:get(...)@141 != null
* java.util.Map:get(...)@160 != null
* java.util.Map:keySet(...)@159 != null
* me.myParser@124 != null
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.askedForListModes)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* init'ed(this.myParser.stringConverter)
* init'ed(new IRCStringConverter(getIRCStringConverter#1) num objects)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* init'ed(new char[](IRCStringConverter#1) num objects)
* ...
*
* Test Vectors:
* java.lang.Byte:byteValue(...)@160: {-128..0, 2..255}, {1}
* java.lang.Character:charValue(...)@162: {101}, {0..100, 102..216-1}
* java.lang.Character:charValue(...)@162: {0..72, 74..216-1}, {73}
* java.lang.Character:charValue(...)@165: {0..71, 73..216-1}, {72}
* java.lang.String:equals(...)@134: {1}, {0}
* java.lang.String:equals(...)@135: {0}, {1}
* java.lang.String:equals(...)@137: {0}, {1}
* java.util.Iterator:hasNext(...)@159: {0}, {1}
* java.util.Map:containsKey(...)@155: {1}, {0}
* java.util.Map:get(...)@141: Addr_Set{null}, Inverse{null}
*/
124 final ChannelClientInfo me = getUser(myParser.getMyself());
125 if (me == null) {
126 // In a normal situation of non bouncer-brokenness this won't happen
127 return;
128 }
129
130 askedForListModes = true;
131
132 final String thisIRCD = myParser.getIRCD(true).toLowerCase();
133 final boolean isFreenode = (thisIRCD.equals("hyperion") || thisIRCD.equals("dancer"));
134 final boolean isUnreal = thisIRCD.equals("unreal");
135 final boolean isStarChat = thisIRCD.equals("starchat");
136 final boolean isHybrid = thisIRCD.equals("hybrid") || thisIRCD.equals("oftc-hybrid");
137 final boolean isCharybdis = thisIRCD.equals("charybdis");
138
139 // We are considered opped if we have a mode higher than voice (or if we have any modes if voice doesn't exist)
140 long voiceValue = 0;
141 if (myParser.hPrefixModes.get('v') != null) { voiceValue = myParser.hPrefixModes.get('v');}
142 final boolean isOpped = me.getImportantModeValue() > voiceValue;
143
144 int modecount = 1;
145 if (!isUnreal) {
146 try {
147 modecount = Integer.parseInt(myParser.h005Info.get("MODES"));
148 } catch (NumberFormatException e) { /* use default modecount */}
149 }
150
151 // Support for potential future decent mode listing in the protocol
152 //
153 // See my proposal: http://shane.dmdirc.com/listmodes.php
154 // Add listmode handler
155 final boolean supportLISTMODE = myParser.h005Info.containsKey("LISTMODE");
156
157 String listmodes = "";
158 int i = 0;
159 for (Character cTemp : myParser.hChanModesOther.keySet()) {
160 final int nTemp = myParser.hChanModesOther.get(cTemp);
161 if (nTemp == IRCParser.MODE_LIST) {
162 if ((isFreenode || isHybrid || isCharybdis) && (cTemp == 'e' || cTemp == 'I') && !isOpped) {
163 // IRCD doesn't allow non-ops to ask for these modes.
164 continue;
165 } else if (isStarChat && cTemp == 'H') {
166 // IRCD Denies the mode exists
167 continue;
168 }
169 i++;
170 listmodes = listmodes + cTemp;
171 if (i >= modecount && !supportLISTMODE) {
172 myParser.sendString("MODE "+getName()+" "+listmodes);
173 i = 0;
174 listmodes = "";
175 }
176 }
177 }
178 if (i > 0) {
179 if (supportLISTMODE) {
180 myParser.sendString("LISTMODE "+getName()+" "+listmodes);
181 } else {
182 myParser.sendString("MODE "+getName()+" "+listmodes);
183 }
184 }
185 }
186
187 /**
188 * Have we ever asked the server for this channels listmodes?
189 *
190 * @return True if requestListModes() has ever been used, else false
191 */
192 public boolean hasAskedForListModes() {
/*
P/P * Method: bool hasAskedForListModes()
*
* Preconditions:
* init'ed(this.askedForListModes)
*
* Postconditions:
* return_value == this.askedForListModes
* init'ed(return_value)
*/
193 return askedForListModes;
194 }
195
196 /**
197 * Returns true if OnChannelGotListModes ever been called for this channel.
198 *
199 * @return True if OnChannelGotListModes ever been called for this channel.
200 */
201 public boolean hasGotListModes() {
/*
P/P * Method: bool hasGotListModes()
*
* Preconditions:
* init'ed(this.hasGotListModes)
*
* Postconditions:
* return_value == this.hasGotListModes
* init'ed(return_value)
*/
202 return hasGotListModes;
203 }
204
205 /**
206 * Set if OnChannelGotListModes ever been called for this channel.
207 *
208 * @param newValue new value for if OnChannelGotListModes ever been called for this channel.
209 */
210 protected void setHasGotListModes(final boolean newValue) {
/*
P/P * Method: void setHasGotListModes(bool)
*
* Postconditions:
* this.hasGotListModes == newValue
* init'ed(this.hasGotListModes)
*/
211 hasGotListModes = newValue;
212 }
213
214 /**
215 * Set the Map object attatched to this object.
216 *
217 * @param newMap New Map to attatch.
218 */
219 public void setMap(final Map newMap) {
/*
P/P * Method: void setMap(Map)
*
* Postconditions:
* this.myMap == newMap
* init'ed(this.myMap)
*/
220 myMap = newMap;
221 }
222
223 /**
224 * Get the Map object attatched to this object.
225 *
226 * @return Map to attatched to this.
227 */
228 public Map getMap() {
/*
P/P * Method: Map getMap()
*
* Preconditions:
* init'ed(this.myMap)
*
* Postconditions:
* return_value == this.myMap
* init'ed(return_value)
*/
229 return myMap;
230 }
231
232 /**
233 * Set if we are getting a names request or not.
234 *
235 * @param newValue if false, any new names reply will cause current known channelclients to be removed.
236 */
/*
P/P * Method: void setAddingNames(bool)
*
* Postconditions:
* this.bAddingNames == newValue
* init'ed(this.bAddingNames)
*/
237 public void setAddingNames(final boolean newValue) { bAddingNames = newValue; }
238
239 /**
240 * Get if we are getting a names request or not.
241 *
242 * @return if false, any new names reply will cause current known channelclients to be removed.
243 */
/*
P/P * Method: bool isAddingNames()
*
* Preconditions:
* init'ed(this.bAddingNames)
*
* Postconditions:
* return_value == this.bAddingNames
* init'ed(return_value)
*/
244 public boolean isAddingNames() { return bAddingNames; }
245
246 /**
247 * Get the name of this channel object.
248 *
249 * @return Channel name.
250 */
/*
P/P * Method: String getName()
*
* Postconditions:
* return_value == this.sName
* init'ed(return_value)
*/
251 public String getName() { return sName; }
252 /**
253 * Get the number of users known on this channel.
254 *
255 * @return Channel user count.
256 */
/*
P/P * Method: int getUserCount()
*
* Preconditions:
* this.hChannelUserList != null
*
* Postconditions:
* init'ed(return_value)
*/
257 public int getUserCount() { return hChannelUserList.size(); }
258
259 /**
260 * Get the channel users.
261 *
262 * @return ArrayList of ChannelClients
263 */
264 public List<ChannelClientInfo> getChannelClients() {
/*
P/P * Method: List getChannelClients()
*
* Preconditions:
* this.hChannelUserList != null
*
* Postconditions:
* return_value == &new ArrayList(getChannelClients#1)
* new ArrayList(getChannelClients#1) num objects == 1
*/
265 return new ArrayList<ChannelClientInfo>(hChannelUserList.values());
266 }
267
268 /**
269 * Empty the channel (Remove all known channelclients).
270 */
271 protected void emptyChannel() {
/*
P/P * Method: void emptyChannel()
*
* Preconditions:
* this.hChannelUserList != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) init'ed(this.myParser.cMyself)
* (soft) this.myParser.hClientList != null
* (soft) this.myParser.stringConverter.lowercase != null
* (soft) init'ed(this.myParser.stringConverter.lowercase[...])
*
* Presumptions:
* cTemp.myChannelClientInfos@273 != null
* cTemp.myParser.stringConverter.lowercase@273 != null
* cTemp.myParser@273 != null
* cTemp.sNickname != null
* client.cClient@273 != null
* ...
*
* Postconditions:
* init'ed(this.myParser.stringConverter)
* init'ed(new IRCStringConverter(getIRCStringConverter#1) num objects)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* init'ed(new char[](IRCStringConverter#1) num objects)
* init'ed(new char[](IRCStringConverter#1).length)
* init'ed(new char[](IRCStringConverter#1)[...])
* init'ed(new char[](IRCStringConverter#2) num objects)
* init'ed(new char[](IRCStringConverter#2).length)
* ...
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@273: {0}, {1}
*/
272 ClientInfo cTemp = null;
273 for (ChannelClientInfo client : hChannelUserList.values()) {
274 cTemp = client.getClient();
275 cTemp.delChannelClientInfo(client);
276 if (cTemp != myParser.getMyself() && !cTemp.checkVisibility()) {
277 myParser.removeClient(cTemp);
278 }
279 }
280 hChannelUserList.clear();
281 }
282
283 /**
284 * Get the ChannelClientInfo object associated with a nickname.
285 *
286 * @param sWho Nickname to return channelclient for
287 * @return ChannelClientInfo object requested, or null if not found
288 */
289 public ChannelClientInfo getUser(final String sWho) {
/*
P/P * Method: ChannelClientInfo getUser(String)
*
* Preconditions:
* init'ed(this.myParser.stringConverter)
* sWho != null
* this.hChannelUserList != null
* this.myParser != null
* (soft) this.myParser.stringConverter.lowercase != null
* (soft) init'ed(this.myParser.stringConverter.lowercase[...])
* (soft) this.sName != null
*
* Postconditions:
* init'ed(return_value)
* this.myParser.stringConverter != null
* new ChannelClientInfo(getUser#1*) num objects == 0
* new ClientInfo(getUser#2*) num objects == 0
* new HashMap(ChannelClientInfo#1) num objects == 0
* new HashMap(ClientInfo#3) num objects == 0
* new Hashtable(ClientInfo#1) num objects == 0
* new LinkedList(ClientInfo#2) num objects == 0
* not_init'ed(new ChannelClientInfo(getUser#1*).cClient)
* not_init'ed(new ChannelClientInfo(getUser#1*).myChannel)
* ...
*/
290 return getUser(sWho, false);
291 }
292
293 /**
294 * Get the ChannelClientInfo object associated with a nickname.
295 *
296 * @param sWho Nickname to return channelclient for
297 * @param createFake Create a fake client if not found
298 * @return ChannelClientInfo object requested
299 * @since 0.6
300 */
301 public ChannelClientInfo getUser(final String sWho, final boolean createFake) {
/*
P/P * Method: ChannelClientInfo getUser(String, bool)
*
* Preconditions:
* init'ed(this.myParser.stringConverter)
* sWho != null
* this.hChannelUserList != null
* this.myParser != null
* (soft) this.myParser.stringConverter.lowercase != null
* (soft) init'ed(this.myParser.stringConverter.lowercase[...])
* (soft) this.sName != null
*
* Presumptions:
* setFake(...).myParser.stringConverter.lowercase != null
*
* Postconditions:
* init'ed(return_value)
* this.myParser.stringConverter != null
* new ChannelClientInfo(getUser#1) num objects <= 1
* new ChannelClientInfo(getUser#1).cClient == &new ClientInfo(getUser#2)
* new ChannelClientInfo(getUser#1).myChannel == this
* new ChannelClientInfo(getUser#1).myChannel != null
* new ChannelClientInfo(getUser#1).myMap == &new HashMap(ChannelClientInfo#1)
* new ChannelClientInfo(getUser#1).myParser == this.myParser
* new ChannelClientInfo(getUser#1).myParser != null
* new ClientInfo(getUser#2) num objects <= 1
* ...
*
* Test Vectors:
* createFake: {0}, {1}
* java.util.Map:containsKey(...)@303: {0}, {1}
*/
302 final String who = myParser.getIRCStringConverter().toLowerCase(ClientInfo.parseHost(sWho));
303 if (hChannelUserList.containsKey(who)) {
304 return hChannelUserList.get(who);
305 }
306 if (createFake) {
307 return new ChannelClientInfo(myParser, (new ClientInfo(myParser, sWho)).setFake(true), this);
308 } else {
309 return null;
310 }
311 }
312
313 /**
314 * Get the ChannelClientInfo object associated with a ClientInfo object.
315 *
316 * @param cWho ClientInfo to return ChannelClient for
317 * @return ChannelClientInfo object requested, or null if not found
318 */
319 public ChannelClientInfo getUser(final ClientInfo cWho) {
/*
P/P * Method: ChannelClientInfo getUser(ClientInfo)
*
* Preconditions:
* this.hChannelUserList != null
*
* Presumptions:
* java.util.Iterator:next(...)@320 != null
* java.util.Map:values(...)@320 != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@320: {0}, {1}
*/
320 for (ChannelClientInfo client : hChannelUserList.values()) {
321 if (client.getClient() == cWho) {
322 return client;
323 }
324 }
325 return null;
326 }
327
328 /**
329 * Get the ChannelClientInfo object associated with a ClientInfo object.
330 *
331 * @param cClient Client object to be added to channel
332 * @return ChannelClientInfo object added, or an existing object if already known on channel
333 */
334 protected ChannelClientInfo addClient(final ClientInfo cClient) {
/*
P/P * Method: ChannelClientInfo addClient(ClientInfo)
*
* Preconditions:
* (soft) cClient != null
* (soft) cClient.myChannelClientInfos != null
* (soft) cClient.myParser != null
* (soft) init'ed(cClient.myParser.stringConverter)
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.hChannelUserList != null
* (soft) this.myParser != null
* (soft) this.sName != null
*
* Presumptions:
* cClient.myParser.stringConverter.lowercase@335 != null
* cTemp.cClient.sNickname != null
* getIRCStringConverter(...).lowercase != null
*
* Postconditions:
* cClient.myParser.stringConverter == One-of{old cClient.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1), old this.myParser.stringConverter}
* init'ed(cClient.myParser.stringConverter)
* return_value != null
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, old cClient.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new ChannelClientInfo(addClient#1) num objects <= 1
* new ChannelClientInfo(addClient#1).cClient == cClient
* new ChannelClientInfo(addClient#1).cClient != null
* new ChannelClientInfo(addClient#1).myChannel == this
* new ChannelClientInfo(addClient#1).myChannel != null
* ...
*/
335 ChannelClientInfo cTemp = getUser(cClient);
336 if (cTemp == null) {
337 cTemp = new ChannelClientInfo(myParser, cClient, this);
338 hChannelUserList.put(myParser.getIRCStringConverter().toLowerCase(cTemp.getNickname()), cTemp);
339 }
340 return cTemp;
341 }
342
343 /**
344 * Remove ChannelClientInfo object associated with a ClientInfo object.
345 *
346 * @param cClient Client object to be removed from channel
347 */
348 protected void delClient(final ClientInfo cClient) {
/*
P/P * Method: void delClient(ClientInfo)
*
* Preconditions:
* this.hChannelUserList != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) init'ed(this.myParser.cMyself)
* (soft) this.myParser.hClientList != null
*
* Presumptions:
* cTemp.cClient.sNickname != null
* cTemp.myChannel.sName@350 != null
* cTemp.myChannel@350 != null
* clTemp.myChannelClientInfos@350 != null
* clTemp.myParser.stringConverter.lowercase@350 != null
* ...
*
* Postconditions:
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* possibly_updated(new char[](IRCStringConverter#1)[...])
* init'ed(new char[](IRCStringConverter#1)[...])
* new char[](IRCStringConverter#2) num objects <= 1
* ...
*/
349 ChannelClientInfo cTemp = null;
350 cTemp = getUser(cClient);
351 if (cTemp != null) {
352 final ClientInfo clTemp = cTemp.getClient();
353 clTemp.delChannelClientInfo(cTemp);
354 if (clTemp != myParser.getMyself() && !clTemp.checkVisibility()) {
355 myParser.removeClient(clTemp);
356 }
357 hChannelUserList.remove(myParser.getIRCStringConverter().toLowerCase(cTemp.getNickname()));
358 }
359 }
360
361 /**
362 * Rename a channelClient.
363 *
364 * @param oldNickname Nickname client used to be known as
365 * @param cChannelClient ChannelClient object with updated client object
366 */
367 protected void renameClient(final String oldNickname, final ChannelClientInfo cChannelClient) {
/*
P/P * Method: void renameClient(String, ChannelClientInfo)
*
* Preconditions:
* this.hChannelUserList != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) this.myParser.stringConverter.lowercase != null
* (soft) init'ed(this.myParser.stringConverter.lowercase[...])
*
* Presumptions:
* cTemp.cClient.sNickname@370 != null
* cTemp.cClient@370 != null
* java.util.Map:get(...)@370 != null
*
* Postconditions:
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* new IRCStringConverter(getIRCStringConverter#1).limit == 4
* new IRCStringConverter(getIRCStringConverter#1).lowercase == &new char[](IRCStringConverter#1)
* new IRCStringConverter(getIRCStringConverter#1).uppercase == &new char[](IRCStringConverter#2)
* new char[](IRCStringConverter#1) num objects <= 1
* new char[](IRCStringConverter#1).length == 127
* possibly_updated(new char[](IRCStringConverter#1)[...])
* new char[](IRCStringConverter#2) num objects <= 1
* ...
*
* Test Vectors:
* java.util.Map:containsKey(...)@369: {0}, {1}
*/
368 ChannelClientInfo cTemp = null;
369 if (hChannelUserList.containsKey(oldNickname)) {
370 cTemp = hChannelUserList.get(oldNickname);
371 if (cTemp == cChannelClient) {
372 // Remove the old key
373 hChannelUserList.remove(oldNickname);
374 // Add with the new key. (getNickname will return the new name not the
375 // old one)
376 hChannelUserList.put(myParser.getIRCStringConverter().toLowerCase(cTemp.getNickname()), cTemp);
377 }
378 }
379 }
380
381 /**
382 * Set the create time.
383 *
384 * @param nNewTime New unixtimestamp time for the channel creation (Seconds since epoch, not milliseconds)
385 */
/*
P/P * Method: void setCreateTime(long)
*
* Postconditions:
* this.nCreateTime == nNewTime
* init'ed(this.nCreateTime)
*/
386 protected void setCreateTime(final long nNewTime) { nCreateTime = nNewTime; }
387 /**
388 * Get the Create time.
389 *
390 * @return Unixtimestamp time for the channel creation (Seconds since epoch, not milliseconds)
391 */
/*
P/P * Method: long getCreateTime()
*
* Preconditions:
* init'ed(this.nCreateTime)
*
* Postconditions:
* return_value == this.nCreateTime
* init'ed(return_value)
*/
392 public long getCreateTime() { return nCreateTime; }
393
394 /**
395 * Set the topic time.
396 *
397 * @param nNewTime New unixtimestamp time for the topic (Seconds since epoch, not milliseconds)
398 */
/*
P/P * Method: void setTopicTime(long)
*
* Postconditions:
* this.nTopicTime == nNewTime
* init'ed(this.nTopicTime)
*/
399 protected void setTopicTime(final long nNewTime) { nTopicTime = nNewTime; }
400 /**
401 * Get the topic time.
402 *
403 * @return Unixtimestamp time for the topic (Seconds since epoch, not milliseconds)
404 */
/*
P/P * Method: long getTopicTime()
*
* Preconditions:
* init'ed(this.nTopicTime)
*
* Postconditions:
* return_value == this.nTopicTime
* init'ed(return_value)
*/
405 public long getTopicTime() { return nTopicTime; }
406
407 /**
408 * Set the topic.
409 *
410 * @param sNewTopic New contents of topic
411 */
/*
P/P * Method: void setTopic(String)
*
* Postconditions:
* this.sTopic == sNewTopic
* init'ed(this.sTopic)
*/
412 protected void setTopic(final String sNewTopic) { sTopic = sNewTopic; }
413 /**
414 * Get the topic.
415 *
416 * @return contents of topic
417 */
/*
P/P * Method: String getTopic()
*
* Preconditions:
* init'ed(this.sTopic)
*
* Postconditions:
* return_value == this.sTopic
* init'ed(return_value)
*/
418 public String getTopic() { return sTopic; }
419
420 /**
421 * Set the topic creator.
422 *
423 * @param sNewUser New user who set the topic (nickname if gotten on connect, full host if seen by parser)
424 */
/*
P/P * Method: void setTopicUser(String)
*
* Postconditions:
* this.sTopicUser == sNewUser
* init'ed(this.sTopicUser)
*/
425 protected void setTopicUser(final String sNewUser) { sTopicUser = sNewUser; }
426 /**
427 * Get the topic creator.
428 *
429 * @return user who set the topic (nickname if gotten on connect, full host if seen by parser)
430 */
/*
P/P * Method: String getTopicUser()
*
* Preconditions:
* init'ed(this.sTopicUser)
*
* Postconditions:
* return_value == this.sTopicUser
* init'ed(return_value)
*/
431 public String getTopicUser() { return sTopicUser; }
432
433 /**
434 * Set the channel modes (as an integer).
435 *
436 * @param nNewMode new long representing channel modes. (Boolean only)
437 */
/*
P/P * Method: void setMode(long)
*
* Postconditions:
* this.nModes == nNewMode
* init'ed(this.nModes)
*/
438 protected void setMode(final long nNewMode) { nModes = nNewMode; }
439 /**
440 * Get the channel modes (as an integer).
441 *
442 * @return long representing channel modes. (Boolean only)
443 */
/*
P/P * Method: long getMode()
*
* Preconditions:
* init'ed(this.nModes)
*
* Postconditions:
* return_value == this.nModes
* init'ed(return_value)
*/
444 public long getMode() { return nModes; }
445
446 /**
447 * Get the channel modes (as a string representation).
448 *
449 * @return string representing modes. (boolean and non-list)
450 */
451 public String getModeStr() {
/*
P/P * Method: String getModeStr()
*
* Preconditions:
* this.hParamModes != null
* this.myParser != null
* this.myParser.hChanModesBool != null
* init'ed(this.nModes)
*
* Presumptions:
* java.util.Iterator:next(...)@457 != null
* java.util.Iterator:next(...)@461 != null
* java.util.Map:get(...)@458 != null
* java.util.Map:get(...)@462 != null
* java.util.Map:keySet(...)@457 != null
* ...
*
* Postconditions:
* init'ed(java.lang.StringBuilder:toString(...)._tainted)
* return_value == &java.lang.StringBuilder:toString(...)
*
* Test Vectors:
* java.lang.String:isEmpty(...)@463: {1}, {0}
* java.util.Iterator:hasNext(...)@457: {0}, {1}
* java.util.Iterator:hasNext(...)@461: {0}, {1}
*/
452 final StringBuilder sModes = new StringBuilder("+");
453 final StringBuilder sModeParams = new StringBuilder();
454 String sTemp = "";
455 long nTemp = 0;
456 final long nChanModes = this.getMode();
457 for (char cTemp : myParser.hChanModesBool.keySet()) {
458 nTemp = myParser.hChanModesBool.get(cTemp);
459 if ((nChanModes & nTemp) == nTemp) { sModes.append(cTemp); }
460 }
461 for (char cTemp : hParamModes.keySet()) {
462 sTemp = hParamModes.get(cTemp);
463 if (!sTemp.isEmpty()) {
464 sModes.append(cTemp);
465 sModeParams.append(" ").append(this.getModeParam(cTemp));
466 }
467 }
468
469 return sModes.append(sModeParams).toString();
470 }
471
472 /**
473 * Set a channel mode that requires a parameter.
474 *
475 * @param cMode Character representing mode
476 * @param sValue String repreenting value (if "" mode is unset)
477 */
478 protected void setModeParam(final Character cMode, final String sValue) {
/*
P/P * Method: void setModeParam(Character, String)
*
* Preconditions:
* sValue != null
* this.hParamModes != null
*
* Test Vectors:
* java.lang.String:isEmpty(...)@479: {0}, {1}
* java.util.Map:containsKey(...)@480: {0}, {1}
*/
479 if (sValue.isEmpty()) {
480 if (hParamModes.containsKey(cMode)) {
481 hParamModes.remove(cMode);
482 }
483 } else {
484 hParamModes.put(cMode, sValue);
485 }
486 }
487 /**
488 * Get the value of a mode that requires a parameter.
489 *
490 * @param cMode Character representing mode
491 * @return string representing the value of the mode ("" if mode not set)
492 */
493 public String getModeParam(final Character cMode) {
/*
P/P * Method: String getModeParam(Character)
*
* Preconditions:
* this.hParamModes != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.util.Map:containsKey(...)@494: {0}, {1}
*/
494 if (hParamModes.containsKey(cMode)) {
495 return hParamModes.get(cMode);
496 }
497 return "";
498 }
499
500 /**
501 * Add/Remove a value to a channel list.
502 *
503 * @param givenMode Character representing mode
504 * @param givenItem ChannelListModeItem representing the item
505 * @param bAdd Add or remove the value. (true for add, false for remove)
506 */
507 protected void setListModeParam(final Character givenMode, final ChannelListModeItem givenItem, final boolean bAdd) {
/*
P/P * Method: void setListModeParam(Character, ChannelListModeItem, bool)
*
* Preconditions:
* this.myParser != null
* this.myParser.hChanModesOther != null
* (soft) givenItem != null
* (soft) givenItem.myItem != null
* (soft) givenItem.myOwner != null
* (soft) givenMode != null
* (soft) this.myParser.stringConverter != null
* (soft) this.hListModes != null
* (soft) this.myParser.h005Info != null
* (soft) this.myParser.sNetworkName != null
* ...
*
* Presumptions:
* getIRCStringConverter(...).lowercase.length@514 >= 1
* getIRCStringConverter(...).lowercase@514 != null
* java.util.ArrayList:get(...)@532 != null
* java.util.Map:get(...)@510 != null
* java.util.Map:get(...)@530 != null
*
* Postconditions:
* init'ed(this.myParser.stringConverter)
* init'ed(new IRCStringConverter(getIRCStringConverter#1) num objects)
* possibly_updated(new IRCStringConverter(getIRCStringConverter#1).limit)
* possibly_updated(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* possibly_updated(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* init'ed(new char[](IRCStringConverter#1) num objects)
* possibly_updated(new char[](IRCStringConverter#1).length)
* possibly_updated(new char[](IRCStringConverter#1)[...])
* init'ed(new char[](IRCStringConverter#2) num objects)
* possibly_updated(new char[](IRCStringConverter#2).length)
* ...
*
* Test Vectors:
* bAdd: {0}, {1}
* java.lang.Byte:byteValue(...)@510: {1}, {-128..0, 2..255}
* java.lang.Character:charValue(...)@513: {98}, {0..97, 99..216-1}
* java.lang.Character:charValue(...)@513: {0..112, 114..216-1}, {113}
* java.lang.Character:charValue(...)@516: {0..97, 99..216-1}, {98}
* java.lang.Character:charValue(...)@518: {0..112, 114..216-1}, {113}
* java.lang.String:charAt(...)@516: {0..36, 38..216-1}, {37}
* java.lang.String:charAt(...)@518: {37}, {0..36, 38..216-1}
* java.lang.String:charAt(...)@521: {0..36, 38..216-1}, {37}
* java.lang.String:equals(...)@515: {1}, {0}
* ...
*/
508 Character cMode = givenMode;
509 ChannelListModeItem newItem = givenItem;
510 if (!myParser.hChanModesOther.containsKey(cMode) || myParser.hChanModesOther.get(cMode) != IRCParser.MODE_LIST) { return; }
511
512 // Hyperion sucks.
513 if (cMode == 'b' || cMode == 'q') {
514 final String thisIRCD = myParser.getIRCD(true).toLowerCase();
515 if ((thisIRCD.equals("hyperion") || thisIRCD.equals("dancer"))) {
516 if (cMode == 'b' && givenItem.getItem().charAt(0) == '%') {
517 cMode = 'q';
518 } else if (cMode == 'q' && givenItem.getItem().charAt(0) != '%') {
519 cMode = 'b';
520 }
521 if (givenItem.getItem().charAt(0) == '%') {
522 newItem = new ChannelListModeItem(givenItem.getItem().substring(1), givenItem.getOwner(), givenItem.getTime());
523 }
524 }
525 }
526
527 if (!hListModes.containsKey(cMode)) {
528 hListModes.put(cMode, new ArrayList<ChannelListModeItem>());
529 }
530 final ArrayList<ChannelListModeItem> lModes = hListModes.get(cMode);
531 for (int i = 0; i < lModes.size(); i++) {
532 if (myParser.getIRCStringConverter().equalsIgnoreCase(lModes.get(i).getItem(), newItem.getItem())) {
533 if (bAdd) { return; }
534 else {
535 lModes.remove(i);
536 break;
537 }
538 }
539 }
540 if (bAdd) { lModes.add(newItem); }
541 }
542
543 /**
544 * Get the list object representing a channel mode.
545 *
546 * @param cMode Character representing mode
547 * @return ArrayList containing ChannelListModeItem in the list, or null if mode is invalid
548 */
549 public List<ChannelListModeItem> getListModeParam(final Character cMode) {
/*
P/P * Method: List getListModeParam(Character)
*
* Preconditions:
* this.myParser != null
* this.myParser.hChanModesOther != null
* (soft) this.hListModes != null
*
* Presumptions:
* java.util.Map:get(...)@550 != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.lang.Byte:byteValue(...)@550: {1}, {-128..0, 2..255}
* java.util.Map:containsKey(...)@550: {0}, {1}
* java.util.Map:containsKey(...)@552: {1}, {0}
*/
550 if (!myParser.hChanModesOther.containsKey(cMode) || myParser.hChanModesOther.get(cMode) != myParser.MODE_LIST) { return null; }
551
552 if (!hListModes.containsKey(cMode)) {
553 hListModes.put(cMode, new ArrayList<ChannelListModeItem>());
554 }
555 return hListModes.get(cMode);
556 }
557
558 /**
559 * Get the "adding state" of a list mode.
560 *
561 * @param cMode Character representing mode
562 * @return false if we are not expecting a 367 etc, else true.
563 */
564 public boolean getAddState(final Character cMode) {
/*
P/P * Method: bool getAddState(Character)
*
* Preconditions:
* this.lAddingModes != null
*
* Postconditions:
* init'ed(return_value)
*/
565 synchronized (lAddingModes) {
566 return lAddingModes.contains(cMode);
567 }
568 }
569
570 /**
571 * Get the "adding state" of a list mode.
572 *
573 * @param cMode Character representing mode
574 * @param newState change the value returned by getAddState
575 */
576 protected void setAddState(final Character cMode, final boolean newState) {
/*
P/P * Method: void setAddState(Character, bool)
*
* Preconditions:
* this.lAddingModes != null
*
* Test Vectors:
* newState: {0}, {1}
*/
577 synchronized (lAddingModes) {
578 if (newState) {
579 lAddingModes.add(cMode);
580 } else {
581 if (lAddingModes.contains(cMode)) { lAddingModes.remove(cMode); }
582 }
583 }
584 }
585
586 /**
587 * Reset the "adding state" of *all* list modes.
588 */
589 protected void resetAddState() {
/*
P/P * Method: void resetAddState()
*
* Preconditions:
* this.lAddingModes != null
*/
590 synchronized (lAddingModes) {
591 lAddingModes.clear();
592 }
593 }
594
595 /**
596 * Adjust the channel modes on a channel.
597 * This function will queue modes up to be sent in one go, according to 005 params.
598 * If less modes are altered than the queue accepts, sendModes() must be called.<br><br>
599 * sendModes is automatically called if you attempt to add more modes than is allowed
600 * to be queued
601 *
602 * @param positive Is this a positive mode change, or a negative mode change
603 * @param mode Character representing the mode to change
604 * @param parameter Parameter needed to make change (not used if mode doesn't need a parameter)
605 */
606 public void alterMode(final boolean positive, final Character mode, final String parameter) {
/*
P/P * Method: void alterMode(bool, Character, String)
*
* Preconditions:
* this.myParser != null
* this.myParser.h005Info != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.hParamModes != null
* (soft) this.lModeQueue != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesBool != null
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* ...
*
* Presumptions:
* java.util.Map:get(...)@633 != null
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* positive: {1}, {0}
* java.lang.String:isEmpty(...)@643: {1}, {0}
* java.lang.String:matches(...)@1730: {1}, {0}
* java.util.List:contains(...)@622: {0}, {1}
* java.util.Map:containsKey(...)@610: {0}, {1}
* java.util.Map:containsKey(...)@620: {0}, {1}
* java.util.Map:containsKey(...)@630: {0}, {1}
*/
607 int modecount = 1;
608 int modeint = 0;
609 String modestr = "";
610 if (myParser.h005Info.containsKey("MODES")) {
611 try {
612 modecount = Integer.parseInt(myParser.h005Info.get("MODES"));
613 } catch (NumberFormatException e) {
614 modecount = 1;
615 }
616 }
617 if (!myParser.isUserSettable(mode)) { return; }
618
619 modestr = ((positive) ? "+" : "-") + mode;
620 if (myParser.hChanModesBool.containsKey(mode)) {
621 final String teststr = ((positive) ? "-" : "+") + mode;
622 if (lModeQueue.contains(teststr)) {
623 lModeQueue.remove(teststr);
624 return;
625 } else if (lModeQueue.contains(modestr)) {
626 return;
627 }
628 } else {
629 // May need a param
630 if (myParser.hPrefixModes.containsKey(mode)) {
631 modestr = modestr + " " + parameter;
632 } else {
633 modeint = myParser.hChanModesOther.get(mode);
634 if ((modeint & IRCParser.MODE_LIST) == IRCParser.MODE_LIST) {
635 modestr = modestr + " " + parameter;
636 } else if (!positive && ((modeint & IRCParser.MODE_UNSET) == IRCParser.MODE_UNSET)) {
637 modestr = modestr + " " + parameter;
638 } else if (positive && ((modeint & IRCParser.MODE_SET) == IRCParser.MODE_SET)) {
639 // Does mode require a param to unset aswell?
640 // We might need to queue an unset first
641 if (((modeint & IRCParser.MODE_UNSET) == IRCParser.MODE_UNSET)) {
642 final String existingParam = getModeParam(mode);
643 if (!existingParam.isEmpty()) {
644 final String reverseModeStr = "-" + mode + " " + existingParam;
645
646 myParser.callDebugInfo(IRCParser.DEBUG_INFO, "Queueing mode: %s", reverseModeStr);
647 lModeQueue.add(reverseModeStr);
648 if (lModeQueue.size() == modecount) { sendModes(); }
649 }
650 }
651 modestr = modestr + " " + parameter;
652 }
653 }
654 }
655 myParser.callDebugInfo(IRCParser.DEBUG_INFO, "Queueing mode: %s", modestr);
656 lModeQueue.add(modestr);
657 if (lModeQueue.size() == modecount) { sendModes(); }
658 }
659
660 /**
661 * This function will send modes that are currently queued up to send.
662 * This assumes that the queue only contains the amount that are alowed to be sent
663 * and thus will try to send the entire queue in one go.<br><br>
664 * Modes are always sent negative then positive and not mixed.
665 */
666 public void sendModes() {
/*
P/P * Method: void sendModes()
*
* Preconditions:
* this.lModeQueue != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
* (soft) init'ed(this.myParser.out)
*
* Presumptions:
* java.util.List:get(...)@677 != null
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* java.lang.String:charAt(...)@679: {0..42, 44..216-1}, {43}
* java.lang.StringBuilder:length(...)@688: {-231..0}, {1..232-1}
* java.lang.StringBuilder:length(...)@689: {-231..0}, {1..232-1}
* java.lang.StringBuilder:length(...)@690: {-231..0}, {1..232-1}
* java.lang.StringBuilder:length(...)@691: {-231..0}, {1..232-1}
* java.util.List:isEmpty(...)@667: {0}, {1}
*/
667 if (lModeQueue.isEmpty()) { return; }
668 final StringBuilder positivemode = new StringBuilder();
669 final StringBuilder positiveparam = new StringBuilder();
670 final StringBuilder negativemode = new StringBuilder();
671 final StringBuilder negativeparam = new StringBuilder();
672 final StringBuilder sendModeStr = new StringBuilder();
673 String modestr;
674 String[] modeparam;
675 boolean positive;
676 for (int i = 0; i < lModeQueue.size(); ++i) {
677 modeparam = lModeQueue.get(i).split(" ");
678 modestr = modeparam[0];
679 positive = modestr.charAt(0) == '+';
680 if (positive) {
681 positivemode.append(modestr.charAt(1));
682 if (modeparam.length > 1) { positiveparam.append(" ").append(modeparam[1]); }
683 } else {
684 negativemode.append(modestr.charAt(1));
685 if (modeparam.length > 1) { negativeparam.append(" ").append(modeparam[1]); }
686 }
687 }
688 if (negativemode.length() > 0) { sendModeStr.append("-").append(negativemode); }
689 if (positivemode.length() > 0) { sendModeStr.append("+").append(positivemode); }
690 if (negativeparam.length() > 0) { sendModeStr.append(negativeparam); }
691 if (positiveparam.length() > 0) { sendModeStr.append(positiveparam); }
692 myParser.callDebugInfo(IRCParser.DEBUG_INFO, "Sending mode: %s", sendModeStr.toString());
693 myParser.sendLine("MODE " + sName + " " + sendModeStr.toString());
694 clearModeQueue();
695 }
696
697 /**
698 * This function will clear the mode queue (WITHOUT Sending).
699 */
700 public void clearModeQueue() {
/*
P/P * Method: void clearModeQueue()
*
* Preconditions:
* this.lModeQueue != null
*/
701 lModeQueue.clear();
702 }
703
704 /**
705 * Send a private message to the channel.
706 *
707 * @param sMessage Message to send
708 */
709 public void sendMessage(final String sMessage) {
/*
P/P * Method: void sendMessage(String)
*
* Preconditions:
* sMessage != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
* (soft) init'ed(this.myParser.out)
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* java.lang.String:isEmpty(...)@710: {0}, {1}
*/
710 if (sMessage.isEmpty()) { return; }
711
712 myParser.sendString("PRIVMSG " + sName + " :" + sMessage);
713 }
714
715 /**
716 * Send a notice message to a target.
717 *
718 * @param sMessage Message to send
719 */
720 public void sendNotice(final String sMessage) {
/*
P/P * Method: void sendNotice(String)
*
* Preconditions:
* sMessage != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
* (soft) init'ed(this.myParser.out)
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* java.lang.String:isEmpty(...)@721: {0}, {1}
*/
721 if (sMessage.isEmpty()) { return; }
722
723 myParser.sendString("NOTICE " + sName + " :" + sMessage);
724 }
725
726 /**
727 * Send a private message to a target.
728 *
729 * @param sMessage Message to send
730 */
731 public void sendAction(final String sMessage) {
/*
P/P * Method: void sendAction(String)
*
* Preconditions:
* sMessage != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) this.myParser != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
* (soft) init'ed(this.myParser.out)
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* java.lang.String:isEmpty(...)@732: {0}, {1}
*/
732 if (sMessage.isEmpty()) { return; }
733 sendCTCP("ACTION", sMessage);
734 }
735
736 /**
737 * Send a CTCP to a target.
738 *
739 * @param sType Type of CTCP
740 * @param sMessage Optional Additional Parameters
741 */
742 public void sendCTCP(final String sType, String sMessage) {
/*
P/P * Method: void sendCTCP(String, String)
*
* Preconditions:
* sType != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) sMessage != null
* (soft) this.myParser != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
* ...
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* java.lang.String:isEmpty(...)@743: {0}, {1}
* java.lang.String:isEmpty(...)@745: {1}, {0}
*/
743 if (sType.isEmpty()) { return; }
744 final char char1 = (char) 1;
745 if (!sMessage.isEmpty()) { sMessage = " " + sMessage; }
746 sendMessage(char1 + sType.toUpperCase() + sMessage + char1);
747 }
748
749 /**
750 * Send a CTCPReply to a target.
751 *
752 * @param sType Type of CTCP
753 * @param sMessage Optional Additional Parameters
754 */
755 public void sendCTCPReply(final String sType, String sMessage) {
/*
P/P * Method: void sendCTCPReply(String, String)
*
* Preconditions:
* sType != null
* (soft) init'ed(this.myParser.stringConverter)
* (soft) sMessage != null
* (soft) this.myParser != null
* (soft) this.myParser.cMyself != null
* (soft) init'ed(this.myParser.currentSocketState)
* (soft) this.myParser.hChanModesOther != null
* (soft) this.myParser.hChannelList != null
* (soft) this.myParser.myCallbackManager != null
* (soft) this.myParser.myCallbackManager.callbackHash != null
* ...
*
* Postconditions:
* init'ed(java.lang.String:substring(...)._tainted)
* possibly_updated(this.myParser.cMyself.myAwayReason)
* this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &new IRCStringConverter(getIRCStringConverter#1)}
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
* init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
* new char[](IRCStringConverter#1) num objects <= 1
* init'ed(new char[](IRCStringConverter#1).length)
* ...
*
* Test Vectors:
* java.lang.String:isEmpty(...)@756: {0}, {1}
* java.lang.String:isEmpty(...)@758: {1}, {0}
*/
756 if (sType.isEmpty()) { return; }
757 final char char1 = (char) 1;
758 if (!sMessage.isEmpty()) { sMessage = " " + sMessage; }
759 sendNotice(char1 + sType.toUpperCase() + sMessage + char1);
760 }
761
762 /**
763 * Get a string representation of the Channel.
764 *
765 * @return String representation of the Channel.
766 */
767 @Override
/*
P/P * Method: String toString()
*
* Postconditions:
* return_value == this.sName
* init'ed(return_value)
*/
768 public String toString() { return sName; }
769
770 /**
771 * Get the parser object that owns this channel.
772 *
773 * @return The parser object that owns this channel
774 */
/*
P/P * Method: IRCParser getParser()
*
* Postconditions:
* return_value == this.myParser
* init'ed(return_value)
*/
775 public IRCParser getParser() { return myParser; }
776
777 }
778
SofCheck Inspector Build Version : 2.17854
| ChannelInfo.java |
2009-Jun-25 01:54:24 |
| ChannelInfo.class |
2009-Sep-02 17:04:11 |