15c523858385176c33a7456bb84035de78552d22dMarc Blank/* 25c523858385176c33a7456bb84035de78552d22dMarc Blank * Copyright (C) 2011 The Android Open Source Project 35c523858385176c33a7456bb84035de78552d22dMarc Blank * 45c523858385176c33a7456bb84035de78552d22dMarc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 55c523858385176c33a7456bb84035de78552d22dMarc Blank * you may not use this file except in compliance with the License. 65c523858385176c33a7456bb84035de78552d22dMarc Blank * You may obtain a copy of the License at 75c523858385176c33a7456bb84035de78552d22dMarc Blank * 85c523858385176c33a7456bb84035de78552d22dMarc Blank * http://www.apache.org/licenses/LICENSE-2.0 95c523858385176c33a7456bb84035de78552d22dMarc Blank * 105c523858385176c33a7456bb84035de78552d22dMarc Blank * Unless required by applicable law or agreed to in writing, software 115c523858385176c33a7456bb84035de78552d22dMarc Blank * distributed under the License is distributed on an "AS IS" BASIS, 125c523858385176c33a7456bb84035de78552d22dMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c523858385176c33a7456bb84035de78552d22dMarc Blank * See the License for the specific language governing permissions and 145c523858385176c33a7456bb84035de78552d22dMarc Blank * limitations under the License. 155c523858385176c33a7456bb84035de78552d22dMarc Blank */ 165c523858385176c33a7456bb84035de78552d22dMarc Blank 175c523858385176c33a7456bb84035de78552d22dMarc Blankpackage com.android.email.mail.store.imap; 185c523858385176c33a7456bb84035de78552d22dMarc Blank 195c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.Logging; 205c523858385176c33a7456bb84035de78552d22dMarc Blank 215c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.util.Log; 225c523858385176c33a7456bb84035de78552d22dMarc Blank 235c523858385176c33a7456bb84035de78552d22dMarc Blankimport java.util.ArrayList; 245c523858385176c33a7456bb84035de78552d22dMarc Blank 255c523858385176c33a7456bb84035de78552d22dMarc Blank/** 265c523858385176c33a7456bb84035de78552d22dMarc Blank * Utility methods for use with IMAP. 275c523858385176c33a7456bb84035de78552d22dMarc Blank */ 285c523858385176c33a7456bb84035de78552d22dMarc Blankpublic class ImapUtility { 295c523858385176c33a7456bb84035de78552d22dMarc Blank /** 305c523858385176c33a7456bb84035de78552d22dMarc Blank * Apply quoting rules per IMAP RFC, 315c523858385176c33a7456bb84035de78552d22dMarc Blank * quoted = DQUOTE *QUOTED-CHAR DQUOTE 325c523858385176c33a7456bb84035de78552d22dMarc Blank * QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials 335c523858385176c33a7456bb84035de78552d22dMarc Blank * quoted-specials = DQUOTE / "\" 345c523858385176c33a7456bb84035de78552d22dMarc Blank * 355c523858385176c33a7456bb84035de78552d22dMarc Blank * This is used primarily for IMAP login, but might be useful elsewhere. 365c523858385176c33a7456bb84035de78552d22dMarc Blank * 375c523858385176c33a7456bb84035de78552d22dMarc Blank * NOTE: Not very efficient - you may wish to preflight this, or perhaps it should check 385c523858385176c33a7456bb84035de78552d22dMarc Blank * for trouble chars before calling the replace functions. 395c523858385176c33a7456bb84035de78552d22dMarc Blank * 405c523858385176c33a7456bb84035de78552d22dMarc Blank * @param s The string to be quoted. 415c523858385176c33a7456bb84035de78552d22dMarc Blank * @return A copy of the string, having undergone quoting as described above 425c523858385176c33a7456bb84035de78552d22dMarc Blank */ 435c523858385176c33a7456bb84035de78552d22dMarc Blank public static String imapQuoted(String s) { 445c523858385176c33a7456bb84035de78552d22dMarc Blank 455c523858385176c33a7456bb84035de78552d22dMarc Blank // First, quote any backslashes by replacing \ with \\ 465c523858385176c33a7456bb84035de78552d22dMarc Blank // regex Pattern: \\ (Java string const = \\\\) 475c523858385176c33a7456bb84035de78552d22dMarc Blank // Substitute: \\\\ (Java string const = \\\\\\\\) 485c523858385176c33a7456bb84035de78552d22dMarc Blank String result = s.replaceAll("\\\\", "\\\\\\\\"); 495c523858385176c33a7456bb84035de78552d22dMarc Blank 505c523858385176c33a7456bb84035de78552d22dMarc Blank // Then, quote any double-quotes by replacing " with \" 515c523858385176c33a7456bb84035de78552d22dMarc Blank // regex Pattern: " (Java string const = \") 525c523858385176c33a7456bb84035de78552d22dMarc Blank // Substitute: \\" (Java string const = \\\\\") 535c523858385176c33a7456bb84035de78552d22dMarc Blank result = result.replaceAll("\"", "\\\\\""); 545c523858385176c33a7456bb84035de78552d22dMarc Blank 555c523858385176c33a7456bb84035de78552d22dMarc Blank // return string with quotes around it 565c523858385176c33a7456bb84035de78552d22dMarc Blank return "\"" + result + "\""; 575c523858385176c33a7456bb84035de78552d22dMarc Blank } 585c523858385176c33a7456bb84035de78552d22dMarc Blank 595c523858385176c33a7456bb84035de78552d22dMarc Blank /** 605c523858385176c33a7456bb84035de78552d22dMarc Blank * Gets all of the values in a sequence set per RFC 3501. Any ranges are expanded into a 615c523858385176c33a7456bb84035de78552d22dMarc Blank * list of individual numbers. If the set is invalid, an empty array is returned. 625c523858385176c33a7456bb84035de78552d22dMarc Blank * <pre> 635c523858385176c33a7456bb84035de78552d22dMarc Blank * sequence-number = nz-number / "*" 645c523858385176c33a7456bb84035de78552d22dMarc Blank * sequence-range = sequence-number ":" sequence-number 655c523858385176c33a7456bb84035de78552d22dMarc Blank * sequence-set = (sequence-number / sequence-range) *("," sequence-set) 665c523858385176c33a7456bb84035de78552d22dMarc Blank * </pre> 675c523858385176c33a7456bb84035de78552d22dMarc Blank */ 685c523858385176c33a7456bb84035de78552d22dMarc Blank public static String[] getImapSequenceValues(String set) { 695c523858385176c33a7456bb84035de78552d22dMarc Blank ArrayList<String> list = new ArrayList<String>(); 705c523858385176c33a7456bb84035de78552d22dMarc Blank if (set != null) { 715c523858385176c33a7456bb84035de78552d22dMarc Blank String[] setItems = set.split(","); 725c523858385176c33a7456bb84035de78552d22dMarc Blank for (String item : setItems) { 735c523858385176c33a7456bb84035de78552d22dMarc Blank if (item.indexOf(':') == -1) { 745c523858385176c33a7456bb84035de78552d22dMarc Blank // simple item 755c523858385176c33a7456bb84035de78552d22dMarc Blank try { 765c523858385176c33a7456bb84035de78552d22dMarc Blank Integer.parseInt(item); // Don't need the value; just ensure it's valid 775c523858385176c33a7456bb84035de78552d22dMarc Blank list.add(item); 785c523858385176c33a7456bb84035de78552d22dMarc Blank } catch (NumberFormatException e) { 795c523858385176c33a7456bb84035de78552d22dMarc Blank Log.d(Logging.LOG_TAG, "Invalid UID value", e); 805c523858385176c33a7456bb84035de78552d22dMarc Blank } 815c523858385176c33a7456bb84035de78552d22dMarc Blank } else { 825c523858385176c33a7456bb84035de78552d22dMarc Blank // range 835c523858385176c33a7456bb84035de78552d22dMarc Blank for (String rangeItem : getImapRangeValues(item)) { 845c523858385176c33a7456bb84035de78552d22dMarc Blank list.add(rangeItem); 855c523858385176c33a7456bb84035de78552d22dMarc Blank } 865c523858385176c33a7456bb84035de78552d22dMarc Blank } 875c523858385176c33a7456bb84035de78552d22dMarc Blank } 885c523858385176c33a7456bb84035de78552d22dMarc Blank } 895c523858385176c33a7456bb84035de78552d22dMarc Blank String[] stringList = new String[list.size()]; 905c523858385176c33a7456bb84035de78552d22dMarc Blank return list.toArray(stringList); 915c523858385176c33a7456bb84035de78552d22dMarc Blank } 925c523858385176c33a7456bb84035de78552d22dMarc Blank 935c523858385176c33a7456bb84035de78552d22dMarc Blank /** 945c523858385176c33a7456bb84035de78552d22dMarc Blank * Expand the given number range into a list of individual numbers. If the range is not valid, 955c523858385176c33a7456bb84035de78552d22dMarc Blank * an empty array is returned. 965c523858385176c33a7456bb84035de78552d22dMarc Blank * <pre> 975c523858385176c33a7456bb84035de78552d22dMarc Blank * sequence-number = nz-number / "*" 985c523858385176c33a7456bb84035de78552d22dMarc Blank * sequence-range = sequence-number ":" sequence-number 995c523858385176c33a7456bb84035de78552d22dMarc Blank * sequence-set = (sequence-number / sequence-range) *("," sequence-set) 1005c523858385176c33a7456bb84035de78552d22dMarc Blank * </pre> 1015c523858385176c33a7456bb84035de78552d22dMarc Blank */ 1025c523858385176c33a7456bb84035de78552d22dMarc Blank public static String[] getImapRangeValues(String range) { 1035c523858385176c33a7456bb84035de78552d22dMarc Blank ArrayList<String> list = new ArrayList<String>(); 1045c523858385176c33a7456bb84035de78552d22dMarc Blank try { 1055c523858385176c33a7456bb84035de78552d22dMarc Blank if (range != null) { 1065c523858385176c33a7456bb84035de78552d22dMarc Blank int colonPos = range.indexOf(':'); 1075c523858385176c33a7456bb84035de78552d22dMarc Blank if (colonPos > 0) { 1085c523858385176c33a7456bb84035de78552d22dMarc Blank int first = Integer.parseInt(range.substring(0, colonPos)); 1095c523858385176c33a7456bb84035de78552d22dMarc Blank int second = Integer.parseInt(range.substring(colonPos + 1)); 1105c523858385176c33a7456bb84035de78552d22dMarc Blank if (first < second) { 1115c523858385176c33a7456bb84035de78552d22dMarc Blank for (int i = first; i <= second; i++) { 1125c523858385176c33a7456bb84035de78552d22dMarc Blank list.add(Integer.toString(i)); 1135c523858385176c33a7456bb84035de78552d22dMarc Blank } 1145c523858385176c33a7456bb84035de78552d22dMarc Blank } else { 1155c523858385176c33a7456bb84035de78552d22dMarc Blank for (int i = first; i >= second; i--) { 1165c523858385176c33a7456bb84035de78552d22dMarc Blank list.add(Integer.toString(i)); 1175c523858385176c33a7456bb84035de78552d22dMarc Blank } 1185c523858385176c33a7456bb84035de78552d22dMarc Blank } 1195c523858385176c33a7456bb84035de78552d22dMarc Blank } 1205c523858385176c33a7456bb84035de78552d22dMarc Blank } 1215c523858385176c33a7456bb84035de78552d22dMarc Blank } catch (NumberFormatException e) { 1225c523858385176c33a7456bb84035de78552d22dMarc Blank Log.d(Logging.LOG_TAG, "Invalid range value", e); 1235c523858385176c33a7456bb84035de78552d22dMarc Blank } 1245c523858385176c33a7456bb84035de78552d22dMarc Blank String[] stringList = new String[list.size()]; 1255c523858385176c33a7456bb84035de78552d22dMarc Blank return list.toArray(stringList); 1265c523858385176c33a7456bb84035de78552d22dMarc Blank } 1275c523858385176c33a7456bb84035de78552d22dMarc Blank} 128