1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * Creates an empty filter rule. Conditions and actions will need to be added.
 26  * @constructor
 27  * @class
 28  * ZmFilterRule represents a filter rule. A rule includes one or more conditions
 29  * and one or more actions.
 30  *
 31  * @author Conrad Damon
 32  *
 33  * @param {String}	name			the rule name
 34  * @param {Boolean}	active		if <code>true</code>, if the rule is enabled
 35  * @param {Object}	filterActions	the filter action data as raw json object
 36  * @param {Object}	filterTests	the filter conditions data as raw json object
 37  * 
 38  */
 39 ZmFilterRule = function(name, active, filterActions, filterTests) {
 40 	/**
 41      * The name of the filter rule.
 42      * @type String
 43      */
 44 	this.name = name;
 45 	/**
 46 	 * The filter rule actions.
 47 	 * @type	Object
 48 	 */
 49 	this.actions = filterActions || {};
 50 	/**
 51 	 * The filter rules conditions.
 52 	 * @type	Object
 53 	 */
 54 	this.conditions = filterTests || {};
 55 	this.active = (active !== false);
 56 	if (!filterTests) {
 57 		this.setGroupOp();
 58 	}
 59 
 60 	this.id = ZmFilterRule._nextId++;
 61 };
 62 
 63 ZmFilterRule.prototype.isZmFilterRule = true;
 64 ZmFilterRule.prototype.toString = function() { return "ZmFilterRule"; };
 65 
 66 
 67 ZmFilterRule._nextId = 1;
 68 
 69 /**
 70  * Defines the "group any" operator.
 71  */
 72 ZmFilterRule.GROUP_ANY = "anyof";
 73 /**
 74  * Defines the "group all" operator.
 75  */
 76 ZmFilterRule.GROUP_ALL = "allof";
 77 
 78 // Display widgets for various rule properties
 79 
 80 /**
 81  * Defines the "input" type.
 82  */
 83 ZmFilterRule.TYPE_INPUT			= "INPUT";
 84 /**
 85  * Defines the "select" type.
 86  */
 87 ZmFilterRule.TYPE_SELECT		= "SELECT";
 88 /**
 89  * Defines the "calendar" type.
 90  */
 91 ZmFilterRule.TYPE_CALENDAR		= "CALENDAR";
 92 /**
 93  * Defines the "folder picker" type.
 94  */
 95 ZmFilterRule.TYPE_FOLDER_PICKER	= "FOLDER_PICKER";
 96 /**
 97  * Defines the "tag picker" type.
 98  */
 99 ZmFilterRule.TYPE_TAG_PICKER	= "TAG_PICKER";
