Utility.java revision eb7752bf695b2a93854e0bb89ddbbc2236bb9aea
196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/*
296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License.
696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at
796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and
1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License.
1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.android.email;
1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
19e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport com.android.email.provider.EmailContent;
20da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadlerimport com.android.email.provider.EmailContent.Account;
21da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadlerimport com.android.email.provider.EmailContent.AccountColumns;
22da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadlerimport com.android.email.provider.EmailContent.HostAuth;
23da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadlerimport com.android.email.provider.EmailContent.HostAuthColumns;
24e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport com.android.email.provider.EmailContent.Mailbox;
25e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport com.android.email.provider.EmailContent.MailboxColumns;
26e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport com.android.email.provider.EmailContent.Message;
27e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport com.android.email.provider.EmailContent.MessageColumns;
28e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler
29e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport android.content.ContentResolver;
30e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadlerimport android.database.Cursor;
31e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler
3296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.IOException;
3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.InputStream;
3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.InputStreamReader;
3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.UnsupportedEncodingException;
3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Date;
3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.codec.binary.Base64;
3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
40dadba9949895696108b31124fc0c6aa1a297ab1csatokimport android.content.Context;
41dadba9949895696108b31124fc0c6aa1a297ab1csatokimport android.content.res.TypedArray;
42dadba9949895696108b31124fc0c6aa1a297ab1csatokimport android.graphics.drawable.Drawable;
4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.text.Editable;
4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.widget.TextView;
4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class Utility {
4796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public final static String readInputStream(InputStream in, String encoding) throws IOException {
4896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        InputStreamReader reader = new InputStreamReader(in, encoding);
4996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        StringBuffer sb = new StringBuffer();
5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        int count;
5196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        char[] buf = new char[512];
5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        while ((count = reader.read(buf)) != -1) {
5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            sb.append(buf, 0, count);
5496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
5596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return sb.toString();
5696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
5796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
5896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public final static boolean arrayContains(Object[] a, Object o) {
5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        for (int i = 0, count = a.length; i < count; i++) {
6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (a[i].equals(o)) {
6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                return true;
6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return false;
6596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
6696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
6796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Combines the given array of Objects into a single string using the
6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * seperator character and each Object's toString() method. between each
7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * part.
7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
7296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param parts
7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param seperator
7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return
7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static String combine(Object[] parts, char seperator) {
7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (parts == null) {
7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return null;
7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        StringBuffer sb = new StringBuffer();
8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        for (int i = 0; i < parts.length; i++) {
8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            sb.append(parts[i].toString());
8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (i < parts.length - 1) {
8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                sb.append(seperator);
8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return sb.toString();
8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
9096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static String base64Decode(String encoded) {
9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (encoded == null) {
9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return null;
9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        byte[] decoded = new Base64().decode(encoded.getBytes());
9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return new String(decoded);
9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static String base64Encode(String s) {
9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (s == null) {
10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return s;
10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        byte[] encoded = new Base64().encode(s.getBytes());
10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return new String(encoded);
10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
10596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static boolean requiredFieldValid(TextView view) {
10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return view.getText() != null && view.getText().length() > 0;
10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static boolean requiredFieldValid(Editable s) {
11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return s != null && s.length() > 0;
11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Ensures that the given string starts and ends with the double quote character. The string is not modified in any way except to add the
11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * double quote character to start and end if it's not already there.
11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Rename this, because "quoteString()" can mean so many different things.
11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * sample -> "sample"
12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * "sample" -> "sample"
12296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * ""sample"" -> "sample"
12396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * "sample"" -> "sample"
12496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * sa"mp"le -> "sa"mp"le"
12596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * "sa"mp"le" -> "sa"mp"le"
12696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * (empty string) -> ""
12796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * " -> ""
12896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param s
12996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return
13096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
13196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static String quoteString(String s) {
13296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (s == null) {
13396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return null;
13496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
13596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (!s.matches("^\".*\"$")) {
13696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return "\"" + s + "\"";
13796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
13896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        else {
13996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return s;
14096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
14196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
14296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
14396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
14496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Apply quoting rules per IMAP RFC,
14596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * quoted          = DQUOTE *QUOTED-CHAR DQUOTE
14696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * QUOTED-CHAR     = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials
14796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * quoted-specials = DQUOTE / "\"
14896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
14996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This is used primarily for IMAP login, but might be useful elsewhere.
15096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
15196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * NOTE:  Not very efficient - you may wish to preflight this, or perhaps it should check
15296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * for trouble chars before calling the replace functions.
15396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
15496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param s The string to be quoted.
15596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return A copy of the string, having undergone quoting as described above
15696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
15796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static String imapQuoted(String s) {
15896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
15996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // First, quote any backslashes by replacing \ with \\
16096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // regex Pattern:  \\    (Java string const = \\\\)
16196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Substitute:     \\\\  (Java string const = \\\\\\\\)
16296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String result = s.replaceAll("\\\\", "\\\\\\\\");
16396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Then, quote any double-quotes by replacing " with \"
16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // regex Pattern:  "    (Java string const = \")
16696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Substitute:     \\"  (Java string const = \\\\\")
16796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        result = result.replaceAll("\"", "\\\\\"");
16896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
16996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // return string with quotes around it
17096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return "\"" + result + "\"";
17196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
17296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
17396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
17496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * A fast version of  URLDecoder.decode() that works only with UTF-8 and does only two
17596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * allocations. This version is around 3x as fast as the standard one and I'm using it
17696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * hundreds of times in places that slow down the UI, so it helps.
17796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static String fastUrlDecode(String s) {
17996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
18096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            byte[] bytes = s.getBytes("UTF-8");
18196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            byte ch;
18296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            int length = 0;
18396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            for (int i = 0, count = bytes.length; i < count; i++) {
18496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                ch = bytes[i];
18596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                if (ch == '%') {
18696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    int h = (bytes[i + 1] - '0');
18796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    int l = (bytes[i + 2] - '0');
18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    if (h > 9) {
18996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                        h -= 7;
19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    }
19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    if (l > 9) {
19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                        l -= 7;
19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    }
19496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    bytes[length] = (byte) ((h << 4) | l);
19596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    i += 2;
19696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                }
19796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                else if (ch == '+') {
19896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    bytes[length] = ' ';
19996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                }
20096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                else {
20196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    bytes[length] = bytes[i];
20296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                }
20396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                length++;
20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return new String(bytes, 0, length, "UTF-8");
20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
20796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        catch (UnsupportedEncodingException uee) {
20896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return null;
20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
21096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
21196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
21296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
21396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Returns true if the specified date is within today. Returns false otherwise.
21496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param date
21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return
21696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static boolean isDateToday(Date date) {
21896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // TODO But Calendar is so slowwwwwww....
21996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Date today = new Date();
22096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (date.getYear() == today.getYear() &&
22196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                date.getMonth() == today.getMonth() &&
22296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                date.getDate() == today.getDate()) {
22396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return true;
22496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
22596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return false;
22696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
22796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
22896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /*
22996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO disabled this method globally. It is used in all the settings screens but I just
23096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * noticed that an unrelated icon was dimmed. Android must share drawables internally.
23196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
23296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public static void setCompoundDrawablesAlpha(TextView view, int alpha) {
23396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project//        Drawable[] drawables = view.getCompoundDrawables();
23496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project//        for (Drawable drawable : drawables) {
23596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project//            if (drawable != null) {
23696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project//                drawable.setAlpha(alpha);
23796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project//            }
23896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project//        }
23996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
240e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler
241e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler    // TODO: unit test this
242e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler    public static String buildMailboxIdSelection(ContentResolver resolver, long mailboxId) {
243e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        // Setup default selection & args, then add to it as necessary
244e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        StringBuilder selection = new StringBuilder(
2456c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler                MessageColumns.FLAG_LOADED + " IN ("
2466c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler                + Message.FLAG_LOADED_PARTIAL + "," + Message.FLAG_LOADED_COMPLETE
2476c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler                + ") AND ");
248e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        if (mailboxId == Mailbox.QUERY_ALL_INBOXES
249e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            || mailboxId == Mailbox.QUERY_ALL_DRAFTS
250e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            || mailboxId == Mailbox.QUERY_ALL_OUTBOX) {
251e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            // query for all mailboxes of type INBOX, DRAFTS, or OUTBOX
252e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            int type;
253e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            if (mailboxId == Mailbox.QUERY_ALL_INBOXES) {
254e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                type = Mailbox.TYPE_INBOX;
255e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            } else if (mailboxId == Mailbox.QUERY_ALL_DRAFTS) {
256e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                type = Mailbox.TYPE_DRAFTS;
257e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            } else {
258e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                type = Mailbox.TYPE_OUTBOX;
259e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            }
260e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            StringBuilder inboxes = new StringBuilder();
261e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            Cursor c = resolver.query(Mailbox.CONTENT_URI,
262e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                        EmailContent.ID_PROJECTION,
263e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                        MailboxColumns.TYPE + "=? AND " + MailboxColumns.FLAG_VISIBLE + "=1",
264e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                        new String[] { Integer.toString(type) }, null);
265e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            // build an IN (mailboxId, ...) list
266e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            // TODO do this directly in the provider
267e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            while (c.moveToNext()) {
268e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                if (inboxes.length() != 0) {
269e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                    inboxes.append(",");
270e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                }
271e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler                inboxes.append(c.getLong(EmailContent.ID_PROJECTION_COLUMN));
272e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            }
273e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            c.close();
274e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            selection.append(MessageColumns.MAILBOX_KEY + " IN ");
275e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            selection.append("(").append(inboxes).append(")");
276e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        } else  if (mailboxId == Mailbox.QUERY_ALL_UNREAD) {
277e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            selection.append(Message.FLAG_READ + "=0");
278e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        } else if (mailboxId == Mailbox.QUERY_ALL_FAVORITES) {
279e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            selection.append(Message.FLAG_FAVORITE + "=1");
280e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        } else {
281e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler            selection.append(MessageColumns.MAILBOX_KEY + "=" + mailboxId);
282e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        }
283e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler        return selection.toString();
284e1f0b0a9bcc78ade7f3b2ac540705701f19cd6cdAndrew Stadler    }
285dadba9949895696108b31124fc0c6aa1a297ab1csatok
286dadba9949895696108b31124fc0c6aa1a297ab1csatok    public static class FolderProperties {
287dadba9949895696108b31124fc0c6aa1a297ab1csatok
288dadba9949895696108b31124fc0c6aa1a297ab1csatok        private static FolderProperties sInstance;
289dadba9949895696108b31124fc0c6aa1a297ab1csatok
290dadba9949895696108b31124fc0c6aa1a297ab1csatok        // Caches for frequently accessed resources.
291dadba9949895696108b31124fc0c6aa1a297ab1csatok        private String[] mSpecialMailbox = new String[] {};
292dadba9949895696108b31124fc0c6aa1a297ab1csatok        private TypedArray mSpecialMailboxDrawable;
293dadba9949895696108b31124fc0c6aa1a297ab1csatok        private Drawable mDefaultMailboxDrawable;
2943786cab2aa1776e92fc67af3931a76cd8b848b48satok        private Drawable mSummaryStarredMailboxDrawable;
2953786cab2aa1776e92fc67af3931a76cd8b848b48satok        private Drawable mSummaryCombinedInboxDrawable;
296dadba9949895696108b31124fc0c6aa1a297ab1csatok
297dadba9949895696108b31124fc0c6aa1a297ab1csatok        private FolderProperties(Context context) {
298fa52e6c95674aef6461a5cfc670a052e1c5b7f2fAndrew Stadler            mSpecialMailbox = context.getResources().getStringArray(R.array.mailbox_display_names);
299dadba9949895696108b31124fc0c6aa1a297ab1csatok            for (int i = 0; i < mSpecialMailbox.length; ++i) {
300dadba9949895696108b31124fc0c6aa1a297ab1csatok                if ("".equals(mSpecialMailbox[i])) {
301dadba9949895696108b31124fc0c6aa1a297ab1csatok                    // there is no localized name, so use the display name from the server
302dadba9949895696108b31124fc0c6aa1a297ab1csatok                    mSpecialMailbox[i] = null;
303dadba9949895696108b31124fc0c6aa1a297ab1csatok                }
304dadba9949895696108b31124fc0c6aa1a297ab1csatok            }
305dadba9949895696108b31124fc0c6aa1a297ab1csatok            mSpecialMailboxDrawable =
306fa52e6c95674aef6461a5cfc670a052e1c5b7f2fAndrew Stadler                context.getResources().obtainTypedArray(R.array.mailbox_display_icons);
307dadba9949895696108b31124fc0c6aa1a297ab1csatok            mDefaultMailboxDrawable =
308dadba9949895696108b31124fc0c6aa1a297ab1csatok                context.getResources().getDrawable(R.drawable.ic_list_folder);
3093786cab2aa1776e92fc67af3931a76cd8b848b48satok            mSummaryStarredMailboxDrawable =
3103786cab2aa1776e92fc67af3931a76cd8b848b48satok                context.getResources().getDrawable(R.drawable.ic_list_starred);
3113786cab2aa1776e92fc67af3931a76cd8b848b48satok            mSummaryCombinedInboxDrawable =
3123786cab2aa1776e92fc67af3931a76cd8b848b48satok                context.getResources().getDrawable(R.drawable.ic_list_combined_inbox);
313dadba9949895696108b31124fc0c6aa1a297ab1csatok        }
314dadba9949895696108b31124fc0c6aa1a297ab1csatok
315dadba9949895696108b31124fc0c6aa1a297ab1csatok        public static FolderProperties getInstance(Context context) {
316dadba9949895696108b31124fc0c6aa1a297ab1csatok            if (sInstance == null) {
317dadba9949895696108b31124fc0c6aa1a297ab1csatok                synchronized (FolderProperties.class) {
318dadba9949895696108b31124fc0c6aa1a297ab1csatok                    if (sInstance == null) {
319dadba9949895696108b31124fc0c6aa1a297ab1csatok                        sInstance = new FolderProperties(context);
320dadba9949895696108b31124fc0c6aa1a297ab1csatok                    }
321dadba9949895696108b31124fc0c6aa1a297ab1csatok                }
322dadba9949895696108b31124fc0c6aa1a297ab1csatok            }
323dadba9949895696108b31124fc0c6aa1a297ab1csatok            return sInstance;
324dadba9949895696108b31124fc0c6aa1a297ab1csatok        }
325dadba9949895696108b31124fc0c6aa1a297ab1csatok
326dadba9949895696108b31124fc0c6aa1a297ab1csatok        /**
327dadba9949895696108b31124fc0c6aa1a297ab1csatok         * Lookup names of localized special mailboxes
328dadba9949895696108b31124fc0c6aa1a297ab1csatok         * @param type
329dadba9949895696108b31124fc0c6aa1a297ab1csatok         * @return Localized strings
330dadba9949895696108b31124fc0c6aa1a297ab1csatok         */
331dadba9949895696108b31124fc0c6aa1a297ab1csatok        public String getDisplayName(int type) {
332dadba9949895696108b31124fc0c6aa1a297ab1csatok            if (type < mSpecialMailbox.length) {
333dadba9949895696108b31124fc0c6aa1a297ab1csatok                return mSpecialMailbox[type];
334dadba9949895696108b31124fc0c6aa1a297ab1csatok            }
335dadba9949895696108b31124fc0c6aa1a297ab1csatok            return null;
336dadba9949895696108b31124fc0c6aa1a297ab1csatok        }
337dadba9949895696108b31124fc0c6aa1a297ab1csatok
338dadba9949895696108b31124fc0c6aa1a297ab1csatok        /**
339dadba9949895696108b31124fc0c6aa1a297ab1csatok         * Lookup icons of special mailboxes
340dadba9949895696108b31124fc0c6aa1a297ab1csatok         * @param type
341dadba9949895696108b31124fc0c6aa1a297ab1csatok         * @return icon's drawable
342dadba9949895696108b31124fc0c6aa1a297ab1csatok         */
3434bb52e36b18ab5e2fb9242069611bc0ef6116c09satok        public Drawable getIconIds(int type) {
344dadba9949895696108b31124fc0c6aa1a297ab1csatok            if (type < mSpecialMailboxDrawable.length()) {
345dadba9949895696108b31124fc0c6aa1a297ab1csatok                return mSpecialMailboxDrawable.getDrawable(type);
346dadba9949895696108b31124fc0c6aa1a297ab1csatok            }
347dadba9949895696108b31124fc0c6aa1a297ab1csatok            return mDefaultMailboxDrawable;
348dadba9949895696108b31124fc0c6aa1a297ab1csatok        }
3493786cab2aa1776e92fc67af3931a76cd8b848b48satok
3503786cab2aa1776e92fc67af3931a76cd8b848b48satok        public Drawable getSummaryMailboxIconIds(long mailboxKey) {
3513786cab2aa1776e92fc67af3931a76cd8b848b48satok            if (mailboxKey == Mailbox.QUERY_ALL_INBOXES) {
3523786cab2aa1776e92fc67af3931a76cd8b848b48satok                return mSummaryCombinedInboxDrawable;
3533786cab2aa1776e92fc67af3931a76cd8b848b48satok            } else if (mailboxKey == Mailbox.QUERY_ALL_FAVORITES) {
3543786cab2aa1776e92fc67af3931a76cd8b848b48satok                return mSummaryStarredMailboxDrawable;
3553786cab2aa1776e92fc67af3931a76cd8b848b48satok            } else if (mailboxKey == Mailbox.QUERY_ALL_DRAFTS) {
3563786cab2aa1776e92fc67af3931a76cd8b848b48satok                return mSpecialMailboxDrawable.getDrawable(Mailbox.TYPE_DRAFTS);
3573786cab2aa1776e92fc67af3931a76cd8b848b48satok            } else if (mailboxKey == Mailbox.QUERY_ALL_OUTBOX) {
3583786cab2aa1776e92fc67af3931a76cd8b848b48satok                return mSpecialMailboxDrawable.getDrawable(Mailbox.TYPE_OUTBOX);
3593786cab2aa1776e92fc67af3931a76cd8b848b48satok            }
3603786cab2aa1776e92fc67af3931a76cd8b848b48satok            return mDefaultMailboxDrawable;
3613786cab2aa1776e92fc67af3931a76cd8b848b48satok        }
362dadba9949895696108b31124fc0c6aa1a297ab1csatok    }
363da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler
364da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler    private final static String HOSTAUTH_WHERE_CREDENTIALS = HostAuthColumns.ADDRESS + " like ?"
365da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler            + " and " + HostAuthColumns.LOGIN + " like ?"
366da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler            + " and " + HostAuthColumns.PROTOCOL + " not like \"smtp\"";
367da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler    private final static String ACCOUNT_WHERE_HOSTAUTH = AccountColumns.HOST_AUTH_KEY_RECV + "=?";
368da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler
369da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler    /**
370da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     * Look for an existing account with the same username & server
371da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     *
372da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     * @param context a system context
373da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     * @param allowAccountId this account Id will not trigger (when editing an existing account)
374da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     * @param hostName the server
375da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     * @param userLogin the user login string
376da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     * @result null = no dupes found.  non-null = dupe account's display name
377da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler     */
378da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler    public static String findDuplicateAccount(Context context, long allowAccountId, String hostName,
379da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler            String userLogin) {
380da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler        ContentResolver resolver = context.getContentResolver();
381da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler        Cursor c = resolver.query(HostAuth.CONTENT_URI, HostAuth.ID_PROJECTION,
382da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                HOSTAUTH_WHERE_CREDENTIALS, new String[] { hostName, userLogin }, null);
383da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler        try {
384da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler            while (c.moveToNext()) {
385da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                long hostAuthId = c.getLong(HostAuth.ID_PROJECTION_COLUMN);
386da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                // Find account with matching hostauthrecv key, and return its display name
387da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                Cursor c2 = resolver.query(Account.CONTENT_URI, Account.ID_PROJECTION,
388da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                        ACCOUNT_WHERE_HOSTAUTH, new String[] { Long.toString(hostAuthId) }, null);
389da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                try {
390da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                    while (c2.moveToNext()) {
391da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                        long accountId = c2.getLong(Account.ID_PROJECTION_COLUMN);
392da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                        if (accountId != allowAccountId) {
393da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                            Account account = Account.restoreAccountWithId(context, accountId);
394da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                            if (account != null) {
395da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                                return account.mDisplayName;
396da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                            }
397da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                        }
398da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                    }
399da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                } finally {
400da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                    c2.close();
401da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler                }
402da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler            }
403da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler        } finally {
404da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler            c.close();
405da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler        }
406da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler
407da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler        return null;
408da8836a76cd8a6eaa7e3693eeacc6393870b2066Andrew Stadler    }
409eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler
410eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler    /**
411eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler     * Generate a random message-id header for locally-generated messages.
412eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler     */
413eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler    public static String generateMessageId() {
414eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        StringBuffer sb = new StringBuffer();
415eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        sb.append("<");
416eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        for (int i = 0; i < 24; i++) {
417eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler            sb.append(Integer.toString((int)(Math.random() * 35), 36));
418eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        }
419eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        sb.append(".");
420eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        sb.append(Long.toString(System.currentTimeMillis()));
421eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        sb.append("@email.android.com>");
422eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler        return sb.toString();
423eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler    }
424eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler
42596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}
426