File Source: ProcessListModes.java
/*
P/P * Method: com.dmdirc.parser.irc.ProcessListModes__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.List;
26 import java.util.LinkedList;
27 import java.util.Queue;
28
29 /**
30 * Process a List Modes.
31 */
32 public class ProcessListModes extends IRCProcessor {
33 /**
34 * Process a ListModes.
35 *
36 * @param sParam Type of line to process
37 * @param token IRCTokenised line to process
38 */
39 @SuppressWarnings("unchecked")
40 @Override
41 public void process(String sParam, String[] token) {
/*
P/P * Method: void process(String, String[])
*
* Preconditions:
* init'ed(this.myParser.stringConverter)
* this.myParser != null
* this.myParser.hChannelList != null
* token != null
* token.length >= 4
* token[3] != null
* (soft) sParam != null
* (soft) this.myParser.h005Info != null
* (soft) init'ed(this.myParser.lastLine)
* (soft) this.myParser.myCallbackManager != null
* ...
*
* Presumptions:
* channel.hListModes != null
* channel.lAddingModes != null
* channel.myParser != null
* channel.myParser.h005Info != null
* channel.myParser.hChanModesOther != null
* ...
*
* Postconditions:
* init'ed(this.myParser.stringConverter)
* new IRCStringConverter(getIRCStringConverter#1) num objects <= 1
* new char[](IRCStringConverter#1) num objects == new IRCStringConverter(getIRCStringConverter#1) num objects
* new char[](IRCStringConverter#2) num objects == new IRCStringConverter(getIRCStringConverter#1) num objects
* 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).length == 127
* new char[](IRCStringConverter#2).length == 127
* possibly_updated(new char[](IRCStringConverter#1)[...])
* ...
*
* Test Vectors:
* token.length: {7..+Inf}, {4}
* java.lang.Character:charValue(...)@106: {98}, {113}, {0..97, 99, 101..112, 114..216-1}, {100}
* java.lang.String:charAt(...)@152: {0..36, 38..216-1}, {37}
* java.lang.String:equals(...)@100: {0}, {1}
* java.lang.String:equals(...)@116: {1}, {0}
* java.lang.String:equals(...)@116: {0}, {1}
* java.lang.String:equals(...)@144: {1}, {0}
* java.lang.String:equals(...)@144: {0}, {1}
* java.lang.String:equals(...)@152: {0}, {1}
* java.lang.String:equals(...)@164: {1}, {0}
* ...
*/
42 ChannelInfo channel = getChannelInfo(token[3]);
43 String thisIRCD = myParser.getIRCD(true).toLowerCase();
44 String item = "";
45 String owner = "";
46 byte tokenStart = 4; // Where do the relevent tokens start?
47 boolean isCleverMode = false;
48 long time = 0;
49 char mode = 'b';
50 boolean isItem = true; // true if item listing, false if "end of .." item
51 if (channel == null) { return; }
52
53 if (sParam.equals("367") || sParam.equals("368")) {
54 // Ban List/Item.
55 // (Also used for +d and +q on hyperion... -_-)
56 mode = 'b';
57 isItem = sParam.equals("367");
58 } else if (sParam.equals("348") || sParam.equals("349")) {
59 // Except / Exempt List etc
60 mode = 'e';
61 isItem = sParam.equals("348");
62 } else if (sParam.equals("346") || sParam.equals("347")) {
63 // Invite List
64 mode = 'I';
65 isItem = sParam.equals("346");
66 } else if (sParam.equals("940") || sParam.equals("941")) {
67 // Censored words List
68 mode = 'g';
69 isItem = sParam.equals("941");
70 } else if (sParam.equals("344") || sParam.equals("345")) {
71 // Reop List, or bad words list, or quiet list. god damn.
72 if (thisIRCD.equals("euircd")) {
73 mode = 'w';
74 } else if (thisIRCD.equals("oftc-hybrid")) {
75 mode = 'q';
76 } else {
77 mode = 'R';
78 }
79 isItem = sParam.equals("344");
80 } else if (thisIRCD.equals("swiftirc") && (sParam.equals("386") || sParam.equals("387"))) {
81 // Channel Owner list
82 mode = 'q';
83 isItem = sParam.equals("387");
84 } else if (thisIRCD.equals("swiftirc") && (sParam.equals("388") || sParam.equals("389"))) {
85 // Protected User list
86 mode = 'a';
87 isItem = sParam.equals("389");
88 } else if (sParam.equals(myParser.h005Info.get("LISTMODE")) || sParam.equals(myParser.h005Info.get("LISTMODEEND"))) {
89 // Support for potential future decent mode listing in the protocol
90 //
91 // See my proposal: http://shane.dmdirc.com/listmodes.php
92 mode = token[4].charAt(0);
93 isItem = sParam.equals(myParser.h005Info.get("LISTMODE"));
94 tokenStart = 5;
95 isCleverMode = true;
96 }
97
98 final Queue<Character> listModeQueue = channel.getListModeQueue();
99 if (!isCleverMode && listModeQueue != null) {
100 if (sParam.equals("482")) {
101 myParser.callDebugInfo(IRCParser.DEBUG_LMQ, "Dropped LMQ mode "+listModeQueue.poll());
102 return;
103 } else {
104 if (listModeQueue.peek() != null) {
105 Character oldMode = mode;
106 mode = listModeQueue.peek();
107 myParser.callDebugInfo(IRCParser.DEBUG_LMQ, "LMQ says this is "+mode);
108
109 boolean error = true;
110
111 // b or q are given in the same list, d is separate.
112 // b and q remove each other from the LMQ.
113 //
114 // Only raise an LMQ error if the lmqmode isn't one of bdq if the
115 // guess is one of bdq
116 if ((thisIRCD.equals("hyperion") || thisIRCD.equals("dancer")) && (mode == 'b' || mode == 'q' || mode == 'd')) {
117 LinkedList<Character> lmq = (LinkedList<Character>)listModeQueue;
118 if (mode == 'b') {
119 error = !(oldMode == 'q' || oldMode == 'd');
120 lmq.remove((Character)'q');
121 myParser.callDebugInfo(IRCParser.DEBUG_LMQ, "Dropping q from list");
122 } else if (mode == 'q') {
123 error = !(oldMode == 'b' || oldMode == 'd');
124 lmq.remove((Character)'b');
125 myParser.callDebugInfo(IRCParser.DEBUG_LMQ, "Dropping b from list");
126 } else if (mode == 'd') {
127 error = !(oldMode == 'b' || oldMode == 'q');
128 }
129 }
130
131 if (oldMode != mode && error) {
132 myParser.callDebugInfo(IRCParser.DEBUG_LMQ, "LMQ disagrees with guess. LMQ: "+mode+" Guess: "+oldMode);
133 // myParser.callErrorInfo(new ParserError(ParserError.ERROR_WARNING, "LMQ disagrees with guess. LMQ: "+mode+" Guess: "+oldMode, myParser.getLastLine()));
134 }
135
136 if (!isItem) {
137 listModeQueue.poll();
138 }
139 }
140 }
141 }
142
143 if (isItem) {
144 if ((!isCleverMode) && listModeQueue == null && (thisIRCD.equals("hyperion") || thisIRCD.equals("dancer")) && token.length > 4 && mode == 'b') {
145 // Assume mode is a 'd' mode
146 mode = 'd';
147 // Now work out if its not (or attempt to.)
148 int identstart = token[tokenStart].indexOf('!');
149 int hoststart = token[tokenStart].indexOf('@');
150 // Check that ! and @ are both in the string - as required by +b and +q
151 if ((identstart >= 0) && (identstart < hoststart)) {
152 if (thisIRCD.equals("hyperion") && token[tokenStart].charAt(0) == '%') { mode = 'q'; }
153 else { mode = 'b'; }
154 }
155 } // End Hyperian stupidness of using the same numeric for 3 different things..
156
157 if (!channel.getAddState(mode)) {
158 callDebugInfo(IRCParser.DEBUG_INFO, "New List Mode Batch ("+mode+"): Clearing!");
159 final List<ChannelListModeItem> list = channel.getListModeParam(mode);
160 if (list == null) {
161 myParser.callErrorInfo(new ParserError(ParserError.ERROR_WARNING, "Got list mode: '"+mode+"' - but channel object doesn't agree.", myParser.getLastLine()));
162 } else {
163 list.clear();
164 if ((thisIRCD.equals("hyperion") || thisIRCD.equals("dancer")) && (mode == 'b' || mode == 'q')) {
165 // Also clear the other list if b or q.
166 final Character otherMode = (mode == 'b') ? 'q' : 'b';
167
168 if (!channel.getAddState(otherMode)) {
169 callDebugInfo(IRCParser.DEBUG_INFO, "New List Mode Batch ("+mode+"): Clearing!");
170 final List<ChannelListModeItem> otherList = channel.getListModeParam(otherMode);
171 if (otherList == null) {
172 myParser.callErrorInfo(new ParserError(ParserError.ERROR_WARNING, "Got list mode: '"+otherMode+"' - but channel object doesn't agree.", myParser.getLastLine()));
173 } else {
174 otherList.clear();
175 }
176 }
177 }
178 }
179 channel.setAddState(mode, true);
180 }
181
182 if (token.length > (tokenStart+2)) {
183 try { time = Long.parseLong(token[tokenStart+2]); } catch (NumberFormatException e) { time = 0; }
184 }
185 if (token.length > (tokenStart+1)) { owner = token[tokenStart+1]; }
186 if (token.length > tokenStart) { item = token[tokenStart]; }
187 if (!item.isEmpty()) {
188 ChannelListModeItem clmi = new ChannelListModeItem(item, owner, time);
189 callDebugInfo(IRCParser.DEBUG_INFO, "List Mode: %c [%s/%s/%d]",mode, item, owner, time);
190 channel.setListModeParam(mode, clmi, true);
191 }
192 } else {
193 callDebugInfo(IRCParser.DEBUG_INFO, "List Mode Batch over");
194 channel.resetAddState();
195 if (isCleverMode || listModeQueue == null || ((LinkedList<Character>)listModeQueue).size() == 0) {
196 callDebugInfo(IRCParser.DEBUG_INFO, "Calling GotListModes");
197 channel.setHasGotListModes(true);
198 callChannelGotListModes(channel);
199 }
200 }
201 }
202
203 /**
204 * What does this IRCProcessor handle.
205 *
206 * @return String[] with the names of the tokens we handle.
207 */
208 @Override
209 public String[] handles() {
/*
P/P * Method: String[] handles()
*
* Postconditions:
* return_value == &new String[](handles#1)
* new String[](handles#1) num objects == 1
* return_value.length == 16
* return_value[0] == &"367"
* return_value[10] == &"388"
* return_value[11] == &"389"
* return_value[12] == &"940"
* return_value[13] == &"941"
* return_value[14] == &"482"
* return_value[15] == &"__LISTMODE__"
* ...
*/
210 return new String[]{"367", "368", /* Bans */
211 "344", "345", /* Reop list (ircnet) or bad words (euirc) */
212 "346", "347", /* Invite List */
213 "348", "349", /* Except/Exempt List */
214 "386", "387", /* Channel Owner List (swiftirc ) */
215 "388", "389", /* Protected User List (swiftirc) */
216 "940", "941", /* Censored words list */
217 "482", /* Permission Denied */
218 "__LISTMODE__" /* Sensible List Modes */
219 };
220 }
221
222 /**
223 * Callback to all objects implementing the ChannelGotListModes Callback.
224 *
225 * @see IChannelGotListModes
226 * @param cChannel Channel which the ListModes reply is for
227 * @return true if a method was called, false otherwise
228 */
229 protected boolean callChannelGotListModes(ChannelInfo cChannel) {
/*
P/P * Method: bool callChannelGotListModes(ChannelInfo)
*
* Preconditions:
* this.myParser != null
* this.myParser.myCallbackManager != null
* this.myParser.myCallbackManager.callbackHash != null
*
* Presumptions:
* getCallbackManager(...)@230 init'ed
*
* Postconditions:
* init'ed(return_value)
*/
230 return getCallbackManager().getCallbackType("OnChannelGotListModes").call(cChannel);
231 }
232
233 /**
234 * Create a new instance of the IRCProcessor Object.
235 *
236 * @param parser IRCParser That owns this IRCProcessor
237 * @param manager ProcessingManager that is in charge of this IRCProcessor
238 */
/*
P/P * Method: void com.dmdirc.parser.irc.ProcessListModes(IRCParser, ProcessingManager)
*
* Postconditions:
* this.myManager == manager
* init'ed(this.myManager)
* this.myParser == parser
* init'ed(this.myParser)
*/
239 protected ProcessListModes (IRCParser parser, ProcessingManager manager) { super(parser, manager); }
240
241 }
SofCheck Inspector Build Version : 2.17854
| ProcessListModes.java |
2009-Jun-25 01:54:24 |
| ProcessListModes.class |
2009-Sep-02 17:04:16 |