100 
101 ZmFilterRule.IMPORTANCE         = "importance";
102 ZmFilterRule.IMPORTANCE_HIGH    = "high";
103 ZmFilterRule.IMPORTANCE_LOW     = "low";
104 ZmFilterRule.IMPORTANCE_NORMAL  = "normal";
105 ZmFilterRule.FLAGGED            = "flagged";
106 ZmFilterRule.READ               = "read";
107 ZmFilterRule.PRIORITY           = "priority";
108 ZmFilterRule.RANKING            = "ranking";
109 
110 
111 // Conditions (subjects)
112 ZmFilterRule.C_FROM			            = AjxEmailAddress.FROM;
113 ZmFilterRule.C_TO			            = AjxEmailAddress.TO;
114 ZmFilterRule.C_CC			            = AjxEmailAddress.CC;
115 ZmFilterRule.C_TO_CC		            = "TO_CC";
116 ZmFilterRule.C_BCC                      = AjxEmailAddress.BCC;
117 ZmFilterRule.C_SUBJECT		            = "SUBJECT";
118 ZmFilterRule.C_HEADER		            = "HEADER";
119 ZmFilterRule.C_SIZE			            = "SIZE";
120 ZmFilterRule.C_DATE			            = "DATE";
121 ZmFilterRule.C_BODY			            = "BODY";
122 ZmFilterRule.C_ATT			            = "ATT";
123 ZmFilterRule.C_MIME_HEADER	            = "MIME_HEADER";
124 ZmFilterRule.C_ADDRBOOK		            = "ADDRBOOK";
125 ZmFilterRule.C_INVITE		            = "INVITE";
126 ZmFilterRule.C_CONV                     = "CONVERSATIONS";
127 ZmFilterRule.C_BULK                     = "BULK";
128 ZmFilterRule.C_LIST                     = "LIST";
129 ZmFilterRule.C_SOCIAL                   = "SOCIAL";
130 ZmFilterRule.C_FACEBOOK                 = "FACEBOOK";
131 ZmFilterRule.C_LINKEDIN                 = "LINKEDIN";
132 ZmFilterRule.C_TWITTER                  = "TWITTER";
133 ZmFilterRule.C_COMMUNITY                = "COMMUNITY";
134 ZmFilterRule.C_COMMUNITY_REQUESTS       = "COMMUNITY_REQUESTS";
135 ZmFilterRule.C_COMMUNITY_CONTENT        = "COMMUNITY_CONTENT";
136 ZmFilterRule.C_COMMUNITY_CONNECTIONS    = "COMMUNITY_CONNECTIONS";
137 ZmFilterRule.C_ADDRESS                  = "ADDRESS";
138 ZmFilterRule.C_RANKING                  = "RANKING";
139 ZmFilterRule.C_ME                       = "ME";
140 ZmFilterRule.C_IMPORTANCE               = "IMPORTANCE";
141 
142 ZmFilterRule.C_HEADER_VALUE = {};
143 ZmFilterRule.C_HEADER_VALUE[ZmFilterRule.C_SUBJECT]	= "subject";
144 ZmFilterRule.C_HEADER_VALUE[ZmFilterRule.C_HEADER]	= "header";
145 
146 ZmFilterRule.C_HEADER_MAP = AjxUtil.valueHash(ZmFilterRule.C_HEADER_VALUE);
147 
148 ZmFilterRule.C_ADDRESS_VALUE = {};
149 ZmFilterRule.C_ADDRESS_VALUE[ZmFilterRule.C_FROM]	= "from";
150 ZmFilterRule.C_ADDRESS_VALUE[ZmFilterRule.C_TO]		= "to";
151 ZmFilterRule.C_ADDRESS_VALUE[ZmFilterRule.C_CC]		= "cc";
152 ZmFilterRule.C_ADDRESS_VALUE[ZmFilterRule.C_TO_CC]	= "to,cc";
153 ZmFilterRule.C_ADDRESS_VALUE[ZmFilterRule.C_BCC]    = "bcc";
154 
155 ZmFilterRule.C_ADDRESS_MAP = AjxUtil.valueHash(ZmFilterRule.C_ADDRESS_VALUE);
156 
157 ZmFilterRule.C_LABEL = {};
158 ZmFilterRule.C_LABEL[ZmFilterRule.C_FROM]		= ZmMsg.from;
159 ZmFilterRule.C_LABEL[ZmFilterRule.C_TO]			= ZmMsg.to;
160 ZmFilterRule.C_LABEL[ZmFilterRule.C_CC]			= ZmMsg.cc;
161 ZmFilterRule.C_LABEL[ZmFilterRule.C_TO_CC]		= ZmMsg.toCc;
162 ZmFilterRule.C_LABEL[ZmFilterRule.C_BCC]        = ZmMsg.bcc;
163 ZmFilterRule.C_LABEL[ZmFilterRule.C_SUBJECT]	= ZmMsg.subject;
164 ZmFilterRule.C_LABEL[ZmFilterRule.C_HEADER]		= ZmMsg.headerNamed;
165 ZmFilterRule.C_LABEL[ZmFilterRule.C_SIZE]		= ZmMsg.size;
166 ZmFilterRule.C_LABEL[ZmFilterRule.C_DATE]		= ZmMsg.date;
167 ZmFilterRule.C_LABEL[ZmFilterRule.C_BODY]		= ZmMsg.body;
168 ZmFilterRule.C_LABEL[ZmFilterRule.C_ATT]		= ZmMsg.attachment;
169 // only read-receipt (i.e. "message/disposition-notification") content-type is currently supported
170 ZmFilterRule.C_LABEL[ZmFilterRule.C_MIME_HEADER]= ZmMsg.readReceiptFilter;
171 ZmFilterRule.C_LABEL[ZmFilterRule.C_ADDRBOOK]	= ZmMsg.addressIn;
172 ZmFilterRule.C_LABEL[ZmFilterRule.C_INVITE]		= ZmMsg.calendarInvite;
173 ZmFilterRule.C_LABEL[ZmFilterRule.C_CONV]       = ZmMsg.message;
174 ZmFilterRule.C_LABEL[ZmFilterRule.C_SOCIAL]     = ZmMsg.socialLabel;
175 ZmFilterRule.C_LABEL[ZmFilterRule.C_COMMUNITY]  = ZmMsg.communityName;
176 ZmFilterRule.C_LABEL[ZmFilterRule.C_ADDRESS]    = ZmMsg.address;
177 
178 // Tests
179 ZmFilterRule.TEST_ADDRESS						= "addressTest"; 
180 ZmFilterRule.TEST_HEADER						= "headerTest";
181 ZmFilterRule.TEST_HEADER_EXISTS					= "headerExistsTest";
182 ZmFilterRule.TEST_SIZE							= "sizeTest";
183 ZmFilterRule.TEST_DATE							= "dateTest";
184 ZmFilterRule.TEST_BODY							= "bodyTest";
185 ZmFilterRule.TEST_ATTACHMENT					= "attachmentTest";
186 ZmFilterRule.TEST_MIME_HEADER					= "mimeHeaderTest";
187 ZmFilterRule.TEST_ADDRBOOK						= "addressBookTest";
188 ZmFilterRule.TEST_INVITE						= "inviteTest";
189 ZmFilterRule.TEST_FACEBOOK                      = "facebookTest";
190 ZmFilterRule.TEST_LINKEDIN                      = "linkedinTest";
191 ZmFilterRule.TEST_TWITTER                       = "twitterTest";
192 ZmFilterRule.TEST_COMMUNITY_REQUESTS            = "communityRequestsTest";
193 ZmFilterRule.TEST_COMMUNITY_CONTENT             = "communityContentTest";
194 ZmFilterRule.TEST_COMMUNITY_CONNECTIONS         = "communityConnectionsTest";
195 ZmFilterRule.TEST_CONVERSATIONS                 = "conversationTest";
196 ZmFilterRule.TEST_BULK                          = "bulkTest";
197 ZmFilterRule.TEST_LIST                          = "listTest";
198 ZmFilterRule.TEST_SOCIAL                        = "socialTest"; //not a real test
199 ZmFilterRule.TEST_COMMUNITY                     = "communityTest"; //not a real test
200 ZmFilterRule.TEST_ME                            = "meTest";
201 ZmFilterRule.TEST_RANKING                       = "contactRankingTest";
202 ZmFilterRule.TEST_IMPORTANCE                    = "importanceTest";
203 ZmFilterRule.TEST_FLAGGED                       = "flaggedTest";
204 
205 
206 // Conditions map to Tests
207 ZmFilterRule.C_TEST_MAP = {};
208 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_FROM]		            = ZmFilterRule.TEST_ADDRESS;
209 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_TO]			            = ZmFilterRule.TEST_ADDRESS;
210 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_CC]			            = ZmFilterRule.TEST_ADDRESS;
211 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_TO_CC]		            = ZmFilterRule.TEST_ADDRESS;
212 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_BCC]                     = ZmFilterRule.TEST_ADDRESS;
213 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_SUBJECT]		            = ZmFilterRule.TEST_HEADER;
214 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_HEADER]		            = ZmFilterRule.TEST_HEADER;
215 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_SIZE]		            = ZmFilterRule.TEST_SIZE;
216 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_DATE]		            = ZmFilterRule.TEST_DATE;
217 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_BODY]		            = ZmFilterRule.TEST_BODY;
218 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_ATT]			            = ZmFilterRule.TEST_ATTACHMENT;
219 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_MIME_HEADER]	            = ZmFilterRule.TEST_MIME_HEADER;
220 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_ADDRBOOK]	            = ZmFilterRule.TEST_ADDRBOOK;
221 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_INVITE]		            = ZmFilterRule.TEST_INVITE;
222 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_FACEBOOK]                = ZmFilterRule.TEST_FACEBOOK;
223 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_LINKEDIN]                = ZmFilterRule.TEST_LINKEDIN;
224 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_TWITTER]                 = ZmFilterRule.TEST_TWITTER;
225 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_COMMUNITY_REQUESTS]      = ZmFilterRule.TEST_COMMUNITY_REQUESTS;
226 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_COMMUNITY_CONTENT]       = ZmFilterRule.TEST_COMMUNITY_CONTENT;
227 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_COMMUNITY_CONNECTIONS]   = ZmFilterRule.TEST_COMMUNITY_CONNECTIONS;
228 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_CONV]                    = ZmFilterRule.TEST_CONVERSATIONS;
229 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_BULK]                    = ZmFilterRule.TEST_BULK;
230 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_SOCIAL]                  = ZmFilterRule.TEST_SOCIAL;
231 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_COMMUNITY]               = ZmFilterRule.TEST_COMMUNITY;
232 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_ADDRESS]                 = ZmFilterRule.TEST_ADDRESS;
233 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_ME]                      = ZmFilterRule.TEST_ME;
234 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_RANKING]                 = ZmFilterRule.TEST_RANKING;
235 ZmFilterRule.C_TEST_MAP[ZmFilterRule.C_IMPORTANCE]              = ZmFilterRule.TEST_IMPORTANCE;
236 
237 // Operations (verbs)
238 ZmFilterRule.OP_IS				        = "IS";
239 ZmFilterRule.OP_NOT_IS			        = "NOT_IS";
240 ZmFilterRule.OP_CONTAINS		        = "CONTAINS";
241 ZmFilterRule.OP_NOT_CONTAINS	        = "NOT_CONTAINS";
242 ZmFilterRule.OP_MATCHES			        = "MATCHES";
243 ZmFilterRule.OP_NOT_MATCHES		        = "NOT_MATCHES";
244 ZmFilterRule.OP_EXISTS			        = "EXISTS";
245 ZmFilterRule.OP_NOT_EXISTS		        = "NOT_EXISTS";
246 ZmFilterRule.OP_UNDER			        = "UNDER";
247 ZmFilterRule.OP_NOT_UNDER		        = "NOT_UNDER";
248 ZmFilterRule.OP_OVER			        = "OVER";
249 ZmFilterRule.OP_NOT_OVER		        = "NOT_OVER";
250 ZmFilterRule.OP_BEFORE			        = "BEFORE";
251 ZmFilterRule.OP_NOT_BEFORE		        = "NOT_BEFORE";
252 ZmFilterRule.OP_AFTER			        = "AFTER";
253 ZmFilterRule.OP_NOT_AFTER		        = "NOT_AFTER";
254 ZmFilterRule.OP_IN				        = "IN";
255 ZmFilterRule.OP_NOT_IN			        = "NOT_IN";
256 ZmFilterRule.OP_IS_REQUESTED	        = "IS_REQUESTED"; // invites
257 ZmFilterRule.OP_NOT_REQUESTED           = "NOT_REQUESTED"; //invites
258 ZmFilterRule.OP_NOT_REPLIED             = "NOT_REPLIED"; //invites
259 ZmFilterRule.OP_IS_REPLIED		        = "IS_REPLIED"; // invites
260 ZmFilterRule.OP_IS_READRECEIPT          = "IS_READRECEIPT";
261 ZmFilterRule.OP_NOT_READRECEIPT         = "NOT_READRECEIPT";
262 ZmFilterRule.OP_WHERE_STARTED           = "STARTED"; //conversations
263 ZmFilterRule.OP_WHERE_PARTICIPATED      = "PARTICIPATED"; //conversations
264 ZmFilterRule.OP_CONV_IS                 = "CONV_IS";//not an operator
265 ZmFilterRule.OP_NOT_CONV                = "CONV_NOT";
266 //ZmFilterRule.OP_SOCIAL_FROM           = "SOCIAL_FROM"; //not an operator
267 ZmFilterRule.OP_SOCIAL_FACEBOOK         = "SOCIAL_FACEBOOK";
268 ZmFilterRule.OP_SOCIAL_TWITTER          = "SOCIAL_TWITTER";
269 ZmFilterRule.OP_SOCIAL_LINKEDIN         = "SOCIAL_LINKEDIN";
270 ZmFilterRule.OP_IS_ME                   = "IS_ME";
271 ZmFilterRule.OP_NOT_ME                  = "IS_NOT_ME";
272 ZmFilterRule.OP_COMMUNITY_REQUESTS      = "COMMUNITY_REQUESTS";
273 ZmFilterRule.OP_COMMUNITY_CONTENT       = "COMMUNITY_CONTENT";
274 ZmFilterRule.OP_COMMUNITY_CONNECTIONS   = "COMMUNITY_CONNECTIONS";
275 
276 
277 // comparator types
278 ZmFilterRule.COMP_STRING    = "stringComparison";
279 ZmFilterRule.COMP_NUMBER    = "numberComparison";
280 ZmFilterRule.COMP_DATE      = "dateComparison";
281 
282 // comparator map to test
283 ZmFilterRule.COMP_TEST_MAP = {};
284 ZmFilterRule.COMP_TEST_MAP[ZmFilterRule.TEST_ADDRESS]		= ZmFilterRule.COMP_STRING;
285 ZmFilterRule.COMP_TEST_MAP[ZmFilterRule.TEST_HEADER]		= ZmFilterRule.COMP_STRING;
286 ZmFilterRule.COMP_TEST_MAP[ZmFilterRule.TEST_MIME_HEADER]	= ZmFilterRule.COMP_STRING;
287 ZmFilterRule.COMP_TEST_MAP[ZmFilterRule.TEST_SIZE]			= ZmFilterRule.COMP_NUMBER;
288 ZmFilterRule.COMP_TEST_MAP[ZmFilterRule.TEST_DATE]			= ZmFilterRule.COMP_DATE;
289 
290 // operation values
291 ZmFilterRule.OP_VALUE = {};
292 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_IS]			            = "is";
293 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_CONTAINS]		            = "contains";
294 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_MATCHES]		            = "matches";
295 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_EXISTS]		            = "exists";
296 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_UNDER]		            = "under";
297 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_OVER]			            = "over";
298 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_BEFORE]		            = "before";
299 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_AFTER]		            = "after";
300 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_IN]			            = "in";
301 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_IS_REQUESTED]	            = "anyrequest";
302 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_IS_REPLIED]	            = "anyreply";
303 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_IS_READRECEIPT]           = "contains";
304 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_WHERE_STARTED]            = "started";
305 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_WHERE_PARTICIPATED]       = "participated";
306 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_CONV_IS]                  = "convIs";
307 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_IS_ME]                    = "isMe";
308 ZmFilterRule.OP_VALUE[ZmFilterRule.OP_NOT_CONV]                 = "convNot";
309 
310 ZmFilterRule.OP_VALUE_MAP = AjxUtil.valueHash(ZmFilterRule.OP_VALUE);
311 
312 ZmFilterRule.OP_SOCIAL_MAP = {};
313 ZmFilterRule.OP_SOCIAL_MAP[ZmFilterRule.OP_SOCIAL_FACEBOOK] = ZmFilterRule.TEST_FACEBOOK;
314 ZmFilterRule.OP_SOCIAL_MAP[ZmFilterRule.OP_SOCIAL_LINKEDIN] = ZmFilterRule.TEST_LINKEDIN;
315 ZmFilterRule.OP_SOCIAL_MAP[ZmFilterRule.OP_SOCIAL_TWITTER] = ZmFilterRule.TEST_TWITTER;
316 
317 ZmFilterRule.OP_COMMUNITY_MAP = {};
318 ZmFilterRule.OP_COMMUNITY_MAP[ZmFilterRule.OP_COMMUNITY_REQUESTS]       = ZmFilterRule.TEST_COMMUNITY_REQUESTS;
319 ZmFilterRule.OP_COMMUNITY_MAP[ZmFilterRule.OP_COMMUNITY_CONTENT]        = ZmFilterRule.TEST_COMMUNITY_CONTENT;
320 ZmFilterRule.OP_COMMUNITY_MAP[ZmFilterRule.OP_COMMUNITY_CONNECTIONS]    = ZmFilterRule.TEST_COMMUNITY_CONNECTIONS;
321 
322 ZmFilterRule.OP_COMMUNITY_MAP_R = AjxUtil.backMap(ZmFilterRule.OP_COMMUNITY_MAP);
323 
324 // operation labels
325 ZmFilterRule.OP_LABEL = {};
326 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_IS]			            = ZmMsg.exactMatch;
327 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_IS]		            = ZmMsg.notExactMatch;
328 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_CONTAINS]		            = ZmMsg.contains;
329 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_CONTAINS]	            = ZmMsg.notContain;
330 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_MATCHES]		            = ZmMsg.matches;
331 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_MATCHES]	            = ZmMsg.notMatch;
332 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_EXISTS]		            = ZmMsg.exists;
333 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_EXISTS]	            = ZmMsg.notExist;
334 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_UNDER]		            = ZmMsg.under;
335 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_UNDER]	            = ZmMsg.notUnder;
336 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_OVER]			            = ZmMsg.over;
337 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_OVER]		            = ZmMsg.notOver;
338 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_BEFORE]		            = ZmMsg.beforeLc;
339 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_BEFORE]	            = ZmMsg.notBefore;
340 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_AFTER]		            = ZmMsg.afterLc;
341 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_AFTER]	            = ZmMsg.notAfter;
342 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_IN]			            = ZmMsg.isIn;
343 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_IN]		            = ZmMsg.notIn;
344 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_IS_REQUESTED]	            = ZmMsg.isRequested;
345 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_REQUESTED]            = ZmMsg.notRequested;
346 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_IS_REPLIED]	            = ZmMsg.isReplied;
347 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_REPLIED]              = ZmMsg.notReplied;
348 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_IS_READRECEIPT]           = ZmMsg.exists;
349 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_READRECEIPT]          = ZmMsg.notExist;
350 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_WHERE_PARTICIPATED]       = ZmMsg.participatedLabel;
351 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_WHERE_STARTED]            = ZmMsg.startedLabel;
352 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_CONV_IS]                  = ZmMsg.isLabel;
353 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_CONV]                 = ZmMsg.notIs;
354 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_SOCIAL_FACEBOOK]          = ZmMsg.facebookNotifications;
355 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_SOCIAL_TWITTER]           = ZmMsg.twitterNotifications;
356 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_SOCIAL_LINKEDIN]          = ZmMsg.linkedinMessagesConnections;
357 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_COMMUNITY_REQUESTS]       = ZmMsg.communityRequests;
358 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_COMMUNITY_CONTENT]        = ZmMsg.communityContent;
359 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_COMMUNITY_CONNECTIONS]    = ZmMsg.communityConnections;
360 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_IS_ME]                    = ZmMsg.isMeLabel;
361 ZmFilterRule.OP_LABEL[ZmFilterRule.OP_NOT_ME]                   = ZmMsg.isNotMeLabel;
362 
363 
364 // commonly used lists
365 ZmFilterRule.MATCHING_OPS = [
366 	ZmFilterRule.OP_IS, ZmFilterRule.OP_NOT_IS,
367 	ZmFilterRule.OP_CONTAINS, ZmFilterRule.OP_NOT_CONTAINS,
368 	ZmFilterRule.OP_MATCHES, ZmFilterRule.OP_NOT_MATCHES
369 ];
370 
371 /**
372  * This defines a hash of conditions. Each condition is a hash of parameters. The key of the hash
373  * is also known as the condition "subject". It is the field of an email message that 
374  * the condition is tested against.
375  * 
376  * <p>
377  * The condition parameters are:
378  * <ul>
379  * <li><b>subjectMod</b>	Type of input widget for the subjectModifier, which is a specifier or 
380  *				modifier for the subject (such as which address to look at)</li>
381  * <li><b>smOptions</b>		List of possible values for the subjectModifier ({@link ZmFilterRule.TYPE_SELECT})</li>
382  * <li><b>ops</b>			Type of input widget for choosing the comparator</li>
383  * <li><b>opsOptions</b>	List of possible comparators for this subject ({@link ZmFilterRule.TYPE_SELECT} type)</li>
384  * <li><b>value</b>			Type of input widget for specifying the value</li>
385  * <li><b>vOptions</b>		List of possible values ({@link ZmFilterRule.TYPE_SELECT} type)</li>
386  * <li><b>valueMod</b>		Type of input widget for the valueModifier, which is a specifier or 
387  *				modifier for the value (such as units for size)</li>
388  * <li><b>vmOptions</b>		List of possible values for the valueModifier ({@link ZmFilterRule.TYPE_SELECT} type)</li>
389  * </ul>
390  */
391 ZmFilterRule.CONDITIONS = {};
392 ZmFilterRule.CONDITIONS[ZmFilterRule.C_FROM] = {
393 	ops:		ZmFilterRule.TYPE_SELECT,
394 	opsOptions:	ZmFilterRule.MATCHING_OPS,
395 	value:		ZmFilterRule.TYPE_INPUT,
396 	valueMod:   ZmFilterRule.TYPE_SELECT,
397 	vmOptions:	[{label: ZmMsg.filterRuleOptionAll, value: "all"}, {label: ZmMsg.filterRuleOptionLocalpart, value: "localpart"}, {label:ZmMsg.filterRuleOptionDomain, value: "domain"}]
398 };
399 ZmFilterRule.CONDITIONS[ZmFilterRule.C_TO] = {
400 	ops:		ZmFilterRule.TYPE_SELECT,
401 	opsOptions:	ZmFilterRule.MATCHING_OPS,
402 	value:		ZmFilterRule.TYPE_INPUT,
403 	valueMod:   ZmFilterRule.TYPE_SELECT,
404 	vmOptions:	[{label: ZmMsg.filterRuleOptionAll, value: "all"}, {label: ZmMsg.filterRuleOptionLocalpart, value: "localpart"}, {label:ZmMsg.filterRuleOptionDomain, value: "domain"}]
405 };
406 ZmFilterRule.CONDITIONS[ZmFilterRule.C_CC] = {
407 	ops:		ZmFilterRule.TYPE_SELECT,
408 	opsOptions:	ZmFilterRule.MATCHING_OPS,
409 	value:		ZmFilterRule.TYPE_INPUT,
410 	valueMod:   ZmFilterRule.TYPE_SELECT,
411 	vmOptions:	[{label: ZmMsg.filterRuleOptionAll, value: "all"}, {label: ZmMsg.filterRuleOptionLocalpart, value: "localpart"}, {label:ZmMsg.filterRuleOptionDomain, value: "domain"}]
412 };
413 ZmFilterRule.CONDITIONS[ZmFilterRule.C_TO_CC] = {
414 	ops:		ZmFilterRule.TYPE_SELECT,
415 	opsOptions:	ZmFilterRule.MATCHING_OPS,
416 	value:		ZmFilterRule.TYPE_INPUT,
417 	valueMod:   ZmFilterRule.TYPE_SELECT,
418 	vmOptions:	[{label: ZmMsg.filterRuleOptionAll, value: "all"}, {label: ZmMsg.filterRuleOptionLocalpart, value: "localpart"}, {label:ZmMsg.filterRuleOptionDomain, value: "domain"}]
419 };
420 ZmFilterRule.CONDITIONS[ZmFilterRule.C_BCC] = {
421 	ops:		ZmFilterRule.TYPE_SELECT,
422 	opsOptions:	ZmFilterRule.MATCHING_OPS,
423 	value:		ZmFilterRule.TYPE_INPUT,
424 	valueMod:   ZmFilterRule.TYPE_SELECT,
425 	vmOptions:	[{label: ZmMsg.filterRuleOptionAll, value: "all"}, {label: ZmMsg.filterRuleOptionLocalpart, value: "localpart"}, {label:ZmMsg.filterRuleOptionDomain, value: "domain"}]
426 };
427 ZmFilterRule.CONDITIONS[ZmFilterRule.C_SUBJECT] = {
428 		ops:		ZmFilterRule.TYPE_SELECT,
429 		opsOptions:	ZmFilterRule.MATCHING_OPS,
430 		value:		ZmFilterRule.TYPE_INPUT
431 };
432 ZmFilterRule.CONDITIONS[ZmFilterRule.C_HEADER] = {
433 		subjectMod:	ZmFilterRule.TYPE_INPUT,
434 		ops:		ZmFilterRule.TYPE_SELECT,
435 		opsOptions:	ZmFilterRule.MATCHING_OPS.concat([ZmFilterRule.OP_EXISTS, ZmFilterRule.OP_NOT_EXISTS]),
436 		value:		ZmFilterRule.TYPE_INPUT
437 };
438 ZmFilterRule.CONDITIONS[ZmFilterRule.C_SIZE] = {
439 		ops:		ZmFilterRule.TYPE_SELECT,
440 		opsOptions:	[ZmFilterRule.OP_UNDER, ZmFilterRule.OP_NOT_UNDER, ZmFilterRule.OP_OVER, ZmFilterRule.OP_NOT_OVER],
441 		value:		ZmFilterRule.TYPE_INPUT,
442 		valueMod:	ZmFilterRule.TYPE_SELECT,
443 		vmOptions:	[{label: ZmMsg.b, value: "B"}, {label: ZmMsg.kb, value: "K"}, {label: ZmMsg.mb, value: "M"}, {label: ZmMsg.gb, value: "G"}]
444 };
445 ZmFilterRule.CONDITIONS[ZmFilterRule.C_DATE] = {
446 		ops:		ZmFilterRule.TYPE_SELECT,
447 		opsOptions:	[ZmFilterRule.OP_BEFORE, ZmFilterRule.OP_NOT_BEFORE, ZmFilterRule.OP_AFTER, ZmFilterRule.OP_NOT_AFTER],
448 		value:		ZmFilterRule.TYPE_CALENDAR
449 };
450 ZmFilterRule.CONDITIONS[ZmFilterRule.C_BODY] = {
451 		ops:		ZmFilterRule.TYPE_SELECT,
452 		opsOptions:	[ZmFilterRule.OP_CONTAINS, ZmFilterRule.OP_NOT_CONTAINS],
453 		value:		ZmFilterRule.TYPE_INPUT
454 };
455 ZmFilterRule.CONDITIONS[ZmFilterRule.C_ATT] = {
456 		ops:		ZmFilterRule.TYPE_SELECT,
457 		opsOptions:	[ZmFilterRule.OP_EXISTS, ZmFilterRule.OP_NOT_EXISTS]
458 };
459 ZmFilterRule.CONDITIONS[ZmFilterRule.C_MIME_HEADER] = {
460         ops:        ZmFilterRule.TYPE_SELECT,
461         opsOptions: [ZmFilterRule.OP_IS_READRECEIPT, ZmFilterRule.OP_NOT_READRECEIPT]
462 
463 };
464 ZmFilterRule.CONDITIONS[ZmFilterRule.C_ADDRBOOK] = {
465 		subjectMod:	ZmFilterRule.TYPE_SELECT,
466 		smOptions:	[{label: ZmMsg.from, value: "FROM"}, {label: ZmMsg.to, value: "TO"},
467 					 {label: ZmMsg.cc, value: "CC"}, {label: ZmMsg.toOrCc, value: "TO,CC"},
468 					 {label: ZmMsg.bcc, value: "BCC"}],
469 		ops:		ZmFilterRule.TYPE_SELECT,
470 		opsOptions:	[ZmFilterRule.OP_IN, ZmFilterRule.OP_NOT_IN, ZmFilterRule.OP_IS_ME, ZmFilterRule.OP_NOT_ME],
471 		value:		ZmFilterRule.TYPE_SELECT,
472 		vOptions:	[{label: ZmMsg.myContactsLabel, value: "contacts"}, {label: ZmMsg.frequentEmailLabel, value: "ranking"}]
473 };
474 ZmFilterRule.CONDITIONS[ZmFilterRule.C_INVITE] = {
475 		ops:		ZmFilterRule.TYPE_SELECT,
476 		opsOptions:	[ZmFilterRule.OP_IS_REQUESTED, ZmFilterRule.OP_NOT_REQUESTED, ZmFilterRule.OP_IS_REPLIED, ZmFilterRule.OP_NOT_REPLIED]
477 };
478 ZmFilterRule.CONDITIONS[ZmFilterRule.C_CONV] = {
479 		ops:        ZmFilterRule.TYPE_SELECT,
480 	    opsOptions: [ZmFilterRule.OP_CONV_IS, ZmFilterRule.OP_NOT_CONV],
481 		value:      ZmFilterRule.TYPE_SELECT,
482 		vOptions:  [{label: ZmMsg.convIStartLabel, value: "started"}, {label: ZmMsg.convIParticipateLabel, value: "participated"},
483 			        {label: ZmMsg.massMarketingLabel, value: ZmFilterRule.C_BULK}, {label: ZmMsg.distributionListLabel, value: ZmFilterRule.C_LIST},
484 					{label: ZmMsg.markedAsLabel, value: ZmFilterRule.IMPORTANCE}, {label: ZmMsg.flagged.toLowerCase(), value: ZmFilterRule.FLAGGED}],
485 	    valueMod:  ZmFilterRule.TYPE_SELECT,
486 	    vmOptions: [{label: ZmMsg.read.toLowerCase(), value: ZmFilterRule.READ}, {label: ZmMsg.priority.toLowerCase(), value: ZmFilterRule.PRIORITY},
487 		            {label: ZmMsg.importanceHigh, value: ZmFilterRule.IMPORTANCE_HIGH}, {label: ZmMsg.importanceNormal, value: ZmFilterRule.IMPORTANCE_NORMAL},
488 		            {label: ZmMsg.importanceLow, value: ZmFilterRule.IMPORTANCE_LOW}]
489 };
490 ZmFilterRule.CONDITIONS[ZmFilterRule.C_SOCIAL] = {
491 		ops:        ZmFilterRule.TYPE_SELECT,
492 		opsOptions: [ZmFilterRule.OP_SOCIAL_FACEBOOK, ZmFilterRule.OP_SOCIAL_TWITTER, ZmFilterRule.OP_SOCIAL_LINKEDIN]
493 };
494 ZmFilterRule.CONDITIONS[ZmFilterRule.C_COMMUNITY] = {
495 		ops:        ZmFilterRule.TYPE_SELECT,
496 		opsOptions: [ZmFilterRule.OP_COMMUNITY_REQUESTS, ZmFilterRule.OP_COMMUNITY_CONTENT, ZmFilterRule.OP_COMMUNITY_CONNECTIONS]
497 };
498 ZmFilterRule.CONDITIONS[ZmFilterRule.C_ADDRESS] = {
499 		ops:		ZmFilterRule.TYPE_SELECT,
500 		opsOptions:	ZmFilterRule.MATCHING_OPS,
501 		value:		ZmFilterRule.TYPE_INPUT,
502 		valueMod:   ZmFilterRule.TYPE_SELECT,    
503 		vmOptions:	[{label: "all", value: "all"}, {label: "localpart", value: "localpart"}, {label:"domain", value: "domain"}]
504 };
505 ZmFilterRule.CONDITIONS[ZmFilterRule.C_LIST] = {
506 		ops:		ZmFilterRule.TYPE_SELECT,
507 		opsOptions:	[ZmFilterRule.OP_EXISTS, ZmFilterRule.OP_NOT_EXISTS]
508 };
509 ZmFilterRule.CONDITIONS[ZmFilterRule.C_BULK] = {
510 		ops:		ZmFilterRule.TYPE_SELECT,
511 		opsOptions:	[ZmFilterRule.OP_EXISTS, ZmFilterRule.OP_NOT_EXISTS]
512 };
513 
514 // map config keys to fields in a ZmCondition
515 ZmFilterRule.CONDITIONS_KEY = {"subjectMod": "subjectMod", "ops": "comparator",
516 							   "value": "value" /*, "valueMod": "valueModifier"*/};   //valueModifier was in the old CONDITIONS_KEY that I revived, but no longer seemed to work at all... no references to it.
517 
518 // listed in order we want to display them in the SELECT
519 ZmFilterRule.CONDITIONS_LIST = [
520 	ZmFilterRule.C_FROM,
521 	ZmFilterRule.C_TO,
522 	ZmFilterRule.C_CC,
523 	ZmFilterRule.C_TO_CC,
524     ZmFilterRule.C_BCC,
525 	ZmFilterRule.C_SUBJECT,
526 	ZmFilterRule.C_CONV,	
527 	ZmFilterRule.C_SIZE,
528 	ZmFilterRule.C_DATE,
529 	ZmFilterRule.C_BODY,
530 	ZmFilterRule.C_ATT,
531 	ZmFilterRule.C_MIME_HEADER,
532 	ZmFilterRule.C_ADDRBOOK,
533 	ZmFilterRule.C_INVITE,
534 	ZmFilterRule.C_SOCIAL,
535 	ZmFilterRule.C_COMMUNITY,
536 	ZmFilterRule.C_HEADER
537 ];
538 
539 // mark certain conditions as headers
540 ZmFilterRule.IS_HEADER = {};
541 ZmFilterRule.IS_HEADER[ZmFilterRule.C_SUBJECT]	= true;
542 ZmFilterRule.IS_HEADER[ZmFilterRule.C_HEADER]	= true;
543 
544 ZmFilterRule.IS_ADDRESS = {};
545 ZmFilterRule.IS_ADDRESS[ZmFilterRule.C_FROM]    = true;
546 ZmFilterRule.IS_ADDRESS[ZmFilterRule.C_TO]      = true;
547 ZmFilterRule.IS_ADDRESS[ZmFilterRule.C_CC]      = true;
548 ZmFilterRule.IS_ADDRESS[ZmFilterRule.C_TO_CC]   = true;
549 ZmFilterRule.IS_ADDRESS[ZmFilterRule.C_BCC]     = true;
550 
551 // Actions
552 
553 /**
554  * Defines the "keep" action type.
555  */
556 ZmFilterRule.A_KEEP			= "KEEP";
557 /**
558  * Defines the "keep" action type.
559  */
560 ZmFilterRule.A_KEEP_SENT	= "KEEP_SENT";
561 /**
562  * Defines the "folder" action type.
563  */
564 ZmFilterRule.A_FOLDER		= "FOLDER";
565 /**
566  * Defines the "discard" action type.
567  */
568 ZmFilterRule.A_DISCARD		= "DISCARD";
569 /**
570  * Defines the "stop" action type.
571  */
572 ZmFilterRule.A_STOP			= "STOP";
573 /**
574  * Defines the "flag" action type.
575  */
576 ZmFilterRule.A_FLAG			= "FLAG";
577 /**
578  * Defines the "tag" action type.
579  */
580 ZmFilterRule.A_TAG			= "TAG";
581 /**
582  * Defines the "forward" action type.
583  */
584 ZmFilterRule.A_FORWARD		= "FORWARD";
585 
586 /**
587  * Defines the "keep" action name.
588  */
589 ZmFilterRule.A_NAME_KEEP						= "actionKeep";
590 /**
591  * Defines the "keep" action name.
592  */
593 ZmFilterRule.A_NAME_KEEP_SENT					= "actionKeep";
594 /**
595  * Defines the "file into a folder" action name.
596  */
597 ZmFilterRule.A_NAME_FOLDER						= "actionFileInto";
598 /**
599  * Defines the "discard" action name.
600  */
601 ZmFilterRule.A_NAME_DISCARD						= "actionDiscard";
602 /**
603  * Defines the "stop" action name.
604  */
605 ZmFilterRule.A_NAME_STOP						= "actionStop";
606 /**
607  * Defines the "flag" action name.
608  */
609 ZmFilterRule.A_NAME_FLAG						= "actionFlag";
610 /**
611  * Defines the "tag" action name.
612  */
613 ZmFilterRule.A_NAME_TAG							= "actionTag";
614 /**
615  * Defines the "forward" action name.
616  */
617 ZmFilterRule.A_NAME_FORWARD						= "actionRedirect";
618 /**
619  * Defines the "reply" action name.
620  */
621 ZmFilterRule.A_REPLY                            = "actionReply";
622 /**
623  * Defines the "notify" action name.
624  */
625 ZmFilterRule.A_NOTIFY                           = "actionNotify";
626 
627 ZmFilterRule.A_VALUE = {};
628 ZmFilterRule.A_VALUE[ZmFilterRule.A_KEEP]		= ZmFilterRule.A_NAME_KEEP;
629 ZmFilterRule.A_VALUE[ZmFilterRule.A_KEEP_SENT]	= ZmFilterRule.A_NAME_KEEP_SENT;
630 ZmFilterRule.A_VALUE[ZmFilterRule.A_FOLDER]		= ZmFilterRule.A_NAME_FOLDER;
631 ZmFilterRule.A_VALUE[ZmFilterRule.A_DISCARD]	= ZmFilterRule.A_NAME_DISCARD;
632 ZmFilterRule.A_VALUE[ZmFilterRule.A_STOP]		= ZmFilterRule.A_NAME_STOP;
633 ZmFilterRule.A_VALUE[ZmFilterRule.A_FLAG]		= ZmFilterRule.A_NAME_FLAG;
634 ZmFilterRule.A_VALUE[ZmFilterRule.A_TAG]		= ZmFilterRule.A_NAME_TAG;
635 ZmFilterRule.A_VALUE[ZmFilterRule.A_FORWARD]	= ZmFilterRule.A_NAME_FORWARD;
636 ZmFilterRule.A_VALUE[ZmFilterRule.A_REPLY]      = ZmFilterRule.A_REPLY;
637 ZmFilterRule.A_VALUE[ZmFilterRule.A_NOTIFY]     = ZmFilterRule.A_NOTIFY;
638 
639 ZmFilterRule.A_VALUE_MAP = AjxUtil.valueHash(ZmFilterRule.A_VALUE);
640 
641 ZmFilterRule.A_LABEL = {};
642 ZmFilterRule.A_LABEL[ZmFilterRule.A_KEEP]		= ZmMsg.keepInInbox;
643 ZmFilterRule.A_LABEL[ZmFilterRule.A_KEEP_SENT]	= ZmMsg.keepInSent;
644 ZmFilterRule.A_LABEL[ZmFilterRule.A_FOLDER]		= ZmMsg.moveIntoFolder;
645 ZmFilterRule.A_LABEL[ZmFilterRule.A_DISCARD]	= ZmMsg.discard;
646 ZmFilterRule.A_LABEL[ZmFilterRule.A_STOP]		= ZmMsg.stopEvaluation;
647 ZmFilterRule.A_LABEL[ZmFilterRule.A_FLAG]		= ZmMsg.filterMarkAs;
648 ZmFilterRule.A_LABEL[ZmFilterRule.A_TAG]		= ZmMsg.tagWith;
649 ZmFilterRule.A_LABEL[ZmFilterRule.A_FORWARD]	= ZmMsg.redirectToAddress;
650 
651 /**
652  * This defines a hash of actions. The hash key is known as the action "name".
653  * It may or may not take an argument.
654  * 
655  * <p>
656  * The action parameters are:
657  * <ul>
658  * <li><b>param</b>			the type of input widget for the action's argument</li>
659  * <li><b>pOptions</b>		the name/value pairs for args</li>
660  * <li><b>precondition</b>	the setting that must be enabled for action to be available
661  * 								(preconditions are set by ZmFilterRulesController, after
662  * 								 settings are available)</li>
663  * </ul>
664  */
665 ZmFilterRule.ACTIONS = {};
666 ZmFilterRule.ACTIONS[ZmFilterRule.A_KEEP]		= {};
667 ZmFilterRule.ACTIONS[ZmFilterRule.A_KEEP_SENT]	= {};
668 ZmFilterRule.ACTIONS[ZmFilterRule.A_DISCARD] = {};
669 ZmFilterRule.ACTIONS[ZmFilterRule.A_STOP]		= {};
670 ZmFilterRule.ACTIONS[ZmFilterRule.A_FOLDER]	= {
671 	param:				ZmFilterRule.TYPE_FOLDER_PICKER
672 };
673 
674 ZmFilterRule.ACTIONS[ZmFilterRule.A_FLAG] = {
675 	param:				ZmFilterRule.TYPE_SELECT,
676 	// NOTE: If you change the order of these options, also change _setPreconditions!!!
677 	pOptions:			[{label: ZmMsg.read, value: ZmFilterRule.READ}, {label: ZmMsg.flagged, value: ZmFilterRule.FLAGGED}]
678 };
679 
680 ZmFilterRule.ACTIONS[ZmFilterRule.A_TAG] = {
681 	param:				ZmFilterRule.TYPE_TAG_PICKER
682 };
683 
684 ZmFilterRule.ACTIONS[ZmFilterRule.A_FORWARD] = {
685 	param:				ZmFilterRule.TYPE_INPUT,
686 	validationFunction:	ZmPref.validateEmail,
687 	errorMessage:		ZmMsg.errorInvalidEmail
688 };
689 
690 
691 ZmFilterRule.ACTIONS_LIST = [
692 	ZmFilterRule.A_KEEP,
693 	ZmFilterRule.A_DISCARD,
694 	ZmFilterRule.A_FOLDER,
695 	ZmFilterRule.A_TAG,
696 	ZmFilterRule.A_FLAG,
697 	ZmFilterRule.A_FORWARD
698 ];
699 
700 ZmFilterRule.ACTIONS_OUTGOING_LIST = [
701 	ZmFilterRule.A_KEEP_SENT,
702 	ZmFilterRule.A_DISCARD,
703 	ZmFilterRule.A_FOLDER,
704 	ZmFilterRule.A_TAG,
705 	ZmFilterRule.A_FLAG,
706 	ZmFilterRule.A_FORWARD
707 ];
708 
709 ZmFilterRule._setPreconditions =
710 function() {
711 	ZmFilterRule.CONDITIONS[ZmFilterRule.C_COMMUNITY].precondition = ZmSetting.SOCIAL_EXTERNAL_URL;
712 	ZmFilterRule.ACTIONS[ZmFilterRule.A_FLAG].pOptions[1].precondition = ZmSetting.FLAGGING_ENABLED;
713 	ZmFilterRule.ACTIONS[ZmFilterRule.A_TAG].precondition = ZmSetting.TAGGING_ENABLED;
714 	ZmFilterRule.ACTIONS[ZmFilterRule.A_FORWARD].precondition = ZmSetting.FILTERS_MAIL_FORWARDING_ENABLED;
715 	ZmFilterRule.ACTIONS[ZmFilterRule.A_DISCARD].precondition = ZmSetting.DISCARD_IN_FILTER_ENABLED;
716 };
717 
718 /**
719  * Returns array of social filter options based on COS settings
720  * @return {array} social filter options
721  */
722 ZmFilterRule.getSocialFilters = 
723 function() {
724 	var ops = [];
725 	var socialFilters = appCtxt.get(ZmSetting.SOCIAL_FILTERS_ENABLED);
726 	if (socialFilters && socialFilters.length) {
727 		for (var i=0; i<socialFilters.length; i++) {
728 			if (socialFilters[i].toLowerCase() == ZmFilterRule.C_FACEBOOK.toLowerCase()) {
729 				ops.push(ZmFilterRule.OP_SOCIAL_FACEBOOK)
730 			}
731 			else if (socialFilters[i].toLowerCase() == ZmFilterRule.C_TWITTER.toLowerCase() ) {
732 				ops.push(ZmFilterRule.OP_SOCIAL_TWITTER);	
733 			}
734 			else if (socialFilters[i].toLowerCase() == ZmFilterRule.C_LINKEDIN.toLowerCase()) {
735 				ops.push(ZmFilterRule.OP_SOCIAL_LINKEDIN);
736 			}
737 		}
738 	}
739 	return ops;
740 };
741 
742 /**
743  * Gets the rule condition grouping operator.
744  * 
745  * @return	{constant}	the operator (see <code>ZmFilterRule.GROUP_</code> constants)
746  */
747 ZmFilterRule.prototype.getGroupOp =
748 function() {
749 	return this.conditions.condition;
750 };
751 
752 /**
753  * Sets the rule condition grouping operator to "any" or "all".
754  *
755  * @param {constant}	groupOp		the grouping operator (see <code>ZmFilterRule.GROUP_</code> constants)
756  */
757 ZmFilterRule.prototype.setGroupOp =
758 function(groupOp) {
759 	this.conditions.condition = groupOp || ZmFilterRule.GROUP_ANY;
760 };
761 
762 ZmFilterRule.prototype.addCondition =
763 function(testType, comparator, value, subjectMod, caseSensitive) {
764 	//In dialog some tests are options under other tests
765 	if (testType == ZmFilterRule.TEST_SOCIAL && comparator) {
766 		testType = ZmFilterRule.OP_SOCIAL_MAP[comparator];
767 	}
768 	else if (testType == ZmFilterRule.TEST_COMMUNITY && comparator) {
769 		testType = ZmFilterRule.OP_COMMUNITY_MAP[comparator];
770 	}
771 	else if (testType == ZmFilterRule.TEST_ADDRBOOK && (comparator == ZmFilterRule.OP_IS_ME || comparator == ZmFilterRule.OP_NOT_ME)) {
772 		testType = ZmFilterRule.TEST_ME;
773 		value = null;
774 		comparator = comparator == ZmFilterRule.OP_IS_ME ? ZmFilterRule.OP_IS : ZmFilterRule.OP_NOT_IS;
775 	}
776 	else if (testType == ZmFilterRule.TEST_ADDRBOOK && value == "ranking") {
777 		testType = ZmFilterRule.TEST_RANKING;
778 		value = null;
779 	}
780 	else if (testType == ZmFilterRule.TEST_CONVERSATIONS && value == ZmFilterRule.C_BULK) {
781 		testType = ZmFilterRule.TEST_BULK;
782 		value = null;
783 	}
784 	else if (testType == ZmFilterRule.TEST_CONVERSATIONS && value == ZmFilterRule.C_LIST) {
785 		testType = ZmFilterRule.TEST_LIST;
786 		value = null;
787 	}
788 	else if (testType == ZmFilterRule.TEST_CONVERSATIONS && (value == ZmFilterRule.IMPORTANCE_HIGH || value == ZmFilterRule.IMPORTANCE_NORMAL || value == ZmFilterRule.IMPORTANCE_LOW))  {
789 		testType = ZmFilterRule.TEST_IMPORTANCE;
790 	}
791 	else if (testType == ZmFilterRule.TEST_CONVERSATIONS && (value == ZmFilterRule.READ || value == ZmFilterRule.PRIORITY || value == ZmFilterRule.FLAGGED)) {
792 		testType = ZmFilterRule.TEST_FLAGGED;
793 	}
794 	
795 	if (!this.conditions[testType]) {
796 		this.conditions[testType] = [];
797 	}
798 	
799 	var cdata = ZmFilterRule.getConditionData(testType, comparator, value, subjectMod, caseSensitive);
800 	this.conditions[testType].push(cdata);
801 	return cdata;
802 };
803 
804 /**
805  * Clears the rule conditions list.
806  * 
807  */
808 ZmFilterRule.prototype.clearConditions =
809 function() {
810 	this.conditions = {};
811 };
812 
813 /**
814  * Adds an action to the rule actions list.
815  *
816  * @param {constant}		actionType	the action type (see <code>ZmFilterRule.A_</code> constants)
817  * @param {String}	value		the value for the action
818  * 
819  */
820 ZmFilterRule.prototype.addAction =
821 function(actionType, value) {
822 	var action = ZmFilterRule.A_VALUE[actionType];
823 	if (!this.actions[action]) {
824 		this.actions[action] = [];
825 	}
826 
827 	var adata = ZmFilterRule.getActionData(actionType, value);
828 	this.actions[action].push(adata);
829 };
830 
831 /**
832  * Clears the rule actions list.
833  * 
834  */
835 ZmFilterRule.prototype.clearActions =
836 function() {
837 	this.actions = {};
838 };
839 
840 /**
841  * Checks if the if the rule is enabled.
842  * 
843  * @return	{Boolean}	<code>true</code> if the rule is enabled
844  */
845 ZmFilterRule.prototype.hasValidAction =
846 function() {
847 	for (var i in this.actions) {
848 		var actionIndex = ZmFilterRule.A_VALUE_MAP[i];
849 		var actionCfg = ZmFilterRule.ACTIONS[actionIndex];
850 		if ((actionIndex != ZmFilterRule.A_STOP && (ZmFilterRule.checkPreconditions(actionCfg))) || actionIndex == ZmFilterRule.A_FORWARD) {
851 			return true;
852 		}
853 	}
854 	return false;
855 };
856 
857 
858 // Static methods
859 
860 ZmFilterRule.getConditionData =
861 function(testType, comparator, value, subjectMod, caseSensitive) {
862 	var conditionData = {};
863 
864 	// add subject modifier
865 	if (subjectMod &&
866 		(testType == ZmFilterRule.TEST_HEADER ||
867 		 testType == ZmFilterRule.TEST_HEADER_EXISTS ||
868 		 testType == ZmFilterRule.TEST_ADDRBOOK ||
869 		 testType == ZmFilterRule.TEST_MIME_HEADER ||
870 		 testType == ZmFilterRule.TEST_ADDRESS ||
871 		 testType == ZmFilterRule.TEST_ME ||
872 		 testType == ZmFilterRule.TEST_RANKING))
873 	{
874 		conditionData.header = subjectMod;
875 	}
876 	
877 	var part = "all"; //default
878 	if (testType == ZmFilterRule.TEST_ADDRESS && value && typeof value == "string") {
879 		var valueArr = value.split(";"); 
880 		if (valueArr && valueArr.length > 1) {
881 			value = valueArr[0];
882 			part = valueArr[1];
883 		}
884 	}
885 	
886 	// normalize negative operator and add comparator
887 	var negativeOp;
888 	switch (comparator) {
889 		case ZmFilterRule.OP_NOT_IS:		negativeOp = ZmFilterRule.OP_IS; break;
890 		case ZmFilterRule.OP_NOT_CONTAINS:	negativeOp = ZmFilterRule.OP_CONTAINS; break;
891 		case ZmFilterRule.OP_NOT_MATCHES:	negativeOp = ZmFilterRule.OP_MATCHES; break;
892 		case ZmFilterRule.OP_NOT_EXISTS:	negativeOp = ZmFilterRule.OP_EXISTS; break;
893 		case ZmFilterRule.OP_NOT_UNDER:		negativeOp = ZmFilterRule.OP_UNDER; break;
894 		case ZmFilterRule.OP_NOT_OVER:		negativeOp = ZmFilterRule.OP_OVER; break;
895 		case ZmFilterRule.OP_NOT_BEFORE:	negativeOp = ZmFilterRule.OP_BEFORE; break;
896 		case ZmFilterRule.OP_NOT_AFTER:		negativeOp = ZmFilterRule.OP_AFTER; break;
897 		case ZmFilterRule.OP_NOT_IN:		negativeOp = ZmFilterRule.OP_IN; break;
898         case ZmFilterRule.OP_NOT_REPLIED:   negativeOp = ZmFilterRule.OP_IS_REPLIED; break;
899         case ZmFilterRule.OP_NOT_REQUESTED: negativeOp = ZmFilterRule.OP_IS_REQUESTED; break;
900         case ZmFilterRule.OP_NOT_READRECEIPT: negativeOp = ZmFilterRule.OP_CONTAINS; break;
901 		case ZmFilterRule.OP_NOT_CONV:      negativeOp = true; break;
902 	}
903 	if (negativeOp) {
904 		conditionData.negative = "1";
905 	}
906 	
907 	var compType = ZmFilterRule.COMP_TEST_MAP[testType];
908 	if (compType) {
909 		conditionData[compType] = ZmFilterRule.OP_VALUE[negativeOp || comparator];
910 	}
911 
912 	// add data value
913 	if (value) {
914 		switch (testType) {
915 			case ZmFilterRule.TEST_ADDRBOOK:	conditionData.type = value; break;
916 			case ZmFilterRule.TEST_SIZE:		conditionData.s = value; break;
917 			case ZmFilterRule.TEST_DATE:		conditionData.d = value; break;
918 			case ZmFilterRule.TEST_CONVERSATIONS: conditionData.where = value; break;
919 			case ZmFilterRule.TEST_IMPORTANCE:  conditionData.imp = value; break;
920 			case ZmFilterRule.TEST_ADDRESS:     conditionData.part = part;
921 												conditionData.value= value;
922 												break;
923 			case ZmFilterRule.TEST_FLAGGED:     conditionData.flagName = value; break;
924 			default:							conditionData.value = value; break;
925 		}
926 	}
927 
928 	if (testType == ZmFilterRule.TEST_INVITE) {
929 	    conditionData.method = [{_content:ZmFilterRule.OP_VALUE[negativeOp || comparator]}];
930 	}
931 	if (caseSensitive != null) {
932 		conditionData.caseSensitive = caseSensitive;
933 	}
934 
935 	return conditionData;
936 };
937 
938 ZmFilterRule.getActionData =
939 function(actionType, value) {
940 	var actionData = {};
941 
942 	switch (actionType) {
943 		case ZmFilterRule.A_FOLDER:			actionData.folderPath = value; break;
944 		case ZmFilterRule.A_FLAG:			actionData.flagName = value; break;
945 		case ZmFilterRule.A_TAG:			actionData.tagName = value; break;
946 		case ZmFilterRule.A_FORWARD:		actionData.a = value; break;
947 	}
948 
949 	return actionData;
950 };
951 
952 ZmFilterRule.getDummyRule =
953 function() {
954 	var rule = new ZmFilterRule(null, true, {}, {});
955 	var subjMod = ZmFilterRule.C_HEADER_VALUE[ZmFilterRule.C_SUBJECT];
956 	rule.addCondition(ZmFilterRule.TEST_HEADER, ZmFilterRule.OP_CONTAINS, "", subjMod);
957 	rule.addAction(ZmFilterRule.A_KEEP);
958 	return rule;
959 };
960 
961 ZmFilterRule.checkPreconditions = function(obj) {
962 
963     if (!ZmFilterRule.__preConditionsInitialized) {
964         ZmFilterRule.__preConditionsInitialized = true;
965         ZmFilterRule._setPreconditions();
966     }
967 
968 	return appCtxt.checkPrecondition(obj && obj.precondition ? obj.precondition : true);
969 };
970 
971 /**
972  * helper method to get the negative comparator
973  *
974  * @return	{constant}	the operator (see <code>ZmFilterRule.OP_</code> constants)
975  */
976 
977 ZmFilterRule.getNegativeComparator =
978 function(comparator) {
979     var negativeOp;
980     
981     switch (comparator) {
982 		case ZmFilterRule.OP_IS:		negativeOp = ZmFilterRule.OP_NOT_IS; break;
983 		case ZmFilterRule.OP_CONTAINS:	negativeOp = ZmFilterRule.OP_NOT_CONTAINS; break;
984 		case ZmFilterRule.OP_MATCHES:	negativeOp = ZmFilterRule.OP_NOT_MATCHES; break;
985 		case ZmFilterRule.OP_EXISTS:	negativeOp = ZmFilterRule.OP_NOT_EXISTS; break;
986 		case ZmFilterRule.OP_UNDER:		negativeOp = ZmFilterRule.OP_NOT_UNDER; break;
987 		case ZmFilterRule.OP_OVER:		negativeOp = ZmFilterRule.OP_NOT_OVER; break;
988 		case ZmFilterRule.OP_BEFORE:	negativeOp = ZmFilterRule.OP_NOT_BEFORE; break;
989 		case ZmFilterRule.OP_AFTER:		negativeOp = ZmFilterRule.OP_NOT_AFTER; break;
990 		case ZmFilterRule.OP_IN:		negativeOp = ZmFilterRule.OP_NOT_IN; break;
991         case ZmFilterRule.OP_IS_REPLIED:   negativeOp = ZmFilterRule.OP_NOT_REPLIED; break;
992         case ZmFilterRule.OP_IS_REQUESTED: negativeOp = ZmFilterRule.OP_NOT_REQUESTED; break;
993         case ZmFilterRule.OP_IS_READRECEIPT: negativeOp = ZmFilterRule.OP_NOT_CONTAINS; break;
994 	    case ZmFilterRule.OP_CONV_IS:  negativeOp = ZmFilterRule.OP_NOT_CONV; break;
995 	    case ZmFilterRule.OP_IS_ME:     negativeOp = ZmFilterRule.OP_NOT_ME; break;
996 	}
997     return negativeOp;
998 
999 };
1000