1988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner/* 2988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * Copyright (C) 2014 The Android Open Source Project 3988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * 4988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * Licensed under the Apache License, Version 2.0 (the "License"); 5988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * you may not use this file except in compliance with the License. 6988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * You may obtain a copy of the License at 7988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * 8988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * http://www.apache.org/licenses/LICENSE-2.0 9988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * 10988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * Unless required by applicable law or agreed to in writing, software 11988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * distributed under the License is distributed on an "AS IS" BASIS, 12988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * See the License for the specific language governing permissions and 14988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner * limitations under the License. 15988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner */ 16988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 17988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shraunerpackage com.android.emailcommon.utility; 18988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 199a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport android.test.AndroidTestCase; 209a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport android.test.IsolatedContext; 219a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport android.test.mock.MockContentResolver; 22988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shraunerimport android.test.suitebuilder.annotation.SmallTest; 239a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport android.text.TextUtils; 249a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 259a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport com.android.emailcommon.utility.Utility.NewFileCreator; 269a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 279a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport java.io.File; 289a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerimport java.io.IOException; 29988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shraunerimport java.text.ParseException; 30988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shraunerimport java.util.Calendar; 31988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shraunerimport java.util.GregorianCalendar; 32988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shraunerimport java.util.TimeZone; 33988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 34988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner@SmallTest 359a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantlerpublic class UtilityTest extends AndroidTestCase { 36988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner private void testParseDateTimesHelper(String date, int year, int month, 37988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner int day, int hour, int minute, int second) throws Exception { 38988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner GregorianCalendar cal = Utility.parseDateTimeToCalendar(date); 39988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(year, cal.get(Calendar.YEAR)); 40988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(month, cal.get(Calendar.MONTH) + 1); 41988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(day, cal.get(Calendar.DAY_OF_MONTH)); 42988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(hour, cal.get(Calendar.HOUR_OF_DAY)); 43988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(minute, cal.get(Calendar.MINUTE)); 44988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(second, cal.get(Calendar.SECOND)); 45988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } 46988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 47988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner @SmallTest 48988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner public void testParseDateTimes() throws Exception { 49988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner testParseDateTimesHelper("20090211T180303Z", 2009, 2, 11, 18, 3, 3); 50988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner testParseDateTimesHelper("20090211", 2009, 2, 11, 0, 0, 0); 51988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner try { 52988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner testParseDateTimesHelper("200902", 0, 0, 0, 0, 0, 0); 53988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner fail("Expected ParseException"); 54988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } catch (ParseException e) { 55988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner // expected 56988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } 57988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } 58988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 59988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner private void testParseEmailDateTimeHelper(String date, int year, int month, 60988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner int day, int hour, int minute, int second, int millis) throws Exception { 61988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner GregorianCalendar cal = new GregorianCalendar(year, month - 1, day, 62988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner hour, minute, second); 63988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner cal.setTimeZone(TimeZone.getTimeZone("GMT")); 64988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner long timeInMillis = Utility.parseEmailDateTimeToMillis(date); 65988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner assertEquals(cal.getTimeInMillis() + millis, timeInMillis); 66988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } 67988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 68988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner @SmallTest 69988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner public void testParseEmailDateTime() throws Exception { 70988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner testParseEmailDateTimeHelper("2010-02-23T16:01:05.000Z", 71988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 2010, 2, 23, 16, 1, 5, 0); 72988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner testParseEmailDateTimeHelper("2009-02-11T18:03:31.123Z", 73988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner 2009, 2, 11, 18, 3, 31, 123); 742fc13087e700ee044684adb99e7114c9f477c67fJay Shrauner testParseEmailDateTimeHelper("2009-02-11", 752fc13087e700ee044684adb99e7114c9f477c67fJay Shrauner 2009, 2, 11, 0, 0, 0, 0); 76988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner try { 772fc13087e700ee044684adb99e7114c9f477c67fJay Shrauner testParseEmailDateTimeHelper("2010-02", 1970, 1, 1, 0, 0, 0, 0); 78988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner fail("Expected ParseException"); 79988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } catch (ParseException e) { 80988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner // expected 81988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } 82988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner } 839a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 849a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler private static NewFileCreator getCountdownFileCreator() { 859a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler return new NewFileCreator() { 869a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler private int mCountdown = 5; 879a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler @Override 889a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler public boolean createNewFile(File f) throws IOException { 899a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler return mCountdown-- <= 0; 909a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 919a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler }; 929a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 939a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 949a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler private static NewFileCreator getTrueFileCreator() { 959a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler return new NewFileCreator() { 969a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler @Override 979a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler public boolean createNewFile(File f) throws IOException { 989a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler return true; 999a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 1009a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler }; 1019a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 1029a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1039a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler @SmallTest 1049a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler public void testCreateUniqueFileCompare() throws Exception { 1059a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File directory = 1069a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler new IsolatedContext(new MockContentResolver(), getContext()).getFilesDir(); 1079a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1089a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created1 = 1099a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "file"); 1109a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created1); 1119a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertFalse(TextUtils.equals(created1.getName(), "file")); 1129a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1139a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created2 = 1149a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file"); 1159a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created2); 1169a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertTrue(TextUtils.equals(created2.getName(), "file")); 1179a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1189a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created3 = 1199a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "file.ext"); 1209a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created3); 1219a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertFalse(TextUtils.equals(created3.getName(), "file.ext")); 1229a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1239a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created4 = 1249a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file.ext"); 1259a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created4); 1269a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertTrue(TextUtils.equals(created4.getName(), "file.ext")); 1279a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 1289a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1299a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler @SmallTest 1309a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler public void testCreateUniqueFileWithPercent() throws Exception { 1319a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File directory = 1329a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler new IsolatedContext(new MockContentResolver(), getContext()).getFilesDir(); 1339a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1349a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created1 = 1359a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file%s"); 1369a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created1); 1379a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1389a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created2 = 1399a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file%s.ext"); 1409a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created2); 1419a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 1429a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1439a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler @SmallTest 1449a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler public void testCreateUniqueFile() throws Exception { 1459a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File directory = 1469a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler new IsolatedContext(new MockContentResolver(), getContext()).getFilesDir(); 1479a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1489a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created1 = 1499a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file"); 1509a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created1); 1519a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1529a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created2 = 1539a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "file"); 1549a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created2); 1559a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1569a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created3 = 1579a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file.ext"); 1589a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created3); 1599a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1609a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created4 = 1619a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "file.ext"); 1629a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created4); 1639a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1649a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created5 = 1659a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, ".ext"); 1669a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created5); 1679a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1689a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created6 = 1699a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, ".ext"); 1709a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created6); 1719a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1729a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created7 = 1739a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "."); 1749a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created7); 1759a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1769a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created8 = 1779a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "."); 1789a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created8); 1799a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 1809a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1819a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler @SmallTest 1829a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler public void testCreateUniqueFileExtensions() throws Exception { 1839a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File directory = 1849a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler new IsolatedContext(new MockContentResolver(), getContext()).getFilesDir(); 1859a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1869a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created1 = 1879a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file"); 1889a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created1); 1899a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertEquals(created1.getName().indexOf('.'), -1); 1909a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1919a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created2 = 1929a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "file"); 1939a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created2); 1949a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertEquals(created2.getName().indexOf('.'), -1); 1959a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 1969a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created3 = 1979a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getTrueFileCreator(), directory, "file.ext"); 1989a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created3); 1999a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertEquals(created3.getName().length() - created3.getName().lastIndexOf('.'), 4); 2009a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler 2019a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler final File created4 = 2029a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler Utility.createUniqueFileInternal(getCountdownFileCreator(), directory, "file.ext"); 2039a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertNotNull(created4); 2049a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler assertEquals(created4.getName().length() - created4.getName().lastIndexOf('.'), 4); 2059a80ffce14f5fac6c3234ee7aab768189fddc7baTony Mantler } 206988d2b6e85ad7bd62bbadd0021f15cd2a70c82d0Jay Shrauner} 207