• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.email.mail.store.imap;
18 
19 import com.android.emailcommon.Logging;
20 
21 import android.util.Log;
22 
23 import java.util.ArrayList;
24 
25 /**
26  * Utility methods for use with IMAP.
27  */
28 public class ImapUtility {
29     /**
30      * Apply quoting rules per IMAP RFC,
31      * quoted          = DQUOTE *QUOTED-CHAR DQUOTE
32      * QUOTED-CHAR     = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials
33      * quoted-specials = DQUOTE / "\"
34      *
35      * This is used primarily for IMAP login, but might be useful elsewhere.
36      *
37      * NOTE:  Not very efficient - you may wish to preflight this, or perhaps it should check
38      * for trouble chars before calling the replace functions.
39      *
40      * @param s The string to be quoted.
41      * @return A copy of the string, having undergone quoting as described above
42      */
imapQuoted(String s)43     public static String imapQuoted(String s) {
44 
45         // First, quote any backslashes by replacing \ with \\
46         // regex Pattern:  \\    (Java string const = \\\\)
47         // Substitute:     \\\\  (Java string const = \\\\\\\\)
48         String result = s.replaceAll("\\\\", "\\\\\\\\");
49 
50         // Then, quote any double-quotes by replacing " with \"
51         // regex Pattern:  "    (Java string const = \")
52         // Substitute:     \\"  (Java string const = \\\\\")
53         result = result.replaceAll("\"", "\\\\\"");
54 
55         // return string with quotes around it
56         return "\"" + result + "\"";
57     }
58 
59     /**
60      * Gets all of the values in a sequence set per RFC 3501. Any ranges are expanded into a
61      * list of individual numbers. If the set is invalid, an empty array is returned.
62      * <pre>
63      * sequence-number = nz-number / "*"
64      * sequence-range  = sequence-number ":" sequence-number
65      * sequence-set    = (sequence-number / sequence-range) *("," sequence-set)
66      * </pre>
67      */
getImapSequenceValues(String set)68     public static String[] getImapSequenceValues(String set) {
69         ArrayList<String> list = new ArrayList<String>();
70         if (set != null) {
71             String[] setItems = set.split(",");
72             for (String item : setItems) {
73                 if (item.indexOf(':') == -1) {
74                     // simple item
75                     try {
76                         Integer.parseInt(item); // Don't need the value; just ensure it's valid
77                         list.add(item);
78                     } catch (NumberFormatException e) {
79                         Log.d(Logging.LOG_TAG, "Invalid UID value", e);
80                     }
81                 } else {
82                     // range
83                     for (String rangeItem : getImapRangeValues(item)) {
84                         list.add(rangeItem);
85                     }
86                 }
87             }
88         }
89         String[] stringList = new String[list.size()];
90         return list.toArray(stringList);
91     }
92 
93     /**
94      * Expand the given number range into a list of individual numbers. If the range is not valid,
95      * an empty array is returned.
96      * <pre>
97      * sequence-number = nz-number / "*"
98      * sequence-range  = sequence-number ":" sequence-number
99      * sequence-set    = (sequence-number / sequence-range) *("," sequence-set)
100      * </pre>
101      */
getImapRangeValues(String range)102     public static String[] getImapRangeValues(String range) {
103         ArrayList<String> list = new ArrayList<String>();
104         try {
105             if (range != null) {
106                 int colonPos = range.indexOf(':');
107                 if (colonPos > 0) {
108                     int first  = Integer.parseInt(range.substring(0, colonPos));
109                     int second = Integer.parseInt(range.substring(colonPos + 1));
110                     if (first < second) {
111                         for (int i = first; i <= second; i++) {
112                             list.add(Integer.toString(i));
113                         }
114                     } else {
115                         for (int i = first; i >= second; i--) {
116                             list.add(Integer.toString(i));
117                         }
118                     }
119                 }
120             }
121         } catch (NumberFormatException e) {
122             Log.d(Logging.LOG_TAG, "Invalid range value", e);
123         }
124         String[] stringList = new String[list.size()];
125         return list.toArray(stringList);
126     }
127 }
128