Tue, 10 Feb 2015 22:40:00 +0100
Merge https://github.com/gggard/AndroidCaldavSyncAdapater/pull/206/
1.1 --- a/res/layout/activity_authenticator.xml Tue Feb 10 21:55:00 2015 +0100 1.2 +++ b/res/layout/activity_authenticator.xml Tue Feb 10 22:40:00 2015 +0100 1.3 @@ -71,6 +71,14 @@ 1.4 1.5 <requestFocus /> 1.6 </EditText> 1.7 + 1.8 + <CheckBox 1.9 + android:id="@+id/trustall" 1.10 + android:layout_width="wrap_content" 1.11 + android:layout_height="wrap_content" 1.12 + android:checked="true" 1.13 + android:text="@string/trustall" 1.14 + android:visibility="gone" /> 1.15 1.16 <EditText 1.17 android:id="@+id/accountname"
2.1 --- a/res/menu/activity_authenticator.xml Tue Feb 10 21:55:00 2015 +0100 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,8 +0,0 @@ 2.4 -<menu xmlns:android="http://schemas.android.com/apk/res/android" > 2.5 - 2.6 - <item 2.7 - android:id="@+id/menu_forgot_password" 2.8 - android:showAsAction="never" 2.9 - android:title="@string/menu_forgot_password"/> 2.10 - 2.11 -</menu> 2.12 \ No newline at end of file
3.1 --- a/res/values-de/strings_activity_authenticator.xml Tue Feb 10 21:55:00 2015 +0100 3.2 +++ b/res/values-de/strings_activity_authenticator.xml Tue Feb 10 22:40:00 2015 +0100 3.3 @@ -24,6 +24,9 @@ 3.4 <string name="error_account_already_in_use" >Account bereits in Verwendung</string> 3.5 <string name="success_calendar">Verbindung erfolgreich (Kalender)</string> 3.6 <string name="success_collection">Verbindung erfolgreich (mehrere Kalender)</string> 3.7 - 3.8 + <string name="trustall">Überprüfe SSL Zertifikat</string> 3.9 + <string name="error_ssl">SSL Fehler</string> 3.10 + <string name="error_untrusted_certificate">Nicht vertrauenswürdiges Zertifikat</string> 3.11 + 3.12 3.13 </resources> 3.14 \ No newline at end of file
4.1 --- a/res/values/strings_activity_authenticator.xml Tue Feb 10 21:55:00 2015 +0100 4.2 +++ b/res/values/strings_activity_authenticator.xml Tue Feb 10 22:40:00 2015 +0100 4.3 @@ -22,8 +22,10 @@ 4.4 <string name="error_connection_refused">Connection refused</string> 4.5 <string name="error_unkown_error">Unknown error</string> 4.6 <string name="error_account_already_in_use">Account already added</string> 4.7 + <string name="error_ssl">SSL error</string> 4.8 <string name="success_calendar">Connection success (calendar)</string> 4.9 <string name="success_collection">Connection success (multiple calendars)</string> 4.10 - 4.11 + <string name="trustall">Check SSL Certificate</string> 4.12 + <string name="error_untrusted_certificate">Untrusted certificate</string> 4.13 4.14 -</resources> 4.15 \ No newline at end of file 4.16 +</resources>
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/org/gege/caldavsyncadapter/Constants.java Tue Feb 10 22:40:00 2015 +0100 5.3 @@ -0,0 +1,10 @@ 5.4 +package org.gege.caldavsyncadapter; 5.5 + 5.6 +/** 5.7 + * @author Joseph Weigl 5.8 + */ 5.9 +public class Constants { 5.10 + 5.11 + public static final String USER_DATA_TRUST_ALL_KEY = "USER_DATA_TRUSTALL_KEY"; 5.12 + 5.13 +}
6.1 --- a/src/org/gege/caldavsyncadapter/android/entities/AndroidEvent.java Tue Feb 10 21:55:00 2015 +0100 6.2 +++ b/src/org/gege/caldavsyncadapter/android/entities/AndroidEvent.java Tue Feb 10 22:40:00 2015 +0100 6.3 @@ -1,6 +1,6 @@ 6.4 /** 6.5 * Copyright (c) 2012-2013, Gerald Garcia, Timo Berger 6.6 - * 6.7 + * 6.8 * This file is part of Andoid Caldav Sync Adapter Free. 6.9 * 6.10 * Andoid Caldav Sync Adapter Free is free software: you can redistribute 6.11 @@ -16,13 +16,17 @@ 6.12 * You should have received a copy of the GNU General Public License 6.13 * along with Andoid Caldav Sync Adapter Free. 6.14 * If not, see <http://www.gnu.org/licenses/>. 6.15 - * 6.16 + * 6.17 */ 6.18 6.19 package org.gege.caldavsyncadapter.android.entities; 6.20 6.21 -import java.net.URISyntaxException; 6.22 -import java.text.ParseException; 6.23 +import android.database.Cursor; 6.24 +import android.net.Uri; 6.25 +import android.provider.CalendarContract.Attendees; 6.26 +import android.provider.CalendarContract.Events; 6.27 +import android.provider.CalendarContract.Reminders; 6.28 + 6.29 import net.fortuna.ical4j.model.Calendar; 6.30 import net.fortuna.ical4j.model.Component; 6.31 import net.fortuna.ical4j.model.ComponentList; 6.32 @@ -62,255 +66,258 @@ 6.33 import net.fortuna.ical4j.model.property.Trigger; 6.34 import net.fortuna.ical4j.model.property.Uid; 6.35 import net.fortuna.ical4j.model.property.Version; 6.36 + 6.37 +import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent; 6.38 + 6.39 +import java.net.URISyntaxException; 6.40 +import java.text.ParseException; 6.41 + 6.42 //import android.accounts.Account; 6.43 //import android.content.ContentProviderClient; 6.44 //import android.content.ContentValues; 6.45 //import android.content.SyncStats; 6.46 -import android.database.Cursor; 6.47 -import android.net.Uri; 6.48 //import android.os.RemoteException; 6.49 -import android.provider.CalendarContract.Attendees; 6.50 //import android.provider.CalendarContract.Calendars; 6.51 -import android.provider.CalendarContract.Events; 6.52 -import android.provider.CalendarContract.Reminders; 6.53 - 6.54 //import org.gege.caldavsyncadapter.Event; 6.55 //import org.gege.caldavsyncadapter.caldav.CaldavFacade; 6.56 -import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent; 6.57 //import org.gege.caldavsyncadapter.caldav.entities.DavCalendar; 6.58 //import org.gege.caldavsyncadapter.syncadapter.SyncAdapter; 6.59 6.60 public class AndroidEvent extends org.gege.caldavsyncadapter.Event { 6.61 6.62 - private Uri muri; 6.63 - 6.64 - private Uri mAndroidCalendarUri; 6.65 - 6.66 - /** 6.67 - * the list of attendees 6.68 - */ 6.69 - private PropertyList mAttendees = new PropertyList(); 6.70 - 6.71 - /** 6.72 - * the list of reminders 6.73 - */ 6.74 - private ComponentList mReminders = new ComponentList(); 6.75 + private Uri muri; 6.76 6.77 - private Calendar mCalendar = null; 6.78 + private Uri mAndroidCalendarUri; 6.79 + 6.80 + /** 6.81 + * the list of attendees 6.82 + */ 6.83 + private PropertyList mAttendees = new PropertyList(); 6.84 + 6.85 + /** 6.86 + * the list of reminders 6.87 + */ 6.88 + private ComponentList mReminders = new ComponentList(); 6.89 + 6.90 + private Calendar mCalendar = null; 6.91 6.92 /* private Account mAccount = null; 6.93 - private ContentProviderClient mProvider = null;*/ 6.94 - 6.95 - //public AndroidEvent(Account account, ContentProviderClient provider, Uri uri, Uri calendarUri) { 6.96 - public AndroidEvent(Uri uri, Uri calendarUri) { 6.97 - super(); 6.98 - this.setUri(uri); 6.99 + private ContentProviderClient mProvider = null;*/ 6.100 + 6.101 + //public AndroidEvent(Account account, ContentProviderClient provider, Uri uri, Uri calendarUri) { 6.102 + public AndroidEvent(Uri uri, Uri calendarUri) { 6.103 + super(); 6.104 + this.setUri(uri); 6.105 /* this.mAccount = account; 6.106 - this.mProvider = provider;*/ 6.107 - //this.setCounterpartUri(calendarUri); 6.108 - mAndroidCalendarUri = calendarUri; 6.109 - } 6.110 - 6.111 - public Calendar getIcsEvent() { 6.112 - return mCalendar; 6.113 - } 6.114 - 6.115 - public String getETag() { 6.116 - String Result = ""; 6.117 - if (this.ContentValues.containsKey(ETAG)) 6.118 - Result = this.ContentValues.getAsString(ETAG); 6.119 - return Result; 6.120 - } 6.121 + this.mProvider = provider;*/ 6.122 + //this.setCounterpartUri(calendarUri); 6.123 + mAndroidCalendarUri = calendarUri; 6.124 + } 6.125 6.126 - public void setETag(String eTag) { 6.127 - this.ContentValues.put(ETAG, eTag); 6.128 - } 6.129 - 6.130 - public Uri getUri() { 6.131 - return muri; 6.132 - } 6.133 + public Calendar getIcsEvent() { 6.134 + return mCalendar; 6.135 + } 6.136 6.137 - public void setUri(Uri uri) { 6.138 - this.muri = uri; 6.139 - } 6.140 - 6.141 - public Uri getAndroidCalendarUri() { 6.142 - return mAndroidCalendarUri; 6.143 - } 6.144 - 6.145 - @Override 6.146 - public String toString() { 6.147 - return this.getUri().toString(); 6.148 - } 6.149 - 6.150 - /** 6.151 - * reads an android event from a given cursor into {@link AndroidEvent#ContentValues} 6.152 - * @param cur the cursor with the event 6.153 - * @return success of this funtion 6.154 - * @see AndroidEvent#ContentValues 6.155 - */ 6.156 - public boolean readContentValues(Cursor cur) { 6.157 - this.setETag(cur.getString(cur.getColumnIndex(ETAG))); 6.158 + public String getETag() { 6.159 + String Result = ""; 6.160 + if (this.ContentValues.containsKey(ETAG)) 6.161 + Result = this.ContentValues.getAsString(ETAG); 6.162 + return Result; 6.163 + } 6.164 6.165 - this.ContentValues.put(Events.EVENT_TIMEZONE, cur.getString(cur.getColumnIndex(Events.EVENT_TIMEZONE))); 6.166 - this.ContentValues.put(Events.EVENT_END_TIMEZONE, cur.getString(cur.getColumnIndex(Events.EVENT_END_TIMEZONE))); 6.167 - this.ContentValues.put(Events.DTSTART, cur.getLong(cur.getColumnIndex(Events.DTSTART))); 6.168 - this.ContentValues.put(Events.DTEND, cur.getLong(cur.getColumnIndex(Events.DTEND))); 6.169 - this.ContentValues.put(Events.ALL_DAY, cur.getLong(cur.getColumnIndex(Events.ALL_DAY))); 6.170 - this.ContentValues.put(Events.TITLE, cur.getString(cur.getColumnIndex(Events.TITLE))); 6.171 - this.ContentValues.put(Events.CALENDAR_ID, cur.getString(cur.getColumnIndex(Events.CALENDAR_ID))); 6.172 - this.ContentValues.put(Events._SYNC_ID, cur.getString(cur.getColumnIndex(Events._SYNC_ID))); 6.173 - //this.ContentValues.put(Events.SYNC_DATA1, cur.getString(cur.getColumnIndex(Events.SYNC_DATA1))); //not needed here, eTag has already been read 6.174 - this.ContentValues.put(Events.DESCRIPTION, cur.getString(cur.getColumnIndex(Events.DESCRIPTION))); 6.175 - this.ContentValues.put(Events.EVENT_LOCATION, cur.getString(cur.getColumnIndex(Events.EVENT_LOCATION))); 6.176 - this.ContentValues.put(Events.ACCESS_LEVEL, cur.getInt(cur.getColumnIndex(Events.ACCESS_LEVEL))); 6.177 - 6.178 - this.ContentValues.put(Events.STATUS, cur.getInt(cur.getColumnIndex(Events.STATUS))); 6.179 - 6.180 - this.ContentValues.put(Events.LAST_DATE, cur.getInt(cur.getColumnIndex(Events.LAST_DATE))); 6.181 - this.ContentValues.put(Events.DURATION, cur.getString(cur.getColumnIndex(Events.DURATION))); 6.182 + public void setETag(String eTag) { 6.183 + this.ContentValues.put(ETAG, eTag); 6.184 + } 6.185 6.186 - this.ContentValues.put(Events.RDATE, cur.getString(cur.getColumnIndex(Events.RDATE))); 6.187 - this.ContentValues.put(Events.RRULE, cur.getString(cur.getColumnIndex(Events.RRULE))); 6.188 - this.ContentValues.put(Events.EXRULE, cur.getString(cur.getColumnIndex(Events.EXRULE))); 6.189 - this.ContentValues.put(Events.EXDATE, cur.getString(cur.getColumnIndex(Events.EXDATE))); 6.190 - this.ContentValues.put(Events.DIRTY, cur.getInt(cur.getColumnIndex(Events.DIRTY))); 6.191 - this.ContentValues.put(UID, cur.getString(cur.getColumnIndex(UID))); 6.192 - this.ContentValues.put(RAWDATA, cur.getString(cur.getColumnIndex(RAWDATA))); 6.193 - 6.194 - return true; 6.195 - } 6.196 - 6.197 - /** 6.198 - * reads the attendees from a given cursor 6.199 - * @param cur the cursor with the attendees 6.200 - * @return success of this function 6.201 - * @see AndroidEvent#mAttendees 6.202 - */ 6.203 - public boolean readAttendees(Cursor cur) { 6.204 - Attendee attendee = null; 6.205 - Organizer organizer = null; 6.206 - ParameterList paraList = null; 6.207 + public Uri getUri() { 6.208 + return muri; 6.209 + } 6.210 6.211 - String Name = ""; 6.212 - Cn cn = null; 6.213 + public void setUri(Uri uri) { 6.214 + this.muri = uri; 6.215 + } 6.216 6.217 - String Email = ""; 6.218 + public Uri getAndroidCalendarUri() { 6.219 + return mAndroidCalendarUri; 6.220 + } 6.221 6.222 - int Relationship = 0; 6.223 - 6.224 - 6.225 - int Status = 0; 6.226 - PartStat partstat = null; 6.227 + @Override 6.228 + public String toString() { 6.229 + return this.getUri().toString(); 6.230 + } 6.231 6.232 - int Type = 0; 6.233 - Role role = null; 6.234 - 6.235 - try { 6.236 - while (cur.moveToNext()) { 6.237 - Name = cur.getString(cur.getColumnIndex(Attendees.ATTENDEE_NAME)); 6.238 - Email = cur.getString(cur.getColumnIndex(Attendees.ATTENDEE_EMAIL)); 6.239 - Relationship = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_RELATIONSHIP)); 6.240 - Type = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_TYPE)); 6.241 - Status = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_STATUS)); 6.242 - 6.243 - if (Relationship == Attendees.RELATIONSHIP_ORGANIZER) { 6.244 - organizer = new Organizer(); 6.245 - organizer.setValue("mailto:" + Email); 6.246 - paraList = organizer.getParameters(); 6.247 - mAttendees.add(organizer); 6.248 - } else { 6.249 - attendee = new Attendee(); 6.250 - attendee.setValue("mailto:" + Email); 6.251 - paraList = attendee.getParameters(); 6.252 - mAttendees.add(attendee); 6.253 - } 6.254 - 6.255 - Rsvp rsvp = new Rsvp(true); 6.256 - paraList.add(rsvp); 6.257 + /** 6.258 + * reads an android event from a given cursor into {@link AndroidEvent#ContentValues} 6.259 + * 6.260 + * @param cur the cursor with the event 6.261 + * @return success of this funtion 6.262 + * @see AndroidEvent#ContentValues 6.263 + */ 6.264 + public boolean readContentValues(Cursor cur) { 6.265 + this.setETag(cur.getString(cur.getColumnIndex(ETAG))); 6.266 6.267 - cn = new Cn(Name); 6.268 - paraList.add(cn); 6.269 - 6.270 - if (Status == Attendees.ATTENDEE_STATUS_INVITED) 6.271 - partstat = new PartStat(PartStat.NEEDS_ACTION.getValue()); 6.272 - else if (Status == Attendees.ATTENDEE_STATUS_ACCEPTED) 6.273 - partstat = new PartStat(PartStat.ACCEPTED.getValue()); 6.274 - else if (Status == Attendees.ATTENDEE_STATUS_DECLINED) 6.275 - partstat = new PartStat(PartStat.DECLINED.getValue()); 6.276 - else if (Status == Attendees.ATTENDEE_STATUS_NONE) 6.277 - partstat = new PartStat(PartStat.COMPLETED.getValue()); 6.278 - else if (Status == Attendees.ATTENDEE_STATUS_TENTATIVE) 6.279 - partstat = new PartStat(PartStat.TENTATIVE.getValue()); 6.280 - else 6.281 - partstat = new PartStat(PartStat.NEEDS_ACTION.getValue()); 6.282 - paraList.add(partstat); 6.283 + this.ContentValues.put(Events.EVENT_TIMEZONE, cur.getString(cur.getColumnIndex(Events.EVENT_TIMEZONE))); 6.284 + this.ContentValues.put(Events.EVENT_END_TIMEZONE, cur.getString(cur.getColumnIndex(Events.EVENT_END_TIMEZONE))); 6.285 + this.ContentValues.put(Events.DTSTART, cur.getLong(cur.getColumnIndex(Events.DTSTART))); 6.286 + this.ContentValues.put(Events.DTEND, cur.getLong(cur.getColumnIndex(Events.DTEND))); 6.287 + this.ContentValues.put(Events.ALL_DAY, cur.getLong(cur.getColumnIndex(Events.ALL_DAY))); 6.288 + this.ContentValues.put(Events.TITLE, cur.getString(cur.getColumnIndex(Events.TITLE))); 6.289 + this.ContentValues.put(Events.CALENDAR_ID, cur.getString(cur.getColumnIndex(Events.CALENDAR_ID))); 6.290 + this.ContentValues.put(Events._SYNC_ID, cur.getString(cur.getColumnIndex(Events._SYNC_ID))); 6.291 + //this.ContentValues.put(Events.SYNC_DATA1, cur.getString(cur.getColumnIndex(Events.SYNC_DATA1))); //not needed here, eTag has already been read 6.292 + this.ContentValues.put(Events.DESCRIPTION, cur.getString(cur.getColumnIndex(Events.DESCRIPTION))); 6.293 + this.ContentValues.put(Events.EVENT_LOCATION, cur.getString(cur.getColumnIndex(Events.EVENT_LOCATION))); 6.294 + this.ContentValues.put(Events.ACCESS_LEVEL, cur.getInt(cur.getColumnIndex(Events.ACCESS_LEVEL))); 6.295 6.296 - if (Type == Attendees.TYPE_OPTIONAL) 6.297 - role = new Role(Role.OPT_PARTICIPANT.getValue()); 6.298 - else if (Type == Attendees.TYPE_NONE) 6.299 - role = new Role(Role.NON_PARTICIPANT.getValue()); //regular participants in android are non required? 6.300 - else if (Type == Attendees.TYPE_REQUIRED) 6.301 - role = new Role(Role.REQ_PARTICIPANT.getValue()); 6.302 - else 6.303 - role = new Role(Role.NON_PARTICIPANT.getValue()); 6.304 - paraList.add(role); 6.305 - } 6.306 + this.ContentValues.put(Events.STATUS, cur.getInt(cur.getColumnIndex(Events.STATUS))); 6.307 6.308 - } catch (URISyntaxException e) { 6.309 - e.printStackTrace(); 6.310 - } 6.311 - return true; 6.312 - } 6.313 - 6.314 - /** 6.315 - * reads the reminders from a given cursor 6.316 - * @param cur the cursor with the reminders 6.317 - * @return success of this function 6.318 - */ 6.319 - public boolean readReminder(Cursor cur) { 6.320 - int Method; 6.321 - int Minutes; 6.322 - VAlarm reminder; 6.323 - while (cur.moveToNext()) { 6.324 - reminder = new VAlarm(); 6.325 - Method = cur.getInt(cur.getColumnIndex(Reminders.METHOD)); 6.326 - Minutes = cur.getInt(cur.getColumnIndex(Reminders.MINUTES)) * -1; 6.327 - 6.328 - 6.329 - Dur dur = new Dur(0, 0, Minutes, 0); 6.330 - Trigger tri = new Trigger(dur); 6.331 - Value val = new Value(Duration.DURATION); 6.332 - tri.getParameters().add(val); 6.333 - reminder.getProperties().add(tri); 6.334 + this.ContentValues.put(Events.LAST_DATE, cur.getInt(cur.getColumnIndex(Events.LAST_DATE))); 6.335 + this.ContentValues.put(Events.DURATION, cur.getString(cur.getColumnIndex(Events.DURATION))); 6.336 6.337 - Description desc = new Description(); 6.338 - desc.setValue("caldavsyncadapter standard description"); 6.339 - reminder.getProperties().add(desc); 6.340 + this.ContentValues.put(Events.RDATE, cur.getString(cur.getColumnIndex(Events.RDATE))); 6.341 + this.ContentValues.put(Events.RRULE, cur.getString(cur.getColumnIndex(Events.RRULE))); 6.342 + this.ContentValues.put(Events.EXRULE, cur.getString(cur.getColumnIndex(Events.EXRULE))); 6.343 + this.ContentValues.put(Events.EXDATE, cur.getString(cur.getColumnIndex(Events.EXDATE))); 6.344 + this.ContentValues.put(Events.DIRTY, cur.getInt(cur.getColumnIndex(Events.DIRTY))); 6.345 + this.ContentValues.put(UID, cur.getString(cur.getColumnIndex(UID))); 6.346 + this.ContentValues.put(RAWDATA, cur.getString(cur.getColumnIndex(RAWDATA))); 6.347 6.348 + return true; 6.349 + } 6.350 6.351 - if (Method == Reminders.METHOD_EMAIL) 6.352 - reminder.getProperties().add(Action.EMAIL); 6.353 - else 6.354 - reminder.getProperties().add(Action.DISPLAY); 6.355 - 6.356 - this.mReminders.add(reminder); 6.357 - } 6.358 - return true; 6.359 - } 6.360 - 6.361 - /** 6.362 - * generates a new ics-file. 6.363 - * uses {@link AndroidEvent#ContentValues} as source. 6.364 - * this should only be used when a new event has been generated within android. 6.365 - * @param strUid the UID for this event. example: UID:e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter 6.366 - * @return success of the function 6.367 - * @see CalendarEvent#fetchBody() 6.368 - */ 6.369 - public boolean createIcs(String strUid) { 6.370 - boolean Result = false; 6.371 - TimeZone timezone = null; 6.372 - TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); 6.373 + /** 6.374 + * reads the attendees from a given cursor 6.375 + * 6.376 + * @param cur the cursor with the attendees 6.377 + * @return success of this function 6.378 + * @see AndroidEvent#mAttendees 6.379 + */ 6.380 + public boolean readAttendees(Cursor cur) { 6.381 + Attendee attendee = null; 6.382 + Organizer organizer = null; 6.383 + ParameterList paraList = null; 6.384 + 6.385 + String Name = ""; 6.386 + Cn cn = null; 6.387 + 6.388 + String Email = ""; 6.389 + 6.390 + int Relationship = 0; 6.391 + 6.392 + 6.393 + int Status = 0; 6.394 + PartStat partstat = null; 6.395 + 6.396 + int Type = 0; 6.397 + Role role = null; 6.398 + 6.399 + try { 6.400 + while (cur.moveToNext()) { 6.401 + Name = cur.getString(cur.getColumnIndex(Attendees.ATTENDEE_NAME)); 6.402 + Email = cur.getString(cur.getColumnIndex(Attendees.ATTENDEE_EMAIL)); 6.403 + Relationship = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_RELATIONSHIP)); 6.404 + Type = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_TYPE)); 6.405 + Status = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_STATUS)); 6.406 + 6.407 + if (Relationship == Attendees.RELATIONSHIP_ORGANIZER) { 6.408 + organizer = new Organizer(); 6.409 + organizer.setValue("mailto:" + Email); 6.410 + paraList = organizer.getParameters(); 6.411 + mAttendees.add(organizer); 6.412 + } else { 6.413 + attendee = new Attendee(); 6.414 + attendee.setValue("mailto:" + Email); 6.415 + paraList = attendee.getParameters(); 6.416 + mAttendees.add(attendee); 6.417 + } 6.418 + 6.419 + Rsvp rsvp = new Rsvp(true); 6.420 + paraList.add(rsvp); 6.421 + 6.422 + cn = new Cn(Name); 6.423 + paraList.add(cn); 6.424 + 6.425 + if (Status == Attendees.ATTENDEE_STATUS_INVITED) 6.426 + partstat = new PartStat(PartStat.NEEDS_ACTION.getValue()); 6.427 + else if (Status == Attendees.ATTENDEE_STATUS_ACCEPTED) 6.428 + partstat = new PartStat(PartStat.ACCEPTED.getValue()); 6.429 + else if (Status == Attendees.ATTENDEE_STATUS_DECLINED) 6.430 + partstat = new PartStat(PartStat.DECLINED.getValue()); 6.431 + else if (Status == Attendees.ATTENDEE_STATUS_NONE) 6.432 + partstat = new PartStat(PartStat.COMPLETED.getValue()); 6.433 + else if (Status == Attendees.ATTENDEE_STATUS_TENTATIVE) 6.434 + partstat = new PartStat(PartStat.TENTATIVE.getValue()); 6.435 + else 6.436 + partstat = new PartStat(PartStat.NEEDS_ACTION.getValue()); 6.437 + paraList.add(partstat); 6.438 + 6.439 + if (Type == Attendees.TYPE_OPTIONAL) 6.440 + role = new Role(Role.OPT_PARTICIPANT.getValue()); 6.441 + else if (Type == Attendees.TYPE_NONE) 6.442 + role = new Role(Role.NON_PARTICIPANT.getValue()); //regular participants in android are non required? 6.443 + else if (Type == Attendees.TYPE_REQUIRED) 6.444 + role = new Role(Role.REQ_PARTICIPANT.getValue()); 6.445 + else 6.446 + role = new Role(Role.NON_PARTICIPANT.getValue()); 6.447 + paraList.add(role); 6.448 + } 6.449 + 6.450 + } catch (URISyntaxException e) { 6.451 + e.printStackTrace(); 6.452 + } 6.453 + return true; 6.454 + } 6.455 + 6.456 + /** 6.457 + * reads the reminders from a given cursor 6.458 + * 6.459 + * @param cur the cursor with the reminders 6.460 + * @return success of this function 6.461 + */ 6.462 + public boolean readReminder(Cursor cur) { 6.463 + int Method; 6.464 + int Minutes; 6.465 + VAlarm reminder; 6.466 + while (cur.moveToNext()) { 6.467 + reminder = new VAlarm(); 6.468 + Method = cur.getInt(cur.getColumnIndex(Reminders.METHOD)); 6.469 + Minutes = cur.getInt(cur.getColumnIndex(Reminders.MINUTES)) * -1; 6.470 + 6.471 + 6.472 + Dur dur = new Dur(0, 0, Minutes, 0); 6.473 + Trigger tri = new Trigger(dur); 6.474 + Value val = new Value(Duration.DURATION); 6.475 + tri.getParameters().add(val); 6.476 + reminder.getProperties().add(tri); 6.477 + 6.478 + Description desc = new Description(); 6.479 + desc.setValue("caldavsyncadapter standard description"); 6.480 + reminder.getProperties().add(desc); 6.481 + 6.482 + 6.483 + if (Method == Reminders.METHOD_EMAIL) 6.484 + reminder.getProperties().add(Action.EMAIL); 6.485 + else 6.486 + reminder.getProperties().add(Action.DISPLAY); 6.487 + 6.488 + this.mReminders.add(reminder); 6.489 + } 6.490 + return true; 6.491 + } 6.492 + 6.493 + /** 6.494 + * generates a new ics-file. 6.495 + * uses {@link AndroidEvent#ContentValues} as source. 6.496 + * this should only be used when a new event has been generated within android. 6.497 + * 6.498 + * @param strUid the UID for this event. example: UID:e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter 6.499 + * @return success of the function 6.500 + * @see CalendarEvent#fetchBody() 6.501 + */ 6.502 + public boolean createIcs(String strUid) { 6.503 + boolean Result = false; 6.504 + TimeZone timeZone = null; 6.505 + TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); 6.506 //TODO: do not simply create the ics-file new. take into account the RAWDATA if available 6.507 /* 6.508 * dtstart=1365598800000 6.509 @@ -335,232 +342,239 @@ 6.510 * _sync_id=null 6.511 * dirty=1 6.512 */ 6.513 - 6.514 - try { 6.515 - mCalendar = new Calendar(); 6.516 - PropertyList propCalendar = mCalendar.getProperties(); 6.517 - propCalendar.add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN")); 6.518 - propCalendar.add(Version.VERSION_2_0); 6.519 - propCalendar.add(CalScale.GREGORIAN); 6.520 - 6.521 - VEvent event = new VEvent(); 6.522 - mCalendar.getComponents().add(event); 6.523 - PropertyList propEvent = event.getProperties(); 6.524 6.525 - // DTSTAMP -> is created by new VEvent() automatical 6.526 - //na 6.527 - 6.528 - // CREATED 6.529 - //na 6.530 - 6.531 - // LAST-MODIFIED 6.532 - //na 6.533 - 6.534 - // SEQUENCE 6.535 - //na 6.536 - 6.537 - // DTSTART 6.538 - long lngStart = this.ContentValues.getAsLong(Events.DTSTART); 6.539 - String strTZStart = this.ContentValues.getAsString(Events.EVENT_TIMEZONE); 6.540 - boolean allDay = this.ContentValues.getAsBoolean(Events.ALL_DAY); 6.541 - if (lngStart > 0) { 6.542 - DtStart dtStart = new DtStart(); 6.543 - if (allDay) { 6.544 - Date dateStart = new Date(); 6.545 - dateStart.setTime(lngStart); 6.546 - dtStart.setDate(dateStart); 6.547 - } else { 6.548 - DateTime datetimeStart = new DateTime(); 6.549 - datetimeStart.setTime(lngStart); 6.550 - dtStart.setDate(datetimeStart); 6.551 + try { 6.552 + mCalendar = new Calendar(); 6.553 + PropertyList propCalendar = mCalendar.getProperties(); 6.554 + propCalendar.add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN")); 6.555 + propCalendar.add(Version.VERSION_2_0); 6.556 + propCalendar.add(CalScale.GREGORIAN); 6.557 6.558 - timezone = registry.getTimeZone(strTZStart); 6.559 - dtStart.setTimeZone(timezone); 6.560 - 6.561 - // no timezone information for allDay events 6.562 - mCalendar.getComponents().add(timezone.getVTimeZone()); 6.563 - } 6.564 - propEvent.add(dtStart); 6.565 - } 6.566 - 6.567 - // DTEND 6.568 - long lngEnd = this.ContentValues.getAsLong(Events.DTEND); 6.569 - String strTZEnd = this.ContentValues.getAsString(Events.EVENT_END_TIMEZONE); 6.570 - if (strTZEnd == null) 6.571 - strTZEnd = strTZStart; 6.572 - if (lngEnd > 0) { 6.573 - DtEnd dtEnd = new DtEnd(); 6.574 - if (allDay) { 6.575 - Date dateEnd = new Date(); 6.576 - dateEnd.setTime(lngEnd); 6.577 - dtEnd.setDate(dateEnd); 6.578 - } else { 6.579 - DateTime datetimeEnd = new DateTime(); 6.580 - datetimeEnd.setTime(lngEnd); 6.581 - dtEnd.setDate(datetimeEnd); 6.582 - if (strTZEnd != null) 6.583 - timezone = registry.getTimeZone(strTZEnd); 6.584 - dtEnd.setTimeZone(timezone); 6.585 - } 6.586 - propEvent.add(dtEnd); 6.587 - } 6.588 - 6.589 - // DURATION 6.590 - if (this.ContentValues.containsKey(Events.DURATION)) { 6.591 - String strDuration = this.ContentValues.getAsString(Events.DURATION); 6.592 - if (strDuration != null) { 6.593 - Duration duration = new Duration(); 6.594 - duration.setValue(strDuration); 6.595 - 6.596 - propEvent.add(duration); 6.597 - } 6.598 - } 6.599 + VEvent event = new VEvent(); 6.600 + mCalendar.getComponents().add(event); 6.601 + PropertyList propEvent = event.getProperties(); 6.602 6.603 - //RRULE 6.604 - if (this.ContentValues.containsKey(Events.RRULE)) { 6.605 - String strRrule = this.ContentValues.getAsString(Events.RRULE); 6.606 - if (strRrule != null) { 6.607 - if (!strRrule.equals("")) { 6.608 - RRule rrule = new RRule(); 6.609 - rrule.setValue(strRrule); 6.610 - propEvent.add(rrule); 6.611 - } 6.612 - } 6.613 - } 6.614 - 6.615 - //RDATE 6.616 - if (this.ContentValues.containsKey(Events.RDATE)) { 6.617 - String strRdate = this.ContentValues.getAsString(Events.RDATE); 6.618 - if (strRdate != null) { 6.619 - if (!strRdate.equals("")) { 6.620 - RDate rdate = new RDate(); 6.621 - rdate.setValue(strRdate); 6.622 - propEvent.add(rdate); 6.623 - } 6.624 - } 6.625 - } 6.626 - 6.627 - //EXRULE 6.628 - if (this.ContentValues.containsKey(Events.EXRULE)) { 6.629 - String strExrule = this.ContentValues.getAsString(Events.EXRULE); 6.630 - if (strExrule != null) { 6.631 - if (!strExrule.equals("")) { 6.632 - ExRule exrule = new ExRule(); 6.633 - exrule.setValue(strExrule); 6.634 - propEvent.add(exrule); 6.635 - } 6.636 - } 6.637 - } 6.638 - 6.639 - //EXDATE 6.640 - if (this.ContentValues.containsKey(Events.EXDATE)) { 6.641 - String strExdate = this.ContentValues.getAsString(Events.EXDATE); 6.642 - if (strExdate != null) { 6.643 - if (!strExdate.equals("")) { 6.644 - ExDate exdate = new ExDate(); 6.645 - exdate.setValue(strExdate); 6.646 - propEvent.add(exdate); 6.647 - } 6.648 - } 6.649 - } 6.650 - 6.651 - //SUMMARY 6.652 - if (this.ContentValues.containsKey(Events.TITLE)) { 6.653 - String strTitle = this.ContentValues.getAsString(Events.TITLE); 6.654 - if (strTitle != null) { 6.655 - Summary summary = new Summary(strTitle); 6.656 - propEvent.add(summary); 6.657 - } 6.658 - } 6.659 - 6.660 - //DESCIPTION 6.661 - if (this.ContentValues.containsKey(Events.DESCRIPTION)) { 6.662 - String strDescription = this.ContentValues.getAsString(Events.DESCRIPTION); 6.663 - if (strDescription != null) { 6.664 - if (!strDescription.equals("")) { 6.665 - Description description = new Description(strDescription); 6.666 - propEvent.add(description); 6.667 - } 6.668 - } 6.669 - } 6.670 - 6.671 - //LOCATION 6.672 - if (this.ContentValues.containsKey(Events.EVENT_LOCATION)) { 6.673 - String strLocation = this.ContentValues.getAsString(Events.EVENT_LOCATION); 6.674 - if (strLocation != null) { 6.675 - if (!strLocation.equals("")) { 6.676 - Location location = new Location(strLocation); 6.677 - propEvent.add(location); 6.678 - } 6.679 - } 6.680 - } 6.681 - 6.682 - //CLASS / ACCESS_LEVEL 6.683 - if (this.ContentValues.containsKey(Events.ACCESS_LEVEL)) { 6.684 - int accessLevel = this.ContentValues.getAsInteger(Events.ACCESS_LEVEL); 6.685 - Clazz clazz = new Clazz(); 6.686 - if (accessLevel == Events.ACCESS_PUBLIC) 6.687 - clazz.setValue(Clazz.PUBLIC.getValue()); 6.688 - else if (accessLevel == Events.ACCESS_PRIVATE) 6.689 - clazz.setValue(Clazz.PRIVATE.getValue()); 6.690 - else if (accessLevel == Events.ACCESS_CONFIDENTIAL) 6.691 - clazz.setValue(Clazz.CONFIDENTIAL.getValue()); 6.692 - else 6.693 - clazz.setValue(Clazz.PUBLIC.getValue()); 6.694 - 6.695 - propEvent.add(clazz); 6.696 - } 6.697 - 6.698 - //STATUS 6.699 - if (this.ContentValues.containsKey(Events.STATUS)) { 6.700 - int intStatus = this.ContentValues.getAsInteger(Events.STATUS); 6.701 - if (intStatus > -1) { 6.702 - Status status = new Status(); 6.703 - if (intStatus == Events.STATUS_CANCELED) 6.704 - status.setValue(Status.VEVENT_CANCELLED.getValue()); 6.705 - else if (intStatus == Events.STATUS_CONFIRMED) 6.706 - status.setValue(Status.VEVENT_CONFIRMED.getValue()); 6.707 - else if (intStatus == Events.STATUS_TENTATIVE) 6.708 - status.setValue(Status.VEVENT_TENTATIVE.getValue()); 6.709 - 6.710 - propEvent.add(status); 6.711 - } 6.712 - } 6.713 + // DTSTAMP -> is created by new VEvent() automatical 6.714 + //na 6.715 6.716 - //UID 6.717 - Uid uid = new Uid(strUid); 6.718 - propEvent.add(uid); 6.719 + // CREATED 6.720 + //na 6.721 6.722 - // Attendees 6.723 - if (mAttendees.size() > 0) { 6.724 - for (Object objProp: mAttendees) { 6.725 - Property prop = (Property) objProp; 6.726 - propEvent.add(prop); 6.727 - } 6.728 - } 6.729 - 6.730 - // Reminders 6.731 - if (mReminders.size() > 0) { 6.732 - for (Object objComp: mReminders) { 6.733 - Component com = (Component) objComp; 6.734 - event.getAlarms().add(com); 6.735 - } 6.736 - } 6.737 - 6.738 - } catch (ParseException e) { 6.739 - e.printStackTrace(); 6.740 - } 6.741 - 6.742 - return Result; 6.743 - } 6.744 - 6.745 - /** 6.746 - * marks the android event as already handled 6.747 - * @return 6.748 - * @see AndroidEvent#cInternalTag 6.749 - * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 6.750 - * @throws RemoteException 6.751 - */ 6.752 + // LAST-MODIFIED 6.753 + //na 6.754 + 6.755 + // SEQUENCE 6.756 + //na 6.757 + 6.758 + // DTSTART 6.759 + long lngStart = this.ContentValues.getAsLong(Events.DTSTART); 6.760 + String strTZStart = this.ContentValues.getAsString(Events.EVENT_TIMEZONE); 6.761 + boolean allDay = this.ContentValues.getAsBoolean(Events.ALL_DAY); 6.762 + if (lngStart > 0) { 6.763 + DtStart dtStart = new DtStart(); 6.764 + if (allDay) { 6.765 + Date dateStart = new Date(); 6.766 + dateStart.setTime(lngStart); 6.767 + dtStart.setDate(dateStart); 6.768 + } else { 6.769 + DateTime datetimeStart = new DateTime(); 6.770 + datetimeStart.setTime(lngStart); 6.771 + dtStart.setDate(datetimeStart); 6.772 + 6.773 + timeZone = registry.getTimeZone(strTZStart); 6.774 + if (timeZone == null) { 6.775 + java.util.TimeZone systemTimeZone = TimeZone.getTimeZone(strTZStart); 6.776 + if (systemTimeZone == null) { 6.777 + systemTimeZone = TimeZone.getDefault(); 6.778 + } 6.779 + timeZone = registry.getTimeZone(systemTimeZone.getID()); 6.780 + } 6.781 + dtStart.setTimeZone(timeZone); 6.782 + 6.783 + // no timezone information for allDay events 6.784 + mCalendar.getComponents().add(timeZone.getVTimeZone()); 6.785 + } 6.786 + propEvent.add(dtStart); 6.787 + } 6.788 + 6.789 + // DTEND 6.790 + long lngEnd = this.ContentValues.getAsLong(Events.DTEND); 6.791 + String strTZEnd = this.ContentValues.getAsString(Events.EVENT_END_TIMEZONE); 6.792 + if (strTZEnd == null) 6.793 + strTZEnd = strTZStart; 6.794 + if (lngEnd > 0) { 6.795 + DtEnd dtEnd = new DtEnd(); 6.796 + if (allDay) { 6.797 + Date dateEnd = new Date(); 6.798 + dateEnd.setTime(lngEnd); 6.799 + dtEnd.setDate(dateEnd); 6.800 + } else { 6.801 + DateTime datetimeEnd = new DateTime(); 6.802 + datetimeEnd.setTime(lngEnd); 6.803 + dtEnd.setDate(datetimeEnd); 6.804 + if (strTZEnd != null) 6.805 + timeZone = registry.getTimeZone(strTZEnd); 6.806 + dtEnd.setTimeZone(timeZone); 6.807 + } 6.808 + propEvent.add(dtEnd); 6.809 + } 6.810 + 6.811 + // DURATION 6.812 + if (this.ContentValues.containsKey(Events.DURATION)) { 6.813 + String strDuration = this.ContentValues.getAsString(Events.DURATION); 6.814 + if (strDuration != null) { 6.815 + Duration duration = new Duration(); 6.816 + duration.setValue(strDuration); 6.817 + 6.818 + propEvent.add(duration); 6.819 + } 6.820 + } 6.821 + 6.822 + //RRULE 6.823 + if (this.ContentValues.containsKey(Events.RRULE)) { 6.824 + String strRrule = this.ContentValues.getAsString(Events.RRULE); 6.825 + if (strRrule != null) { 6.826 + if (!strRrule.equals("")) { 6.827 + RRule rrule = new RRule(); 6.828 + rrule.setValue(strRrule); 6.829 + propEvent.add(rrule); 6.830 + } 6.831 + } 6.832 + } 6.833 + 6.834 + //RDATE 6.835 + if (this.ContentValues.containsKey(Events.RDATE)) { 6.836 + String strRdate = this.ContentValues.getAsString(Events.RDATE); 6.837 + if (strRdate != null) { 6.838 + if (!strRdate.equals("")) { 6.839 + RDate rdate = new RDate(); 6.840 + rdate.setValue(strRdate); 6.841 + propEvent.add(rdate); 6.842 + } 6.843 + } 6.844 + } 6.845 + 6.846 + //EXRULE 6.847 + if (this.ContentValues.containsKey(Events.EXRULE)) { 6.848 + String strExrule = this.ContentValues.getAsString(Events.EXRULE); 6.849 + if (strExrule != null) { 6.850 + if (!strExrule.equals("")) { 6.851 + ExRule exrule = new ExRule(); 6.852 + exrule.setValue(strExrule); 6.853 + propEvent.add(exrule); 6.854 + } 6.855 + } 6.856 + } 6.857 + 6.858 + //EXDATE 6.859 + if (this.ContentValues.containsKey(Events.EXDATE)) { 6.860 + String strExdate = this.ContentValues.getAsString(Events.EXDATE); 6.861 + if (strExdate != null) { 6.862 + if (!strExdate.equals("")) { 6.863 + ExDate exdate = new ExDate(); 6.864 + exdate.setValue(strExdate); 6.865 + propEvent.add(exdate); 6.866 + } 6.867 + } 6.868 + } 6.869 + 6.870 + //SUMMARY 6.871 + if (this.ContentValues.containsKey(Events.TITLE)) { 6.872 + String strTitle = this.ContentValues.getAsString(Events.TITLE); 6.873 + if (strTitle != null) { 6.874 + Summary summary = new Summary(strTitle); 6.875 + propEvent.add(summary); 6.876 + } 6.877 + } 6.878 + 6.879 + //DESCIPTION 6.880 + if (this.ContentValues.containsKey(Events.DESCRIPTION)) { 6.881 + String strDescription = this.ContentValues.getAsString(Events.DESCRIPTION); 6.882 + if (strDescription != null) { 6.883 + if (!strDescription.equals("")) { 6.884 + Description description = new Description(strDescription); 6.885 + propEvent.add(description); 6.886 + } 6.887 + } 6.888 + } 6.889 + 6.890 + //LOCATION 6.891 + if (this.ContentValues.containsKey(Events.EVENT_LOCATION)) { 6.892 + String strLocation = this.ContentValues.getAsString(Events.EVENT_LOCATION); 6.893 + if (strLocation != null) { 6.894 + if (!strLocation.equals("")) { 6.895 + Location location = new Location(strLocation); 6.896 + propEvent.add(location); 6.897 + } 6.898 + } 6.899 + } 6.900 + 6.901 + //CLASS / ACCESS_LEVEL 6.902 + if (this.ContentValues.containsKey(Events.ACCESS_LEVEL)) { 6.903 + int accessLevel = this.ContentValues.getAsInteger(Events.ACCESS_LEVEL); 6.904 + Clazz clazz = new Clazz(); 6.905 + if (accessLevel == Events.ACCESS_PUBLIC) 6.906 + clazz.setValue(Clazz.PUBLIC.getValue()); 6.907 + else if (accessLevel == Events.ACCESS_PRIVATE) 6.908 + clazz.setValue(Clazz.PRIVATE.getValue()); 6.909 + else if (accessLevel == Events.ACCESS_CONFIDENTIAL) 6.910 + clazz.setValue(Clazz.CONFIDENTIAL.getValue()); 6.911 + else 6.912 + clazz.setValue(Clazz.PUBLIC.getValue()); 6.913 + 6.914 + propEvent.add(clazz); 6.915 + } 6.916 + 6.917 + //STATUS 6.918 + if (this.ContentValues.containsKey(Events.STATUS)) { 6.919 + int intStatus = this.ContentValues.getAsInteger(Events.STATUS); 6.920 + if (intStatus > -1) { 6.921 + Status status = new Status(); 6.922 + if (intStatus == Events.STATUS_CANCELED) 6.923 + status.setValue(Status.VEVENT_CANCELLED.getValue()); 6.924 + else if (intStatus == Events.STATUS_CONFIRMED) 6.925 + status.setValue(Status.VEVENT_CONFIRMED.getValue()); 6.926 + else if (intStatus == Events.STATUS_TENTATIVE) 6.927 + status.setValue(Status.VEVENT_TENTATIVE.getValue()); 6.928 + 6.929 + propEvent.add(status); 6.930 + } 6.931 + } 6.932 + 6.933 + //UID 6.934 + Uid uid = new Uid(strUid); 6.935 + propEvent.add(uid); 6.936 + 6.937 + // Attendees 6.938 + if (mAttendees.size() > 0) { 6.939 + for (Object objProp : mAttendees) { 6.940 + Property prop = (Property) objProp; 6.941 + propEvent.add(prop); 6.942 + } 6.943 + } 6.944 + 6.945 + // Reminders 6.946 + if (mReminders.size() > 0) { 6.947 + for (Object objComp : mReminders) { 6.948 + Component com = (Component) objComp; 6.949 + event.getAlarms().add(com); 6.950 + } 6.951 + } 6.952 + 6.953 + } catch (ParseException e) { 6.954 + e.printStackTrace(); 6.955 + } 6.956 + 6.957 + return Result; 6.958 + } 6.959 + 6.960 + /** 6.961 + * marks the android event as already handled 6.962 + * @return 6.963 + * @see AndroidEvent#cInternalTag 6.964 + * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 6.965 + * @throws RemoteException 6.966 + */ 6.967 /* public boolean tagAndroidEvent() throws RemoteException { 6.968 6.969 ContentValues values = new ContentValues();
7.1 --- a/src/org/gege/caldavsyncadapter/authenticator/AuthenticatorActivity.java Tue Feb 10 21:55:00 2015 +0100 7.2 +++ b/src/org/gege/caldavsyncadapter/authenticator/AuthenticatorActivity.java Tue Feb 10 22:40:00 2015 +0100 7.3 @@ -1,6 +1,6 @@ 7.4 /** 7.5 * Copyright (c) 2012-2013, Gerald Garcia 7.6 - * 7.7 + * 7.8 * This file is part of Andoid Caldav Sync Adapter Free. 7.9 * 7.10 * Andoid Caldav Sync Adapter Free is free software: you can redistribute 7.11 @@ -16,24 +16,11 @@ 7.12 * You should have received a copy of the GNU General Public License 7.13 * along with Andoid Caldav Sync Adapter Free. 7.14 * If not, see <http://www.gnu.org/licenses/>. 7.15 - * 7.16 + * 7.17 */ 7.18 7.19 package org.gege.caldavsyncadapter.authenticator; 7.20 7.21 -import java.io.IOException; 7.22 -import java.io.UnsupportedEncodingException; 7.23 -import java.net.MalformedURLException; 7.24 -import java.net.URISyntaxException; 7.25 - 7.26 -import javax.xml.parsers.ParserConfigurationException; 7.27 - 7.28 -import org.apache.http.conn.HttpHostConnectException; 7.29 -import org.gege.caldavsyncadapter.R; 7.30 -import org.gege.caldavsyncadapter.caldav.CaldavFacade; 7.31 -import org.gege.caldavsyncadapter.caldav.CaldavFacade.TestConnectionResult; 7.32 -import org.xml.sax.SAXException; 7.33 - 7.34 import android.accounts.Account; 7.35 import android.accounts.AccountManager; 7.36 import android.animation.Animator; 7.37 @@ -45,430 +32,480 @@ 7.38 import android.os.AsyncTask; 7.39 import android.os.Build; 7.40 import android.os.Bundle; 7.41 +import android.text.Editable; 7.42 import android.text.TextUtils; 7.43 +import android.text.TextWatcher; 7.44 import android.util.Log; 7.45 import android.view.KeyEvent; 7.46 import android.view.Menu; 7.47 import android.view.View; 7.48 import android.view.inputmethod.EditorInfo; 7.49 +import android.widget.CheckBox; 7.50 import android.widget.EditText; 7.51 import android.widget.TextView; 7.52 import android.widget.Toast; 7.53 7.54 +import org.apache.http.conn.HttpHostConnectException; 7.55 +import org.gege.caldavsyncadapter.Constants; 7.56 +import org.gege.caldavsyncadapter.R; 7.57 +import org.gege.caldavsyncadapter.caldav.CaldavFacade; 7.58 +import org.gege.caldavsyncadapter.caldav.CaldavFacade.TestConnectionResult; 7.59 +import org.xml.sax.SAXException; 7.60 + 7.61 +import java.io.IOException; 7.62 +import java.io.UnsupportedEncodingException; 7.63 +import java.net.MalformedURLException; 7.64 +import java.net.URISyntaxException; 7.65 +import java.util.Locale; 7.66 + 7.67 +import javax.xml.parsers.ParserConfigurationException; 7.68 + 7.69 /** 7.70 * Activity which displays a login screen to the user, offering registration as 7.71 * well. 7.72 */ 7.73 public class AuthenticatorActivity extends Activity { 7.74 - 7.75 - private static final String TAG = "AuthenticatorActivity"; 7.76 7.77 - private static final String ACCOUNT_TYPE = "org.gege.caldavsyncadapter.account"; 7.78 + private static final String TAG = "AuthenticatorActivity"; 7.79 7.80 - public static final String USER_DATA_URL_KEY = "USER_DATA_URL_KEY"; 7.81 - public static final String USER_DATA_USERNAME = "USER_DATA_USERNAME"; 7.82 - public static final String USER_DATA_VERSION = "USER_DATA_VERSION"; 7.83 - public static final String CURRENT_USER_DATA_VERSION = "1"; 7.84 - 7.85 - public static final String ACCOUNT_NAME_SPLITTER = "@"; 7.86 - 7.87 - /** 7.88 - * The default email to populate the email field with. 7.89 - */ 7.90 - public static final String EXTRA_EMAIL = "com.example.android.authenticatordemo.extra.EMAIL"; 7.91 + private static final String ACCOUNT_TYPE = "org.gege.caldavsyncadapter.account"; 7.92 7.93 - /** 7.94 - * Keep track of the login task to ensure we can cancel it if requested. 7.95 - */ 7.96 - private UserLoginTask mAuthTask = null; 7.97 + public static final String USER_DATA_URL_KEY = "USER_DATA_URL_KEY"; 7.98 + public static final String USER_DATA_USERNAME = "USER_DATA_USERNAME"; 7.99 + public static final String USER_DATA_VERSION = "USER_DATA_VERSION"; 7.100 + public static final String CURRENT_USER_DATA_VERSION = "1"; 7.101 7.102 - // Values for email and password at the time of the login attempt. 7.103 - private String mUser; 7.104 - private String mPassword; 7.105 - private Context mContext; 7.106 + public static final String ACCOUNT_NAME_SPLITTER = "@"; 7.107 7.108 - // UI references. 7.109 - private EditText mUserView; 7.110 - private EditText mPasswordView; 7.111 - private View mLoginFormView; 7.112 - private View mLoginStatusView; 7.113 - private TextView mLoginStatusMessageView; 7.114 + /** 7.115 + * The default email to populate the email field with. 7.116 + */ 7.117 + public static final String EXTRA_EMAIL = "com.example.android.authenticatordemo.extra.EMAIL"; 7.118 7.119 - private AccountManager mAccountManager; 7.120 + /** 7.121 + * Keep track of the login task to ensure we can cancel it if requested. 7.122 + */ 7.123 + private UserLoginTask mAuthTask = null; 7.124 7.125 - private String mURL; 7.126 - private EditText mURLView; 7.127 - 7.128 - private String mAccountname; 7.129 - private EditText mAccountnameView; 7.130 - 7.131 - public AuthenticatorActivity() { 7.132 - super(); 7.133 - 7.134 - } 7.135 - 7.136 - @Override 7.137 - protected void onCreate(Bundle savedInstanceState) { 7.138 - super.onCreate(savedInstanceState); 7.139 - 7.140 - mAccountManager = AccountManager.get(this); 7.141 + // Values for email and password at the time of the login attempt. 7.142 + private String mUser; 7.143 + private String mPassword; 7.144 + private String mTrustAll; 7.145 + private Context mContext; 7.146 7.147 - setContentView(R.layout.activity_authenticator); 7.148 + // UI references. 7.149 + private EditText mUserView; 7.150 + private EditText mPasswordView; 7.151 + private View mLoginFormView; 7.152 + private View mLoginStatusView; 7.153 + private TextView mLoginStatusMessageView; 7.154 + private CheckBox mTrustCheckBox; 7.155 7.156 - // Set up the login form. 7.157 - mUser = getIntent().getStringExtra(EXTRA_EMAIL); 7.158 - mUserView = (EditText) findViewById(R.id.user); 7.159 - mUserView.setText(mUser); 7.160 - 7.161 - mContext = getBaseContext(); 7.162 + private AccountManager mAccountManager; 7.163 7.164 - mPasswordView = (EditText) findViewById(R.id.password); 7.165 - mPasswordView 7.166 - .setOnEditorActionListener(new TextView.OnEditorActionListener() { 7.167 - @Override 7.168 - public boolean onEditorAction(TextView textView, int id, 7.169 - KeyEvent keyEvent) { 7.170 - if (id == R.id.login || id == EditorInfo.IME_NULL) { 7.171 - attemptLogin(); 7.172 - return true; 7.173 - } 7.174 - return false; 7.175 - } 7.176 - }); 7.177 + private String mURL; 7.178 + private EditText mURLView; 7.179 7.180 - 7.181 - mURLView = (EditText) findViewById(R.id.url); 7.182 - 7.183 - mAccountnameView = (EditText) findViewById(R.id.accountname); 7.184 - 7.185 - mLoginFormView = findViewById(R.id.login_form); 7.186 - mLoginStatusView = findViewById(R.id.login_status); 7.187 - mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message); 7.188 + private String mAccountname; 7.189 + private EditText mAccountnameView; 7.190 7.191 - findViewById(R.id.sign_in_button).setOnClickListener( 7.192 - new View.OnClickListener() { 7.193 - @Override 7.194 - public void onClick(View view) { 7.195 - attemptLogin(); 7.196 - } 7.197 - }); 7.198 - 7.199 - 7.200 - } 7.201 + public AuthenticatorActivity() { 7.202 + super(); 7.203 7.204 - @Override 7.205 - public boolean onCreateOptionsMenu(Menu menu) { 7.206 - super.onCreateOptionsMenu(menu); 7.207 - getMenuInflater().inflate(R.menu.activity_authenticator, menu); 7.208 - return true; 7.209 - } 7.210 + } 7.211 7.212 - /** 7.213 - * Attempts to sign in or register the account specified by the login form. 7.214 - * If there are form errors (invalid email, missing fields, etc.), the 7.215 - * errors are presented and no actual login attempt is made. 7.216 - */ 7.217 - public void attemptLogin() { 7.218 - if (mAuthTask != null) { 7.219 - return; 7.220 - } 7.221 + @Override 7.222 + protected void onCreate(Bundle savedInstanceState) { 7.223 + super.onCreate(savedInstanceState); 7.224 7.225 - // Reset errors. 7.226 - mUserView.setError(null); 7.227 - mPasswordView.setError(null); 7.228 + mAccountManager = AccountManager.get(this); 7.229 7.230 - // Store values at the time of the login attempt. 7.231 - mUser = mUserView.getText().toString(); 7.232 - mPassword = mPasswordView.getText().toString(); 7.233 - mURL = mURLView.getText().toString(); 7.234 - mAccountname = mAccountnameView.getText().toString(); 7.235 + setContentView(R.layout.activity_authenticator); 7.236 7.237 - boolean cancel = false; 7.238 - View focusView = null; 7.239 - 7.240 - if (!mAccountname.equals("")) { 7.241 - Account TestAccount = new Account(mAccountname, ACCOUNT_TYPE); 7.242 - String TestUrl = mAccountManager.getUserData(TestAccount, AuthenticatorActivity.USER_DATA_URL_KEY); 7.243 - if (TestUrl != null) { 7.244 - mAccountnameView.setError(getString(R.string.error_account_already_in_use)); 7.245 - focusView = mAccountnameView; 7.246 - cancel = true; 7.247 - } 7.248 - } 7.249 + // Set up the login form. 7.250 + mUser = getIntent().getStringExtra(EXTRA_EMAIL); 7.251 + mUserView = (EditText) findViewById(R.id.user); 7.252 + mUserView.setText(mUser); 7.253 7.254 - // Check for a valid password. 7.255 - if (TextUtils.isEmpty(mPassword)) { 7.256 - mPasswordView.setError(getString(R.string.error_field_required)); 7.257 - focusView = mPasswordView; 7.258 - cancel = true; 7.259 - } else if (mPassword.length() < 4) { 7.260 - mPasswordView.setError(getString(R.string.error_invalid_password)); 7.261 - focusView = mPasswordView; 7.262 - cancel = true; 7.263 - } 7.264 + mContext = getBaseContext(); 7.265 7.266 - // Check for a valid email address. 7.267 - if (TextUtils.isEmpty(mUser)) { 7.268 - mUserView.setError(getString(R.string.error_field_required)); 7.269 - focusView = mUserView; 7.270 - cancel = true; 7.271 - } 7.272 - //else if (!mUser.contains("@")) { 7.273 - // mUserView.setError(getString(R.string.error_invalid_email)); 7.274 - // focusView = mUserView; 7.275 - // cancel = true; 7.276 - //} 7.277 + mPasswordView = (EditText) findViewById(R.id.password); 7.278 + mPasswordView 7.279 + .setOnEditorActionListener(new TextView.OnEditorActionListener() { 7.280 + @Override 7.281 + public boolean onEditorAction(TextView textView, int id, 7.282 + KeyEvent keyEvent) { 7.283 + if (id == R.id.login || id == EditorInfo.IME_NULL) { 7.284 + attemptLogin(); 7.285 + return true; 7.286 + } 7.287 + return false; 7.288 + } 7.289 + }); 7.290 7.291 - if (cancel) { 7.292 - // There was an error; don't attempt login and focus the first 7.293 - // form field with an error. 7.294 - focusView.requestFocus(); 7.295 - } else { 7.296 - // Show a progress spinner, and kick off a background task to 7.297 - // perform the user login attempt. 7.298 - mLoginStatusMessageView.setText(R.string.login_progress_signing_in); 7.299 - showProgress(true); 7.300 - mAuthTask = new UserLoginTask(); 7.301 - mAuthTask.execute((Void) null); 7.302 - } 7.303 - } 7.304 7.305 - /** 7.306 - * Shows the progress UI and hides the login form. 7.307 - */ 7.308 - @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 7.309 - private void showProgress(final boolean show) { 7.310 - // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow 7.311 - // for very easy animations. If available, use these APIs to fade-in 7.312 - // the progress spinner. 7.313 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { 7.314 - int shortAnimTime = getResources().getInteger( 7.315 - android.R.integer.config_shortAnimTime); 7.316 + mURLView = (EditText) findViewById(R.id.url); 7.317 + // if the URL start with "https" show the option to disable SSL host verification 7.318 + mURLView.addTextChangedListener(new TextWatcher() { 7.319 + @Override 7.320 + public void onTextChanged(CharSequence s, int start, int before, int count) { 7.321 + String url = ((EditText) findViewById(R.id.url)).getText().toString(); 7.322 + int visible = url.toLowerCase(Locale.getDefault()) 7.323 + .startsWith("https") ? View.VISIBLE : View.GONE; 7.324 + ((CheckBox) findViewById(R.id.trustall)).setVisibility(visible); 7.325 + } 7.326 7.327 - mLoginStatusView.setVisibility(View.VISIBLE); 7.328 - mLoginStatusView.animate().setDuration(shortAnimTime) 7.329 - .alpha(show ? 1 : 0) 7.330 - .setListener(new AnimatorListenerAdapter() { 7.331 - @Override 7.332 - public void onAnimationEnd(Animator animation) { 7.333 - mLoginStatusView.setVisibility(show ? View.VISIBLE 7.334 - : View.GONE); 7.335 - } 7.336 - }); 7.337 + @Override 7.338 + public void beforeTextChanged(CharSequence s, int start, int count, 7.339 + int after) { 7.340 + } 7.341 7.342 - mLoginFormView.setVisibility(View.VISIBLE); 7.343 - mLoginFormView.animate().setDuration(shortAnimTime) 7.344 - .alpha(show ? 0 : 1) 7.345 - .setListener(new AnimatorListenerAdapter() { 7.346 - @Override 7.347 - public void onAnimationEnd(Animator animation) { 7.348 - mLoginFormView.setVisibility(show ? View.GONE 7.349 - : View.VISIBLE); 7.350 - } 7.351 - }); 7.352 - } else { 7.353 - // The ViewPropertyAnimator APIs are not available, so simply show 7.354 - // and hide the relevant UI components. 7.355 - mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE); 7.356 - mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 7.357 - } 7.358 - } 7.359 + @Override 7.360 + public void afterTextChanged(Editable s) { 7.361 + } 7.362 + }); 7.363 7.364 - 7.365 - protected enum LoginResult { 7.366 - MalformedURLException, 7.367 - GeneralSecurityException, 7.368 - UnkonwnException, 7.369 - WrongCredentials, 7.370 - InvalidResponse, 7.371 - WrongUrl, 7.372 - ConnectionRefused, 7.373 - Success_Calendar, 7.374 - Success_Collection, 7.375 - Account_Already_In_Use 7.376 - } 7.377 - 7.378 - 7.379 - /** 7.380 - * Represents an asynchronous login/registration task used to authenticate 7.381 - * the user. 7.382 - */ 7.383 - public class UserLoginTask extends AsyncTask<Void, Void, LoginResult> { 7.384 + mAccountnameView = (EditText) findViewById(R.id.accountname); 7.385 7.386 - @Override 7.387 - protected LoginResult doInBackground(Void... params) { 7.388 + mLoginFormView = findViewById(R.id.login_form); 7.389 + mLoginStatusView = findViewById(R.id.login_status); 7.390 + mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message); 7.391 7.392 - TestConnectionResult result = null; 7.393 - 7.394 - try { 7.395 - CaldavFacade facade = new CaldavFacade(mUser, mPassword, mURL); 7.396 - String version = ""; 7.397 - try { 7.398 - version = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName; 7.399 - } catch (NameNotFoundException e) { 7.400 - version = "unknown"; 7.401 - e.printStackTrace(); 7.402 - } 7.403 - facade.setVersion(version); 7.404 - result = facade.testConnection(); 7.405 - Log.i(TAG, "testConnection status="+result); 7.406 - } catch (HttpHostConnectException e) { 7.407 - Log.w(TAG,"testConnection", e); 7.408 - return LoginResult.ConnectionRefused; 7.409 - } catch (MalformedURLException e) { 7.410 - Log.w(TAG,"testConnection", e); 7.411 - return LoginResult.MalformedURLException; 7.412 - } catch (UnsupportedEncodingException e) { 7.413 - Log.w(TAG,"testConnection", e); 7.414 - return LoginResult.UnkonwnException; 7.415 - } catch (ParserConfigurationException e) { 7.416 - Log.w(TAG,"testConnection", e); 7.417 - return LoginResult.UnkonwnException; 7.418 - } catch (SAXException e) { 7.419 - Log.w(TAG,"testConnection", e); 7.420 - return LoginResult.InvalidResponse; 7.421 - } catch (IOException e) { 7.422 - Log.w(TAG,"testConnection", e); 7.423 - return LoginResult.UnkonwnException; 7.424 - } catch (URISyntaxException e) { 7.425 - Log.w(TAG,"testConnection", e); 7.426 - return LoginResult.MalformedURLException; 7.427 - } 7.428 + findViewById(R.id.sign_in_button).setOnClickListener( 7.429 + new View.OnClickListener() { 7.430 + @Override 7.431 + public void onClick(View view) { 7.432 + attemptLogin(); 7.433 + } 7.434 + } 7.435 + ); 7.436 7.437 - if (result == null) { 7.438 - return LoginResult.UnkonwnException; 7.439 - } 7.440 - 7.441 - switch (result) { 7.442 - 7.443 - case SUCCESS: 7.444 - boolean OldAccount = false; 7.445 - LoginResult Result = LoginResult.Success_Calendar; 7.446 + mTrustCheckBox = (CheckBox) findViewById(R.id.trustall); 7.447 7.448 - if (OldAccount) { 7.449 - final Account account = new Account(mUser, ACCOUNT_TYPE); 7.450 - if (mAccountManager.addAccountExplicitly(account, mPassword, null)) { 7.451 - Log.v(TAG,"new account created"); 7.452 - mAccountManager.setUserData(account, USER_DATA_URL_KEY, mURL); 7.453 - } else { 7.454 - Log.v(TAG,"no new account created"); 7.455 - Result = LoginResult.Account_Already_In_Use; 7.456 - } 7.457 - } else { 7.458 - final Account account; 7.459 - if (mAccountname.equals("")) { 7.460 - account = new Account(mUser + ACCOUNT_NAME_SPLITTER + mURL, ACCOUNT_TYPE); 7.461 - } else { 7.462 - account = new Account(mAccountname, ACCOUNT_TYPE); 7.463 - } 7.464 - if (mAccountManager.addAccountExplicitly(account, mPassword, null)) { 7.465 - Log.v(TAG,"new account created"); 7.466 - mAccountManager.setUserData(account, USER_DATA_URL_KEY, mURL); 7.467 - mAccountManager.setUserData(account, USER_DATA_USERNAME, mUser); 7.468 - mAccountManager.setUserData(account, USER_DATA_VERSION, CURRENT_USER_DATA_VERSION); 7.469 - } else { 7.470 - Log.v(TAG,"no new account created"); 7.471 - Result = LoginResult.Account_Already_In_Use; 7.472 - } 7.473 - } 7.474 - 7.475 - return Result; 7.476 7.477 - case WRONG_CREDENTIAL: 7.478 - return LoginResult.WrongCredentials; 7.479 - 7.480 - case WRONG_SERVER_STATUS: 7.481 - return LoginResult.InvalidResponse; 7.482 - 7.483 - case WRONG_URL: 7.484 - return LoginResult.WrongUrl; 7.485 - 7.486 - case WRONG_ANSWER: 7.487 - return LoginResult.InvalidResponse; 7.488 - 7.489 - default: 7.490 - return LoginResult.UnkonwnException; 7.491 - 7.492 - } 7.493 - 7.494 - } 7.495 - 7.496 + } 7.497 7.498 - @Override 7.499 - protected void onPostExecute(final LoginResult result) { 7.500 - mAuthTask = null; 7.501 - showProgress(false); 7.502 + @Override 7.503 + public boolean onCreateOptionsMenu(Menu menu) { 7.504 + super.onCreateOptionsMenu(menu); 7.505 + return true; 7.506 + } 7.507 7.508 - int duration = Toast.LENGTH_SHORT; 7.509 - Toast toast = null; 7.510 - 7.511 - switch (result) { 7.512 - case Success_Calendar: 7.513 - toast = Toast.makeText(getApplicationContext(), R.string.success_calendar, duration); 7.514 - toast.show(); 7.515 - finish(); 7.516 - break; 7.517 - 7.518 - case Success_Collection: 7.519 - toast = Toast.makeText(getApplicationContext(), R.string.success_collection, duration); 7.520 - toast.show(); 7.521 - finish(); 7.522 - break; 7.523 - 7.524 - case MalformedURLException: 7.525 - 7.526 - toast = Toast.makeText(getApplicationContext(), R.string.error_incorrect_url_format, duration); 7.527 - toast.show(); 7.528 - mURLView.setError(getString(R.string.error_incorrect_url_format)); 7.529 - mURLView.requestFocus(); 7.530 - break; 7.531 - case InvalidResponse: 7.532 - toast = Toast.makeText(getApplicationContext(), R.string.error_invalid_server_answer, duration); 7.533 - toast.show(); 7.534 - mURLView.setError(getString(R.string.error_invalid_server_answer)); 7.535 - mURLView.requestFocus(); 7.536 - break; 7.537 - case WrongUrl: 7.538 - toast = Toast.makeText(getApplicationContext(), R.string.error_wrong_url, duration); 7.539 - toast.show(); 7.540 - mURLView.setError(getString(R.string.error_wrong_url)); 7.541 - mURLView.requestFocus(); 7.542 - break; 7.543 - 7.544 - case WrongCredentials: 7.545 - mPasswordView.setError(getString(R.string.error_incorrect_password)); 7.546 - mPasswordView.requestFocus(); 7.547 - break; 7.548 - 7.549 - case ConnectionRefused: 7.550 - toast = Toast.makeText(getApplicationContext(), R.string.error_connection_refused, duration); 7.551 - toast.show(); 7.552 - mURLView.setError(getString(R.string.error_connection_refused)); 7.553 - mURLView.requestFocus(); 7.554 - break; 7.555 - case Account_Already_In_Use: 7.556 - toast = Toast.makeText(getApplicationContext(), R.string.error_account_already_in_use, duration); 7.557 - toast.show(); 7.558 - mURLView.setError(getString(R.string.error_account_already_in_use)); 7.559 - mURLView.requestFocus(); 7.560 - break; 7.561 - default: 7.562 - toast = Toast.makeText(getApplicationContext(), R.string.error_unkown_error, duration); 7.563 - toast.show(); 7.564 - mURLView.setError(getString(R.string.error_unkown_error)); 7.565 - mURLView.requestFocus(); 7.566 - break; 7.567 - } 7.568 - 7.569 - 7.570 - 7.571 - 7.572 - } 7.573 + /** 7.574 + * Attempts to sign in or register the account specified by the login form. 7.575 + * If there are form errors (invalid email, missing fields, etc.), the 7.576 + * errors are presented and no actual login attempt is made. 7.577 + */ 7.578 + public void attemptLogin() { 7.579 + if (mAuthTask != null) { 7.580 + return; 7.581 + } 7.582 7.583 - @Override 7.584 - protected void onCancelled() { 7.585 - mAuthTask = null; 7.586 - showProgress(false); 7.587 - } 7.588 - } 7.589 -} 7.590 + // Reset errors. 7.591 + mUserView.setError(null); 7.592 + mPasswordView.setError(null); 7.593 + 7.594 + // Store values at the time of the login attempt. 7.595 + mUser = mUserView.getText().toString(); 7.596 + mPassword = mPasswordView.getText().toString(); 7.597 + mURL = mURLView.getText().toString(); 7.598 + mAccountname = mAccountnameView.getText().toString(); 7.599 + mTrustAll = (mTrustCheckBox.isChecked() ? "false" : "true"); 7.600 + boolean cancel = false; 7.601 + View focusView = null; 7.602 + 7.603 + if (!mAccountname.equals("")) { 7.604 + Account TestAccount = new Account(mAccountname, ACCOUNT_TYPE); 7.605 + String TestUrl = mAccountManager.getUserData(TestAccount, AuthenticatorActivity.USER_DATA_URL_KEY); 7.606 + if (TestUrl != null) { 7.607 + mAccountnameView.setError(getString(R.string.error_account_already_in_use)); 7.608 + focusView = mAccountnameView; 7.609 + cancel = true; 7.610 + } 7.611 + } 7.612 + 7.613 + // Check for a valid password. 7.614 + if (TextUtils.isEmpty(mPassword)) { 7.615 + mPasswordView.setError(getString(R.string.error_field_required)); 7.616 + focusView = mPasswordView; 7.617 + cancel = true; 7.618 + } 7.619 + 7.620 + // Check for a valid email address. 7.621 + if (TextUtils.isEmpty(mUser)) { 7.622 + mUserView.setError(getString(R.string.error_field_required)); 7.623 + focusView = mUserView; 7.624 + cancel = true; 7.625 + } 7.626 + //else if (!mUser.contains("@")) { 7.627 + // mUserView.setError(getString(R.string.error_invalid_email)); 7.628 + // focusView = mUserView; 7.629 + // cancel = true; 7.630 + //} 7.631 + 7.632 + if (cancel) { 7.633 + // There was an error; don't attempt login and focus the first 7.634 + // form field with an error. 7.635 + focusView.requestFocus(); 7.636 + } else { 7.637 + // Show a progress spinner, and kick off a background task to 7.638 + // perform the user login attempt. 7.639 + mLoginStatusMessageView.setText(R.string.login_progress_signing_in); 7.640 + showProgress(true); 7.641 + mAuthTask = new UserLoginTask(); 7.642 + mAuthTask.execute((Void) null); 7.643 + } 7.644 + } 7.645 + 7.646 + /** 7.647 + * Shows the progress UI and hides the login form. 7.648 + */ 7.649 + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 7.650 + private void showProgress(final boolean show) { 7.651 + // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow 7.652 + // for very easy animations. If available, use these APIs to fade-in 7.653 + // the progress spinner. 7.654 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { 7.655 + int shortAnimTime = getResources().getInteger( 7.656 + android.R.integer.config_shortAnimTime); 7.657 + 7.658 + mLoginStatusView.setVisibility(View.VISIBLE); 7.659 + mLoginStatusView.animate().setDuration(shortAnimTime) 7.660 + .alpha(show ? 1 : 0) 7.661 + .setListener(new AnimatorListenerAdapter() { 7.662 + @Override 7.663 + public void onAnimationEnd(Animator animation) { 7.664 + mLoginStatusView.setVisibility(show ? View.VISIBLE 7.665 + : View.GONE); 7.666 + } 7.667 + }); 7.668 + 7.669 + mLoginFormView.setVisibility(View.VISIBLE); 7.670 + mLoginFormView.animate().setDuration(shortAnimTime) 7.671 + .alpha(show ? 0 : 1) 7.672 + .setListener(new AnimatorListenerAdapter() { 7.673 + @Override 7.674 + public void onAnimationEnd(Animator animation) { 7.675 + mLoginFormView.setVisibility(show ? View.GONE 7.676 + : View.VISIBLE); 7.677 + } 7.678 + }); 7.679 + } else { 7.680 + // The ViewPropertyAnimator APIs are not available, so simply show 7.681 + // and hide the relevant UI components. 7.682 + mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE); 7.683 + mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 7.684 + } 7.685 + } 7.686 + 7.687 + 7.688 + protected enum LoginResult { 7.689 + MalformedURLException, 7.690 + GeneralSecurityException, 7.691 + UnkonwnException, 7.692 + WrongCredentials, 7.693 + InvalidResponse, 7.694 + WrongUrl, 7.695 + ConnectionRefused, 7.696 + Success_Calendar, 7.697 + Success_Collection, 7.698 + UNTRUSTED_CERT, 7.699 + Account_Already_In_Use 7.700 + } 7.701 + 7.702 + 7.703 + /** 7.704 + * Represents an asynchronous login/registration task used to authenticate 7.705 + * the user. 7.706 + */ 7.707 + public class UserLoginTask extends AsyncTask<Void, Void, LoginResult> { 7.708 + 7.709 + @Override 7.710 + protected LoginResult doInBackground(Void... params) { 7.711 + 7.712 + TestConnectionResult result = null; 7.713 + 7.714 + try { 7.715 + CaldavFacade facade = new CaldavFacade(mUser, mPassword, mURL, mTrustAll); 7.716 + String version = ""; 7.717 + try { 7.718 + version = mContext.getPackageManager() 7.719 + .getPackageInfo(mContext.getPackageName(), 0).versionName; 7.720 + } catch (NameNotFoundException e) { 7.721 + version = "unknown"; 7.722 + e.printStackTrace(); 7.723 + } 7.724 + facade.setVersion(version); 7.725 + result = facade.testConnection(); 7.726 + Log.i(TAG, "testConnection status=" + result); 7.727 + } catch (HttpHostConnectException e) { 7.728 + Log.w(TAG, "testConnection", e); 7.729 + return LoginResult.ConnectionRefused; 7.730 + } catch (MalformedURLException e) { 7.731 + Log.w(TAG, "testConnection", e); 7.732 + return LoginResult.MalformedURLException; 7.733 + } catch (UnsupportedEncodingException e) { 7.734 + Log.w(TAG, "testConnection", e); 7.735 + return LoginResult.UnkonwnException; 7.736 + } catch (ParserConfigurationException e) { 7.737 + Log.w(TAG, "testConnection", e); 7.738 + return LoginResult.UnkonwnException; 7.739 + } catch (SAXException e) { 7.740 + Log.w(TAG, "testConnection", e); 7.741 + return LoginResult.InvalidResponse; 7.742 + } catch (IOException e) { 7.743 + Log.w(TAG, "testConnection", e); 7.744 + return LoginResult.UnkonwnException; 7.745 + } catch (URISyntaxException e) { 7.746 + Log.w(TAG, "testConnection", e); 7.747 + return LoginResult.MalformedURLException; 7.748 + } 7.749 + 7.750 + if (result == null) { 7.751 + return LoginResult.UnkonwnException; 7.752 + } 7.753 + 7.754 + switch (result) { 7.755 + 7.756 + case SSL_ERROR: 7.757 + return LoginResult.UNTRUSTED_CERT; 7.758 + case SUCCESS: 7.759 + boolean OldAccount = false; 7.760 + LoginResult Result = LoginResult.Success_Calendar; 7.761 + 7.762 + if (OldAccount) { 7.763 + final Account account = new Account(mUser, ACCOUNT_TYPE); 7.764 + if (mAccountManager.addAccountExplicitly(account, mPassword, null)) { 7.765 + Log.v(TAG, "new account created"); 7.766 + mAccountManager.setUserData(account, USER_DATA_URL_KEY, mURL); 7.767 + } else { 7.768 + Log.v(TAG, "no new account created"); 7.769 + Result = LoginResult.Account_Already_In_Use; 7.770 + } 7.771 + } else { 7.772 + final Account account; 7.773 + if (mAccountname.equals("")) { 7.774 + account = new Account(mUser + ACCOUNT_NAME_SPLITTER + mURL, ACCOUNT_TYPE); 7.775 + } else { 7.776 + account = new Account(mAccountname, ACCOUNT_TYPE); 7.777 + } 7.778 + if (mAccountManager.addAccountExplicitly(account, mPassword, null)) { 7.779 + Log.v(TAG, "new account created"); 7.780 + mAccountManager.setUserData(account, USER_DATA_URL_KEY, mURL); 7.781 + mAccountManager.setUserData(account, USER_DATA_USERNAME, mUser); 7.782 + mAccountManager.setUserData(account, USER_DATA_VERSION, CURRENT_USER_DATA_VERSION); 7.783 + mAccountManager.setUserData(account, Constants.USER_DATA_TRUST_ALL_KEY, mTrustAll); 7.784 + } else { 7.785 + Log.v(TAG, "no new account created"); 7.786 + Result = LoginResult.Account_Already_In_Use; 7.787 + } 7.788 + } 7.789 + 7.790 + return Result; 7.791 + 7.792 + case WRONG_CREDENTIAL: 7.793 + return LoginResult.WrongCredentials; 7.794 + 7.795 + case WRONG_SERVER_STATUS: 7.796 + return LoginResult.InvalidResponse; 7.797 + 7.798 + case WRONG_URL: 7.799 + return LoginResult.WrongUrl; 7.800 + 7.801 + case WRONG_ANSWER: 7.802 + return LoginResult.InvalidResponse; 7.803 + 7.804 + default: 7.805 + return LoginResult.UnkonwnException; 7.806 + 7.807 + } 7.808 + 7.809 + } 7.810 + 7.811 + 7.812 + @Override 7.813 + protected void onPostExecute(final LoginResult result) { 7.814 + mAuthTask = null; 7.815 + showProgress(false); 7.816 + 7.817 + int duration = Toast.LENGTH_SHORT; 7.818 + Toast toast = null; 7.819 + 7.820 + switch (result) { 7.821 + case Success_Calendar: 7.822 + toast = Toast.makeText(getApplicationContext(), R.string.success_calendar, duration); 7.823 + toast.show(); 7.824 + finish(); 7.825 + break; 7.826 + 7.827 + case Success_Collection: 7.828 + toast = Toast.makeText(getApplicationContext(), R.string.success_collection, duration); 7.829 + toast.show(); 7.830 + finish(); 7.831 + break; 7.832 + 7.833 + case MalformedURLException: 7.834 + 7.835 + toast = Toast.makeText(getApplicationContext(), R.string.error_incorrect_url_format, duration); 7.836 + toast.show(); 7.837 + mURLView.setError(getString(R.string.error_incorrect_url_format)); 7.838 + mURLView.requestFocus(); 7.839 + break; 7.840 + case InvalidResponse: 7.841 + toast = Toast.makeText(getApplicationContext(), R.string.error_invalid_server_answer, duration); 7.842 + toast.show(); 7.843 + mURLView.setError(getString(R.string.error_invalid_server_answer)); 7.844 + mURLView.requestFocus(); 7.845 + break; 7.846 + case WrongUrl: 7.847 + toast = Toast.makeText(getApplicationContext(), R.string.error_wrong_url, duration); 7.848 + toast.show(); 7.849 + mURLView.setError(getString(R.string.error_wrong_url)); 7.850 + mURLView.requestFocus(); 7.851 + break; 7.852 + 7.853 + case GeneralSecurityException: 7.854 + break; 7.855 + case UnkonwnException: 7.856 + break; 7.857 + case WrongCredentials: 7.858 + mPasswordView.setError(getString(R.string.error_incorrect_password)); 7.859 + mPasswordView.requestFocus(); 7.860 + break; 7.861 + 7.862 + case ConnectionRefused: 7.863 + toast = Toast.makeText(getApplicationContext(), R.string.error_connection_refused, duration); 7.864 + toast.show(); 7.865 + mURLView.setError(getString(R.string.error_connection_refused)); 7.866 + mURLView.requestFocus(); 7.867 + break; 7.868 + case UNTRUSTED_CERT: 7.869 + toast = Toast.makeText(getApplicationContext(), getString(R.string.error_untrusted_certificate), duration); 7.870 + toast.show(); 7.871 + mURLView.setError(getString(R.string.error_ssl)); 7.872 + mURLView.requestFocus(); 7.873 + break; 7.874 + case Account_Already_In_Use: 7.875 + toast = Toast.makeText(getApplicationContext(), R.string.error_account_already_in_use, duration); 7.876 + toast.show(); 7.877 + mURLView.setError(getString(R.string.error_account_already_in_use)); 7.878 + mURLView.requestFocus(); 7.879 + break; 7.880 + default: 7.881 + toast = Toast.makeText(getApplicationContext(), R.string.error_unkown_error, duration); 7.882 + toast.show(); 7.883 + mURLView.setError(getString(R.string.error_unkown_error)); 7.884 + mURLView.requestFocus(); 7.885 + break; 7.886 + } 7.887 + 7.888 + 7.889 + } 7.890 + 7.891 + @Override 7.892 + protected void onCancelled() { 7.893 + mAuthTask = null; 7.894 + showProgress(false); 7.895 + } 7.896 + } 7.897 +} 7.898 \ No newline at end of file
8.1 --- a/src/org/gege/caldavsyncadapter/caldav/CaldavFacade.java Tue Feb 10 21:55:00 2015 +0100 8.2 +++ b/src/org/gege/caldavsyncadapter/caldav/CaldavFacade.java Tue Feb 10 22:40:00 2015 +0100 8.3 @@ -1,6 +1,6 @@ 8.4 /** 8.5 * Copyright (c) 2012-2013, Gerald Garcia, David Wiesner, Timo Berger 8.6 - * 8.7 + * 8.8 * This file is part of Andoid Caldav Sync Adapter Free. 8.9 * 8.10 * Andoid Caldav Sync Adapter Free is free software: you can redistribute 8.11 @@ -16,31 +16,15 @@ 8.12 * You should have received a copy of the GNU General Public License 8.13 * along with Andoid Caldav Sync Adapter Free. 8.14 * If not, see <http://www.gnu.org/licenses/>. 8.15 - * 8.16 + * 8.17 */ 8.18 8.19 package org.gege.caldavsyncadapter.caldav; 8.20 8.21 -import java.io.BufferedReader; 8.22 -import java.io.ByteArrayInputStream; 8.23 -import java.io.FileNotFoundException; 8.24 -import java.io.IOException; 8.25 -import java.io.InputStream; 8.26 -import java.io.InputStreamReader; 8.27 -import java.io.UnsupportedEncodingException; 8.28 -import java.net.MalformedURLException; 8.29 -import java.net.SocketException; 8.30 -import java.net.URI; 8.31 -import java.net.URISyntaxException; 8.32 -import java.net.URL; 8.33 -import java.util.ArrayList; 8.34 -import java.util.List; 8.35 - 8.36 -import javax.xml.parsers.DocumentBuilder; 8.37 -import javax.xml.parsers.DocumentBuilderFactory; 8.38 -import javax.xml.parsers.ParserConfigurationException; 8.39 -import javax.xml.parsers.SAXParser; 8.40 -import javax.xml.parsers.SAXParserFactory; 8.41 +import android.accounts.Account; 8.42 +import android.content.ContentProviderClient; 8.43 +import android.content.Context; 8.44 +import android.util.Log; 8.45 8.46 import org.apache.http.HttpException; 8.47 import org.apache.http.HttpHost; 8.48 @@ -76,11 +60,12 @@ 8.49 import org.apache.http.params.HttpProtocolParams; 8.50 import org.apache.http.protocol.BasicHttpContext; 8.51 import org.apache.http.protocol.HttpContext; 8.52 +import org.apache.http.util.EntityUtils; 8.53 import org.gege.caldavsyncadapter.BuildConfig; 8.54 +import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent; 8.55 +import org.gege.caldavsyncadapter.caldav.entities.CalendarList; 8.56 import org.gege.caldavsyncadapter.caldav.entities.DavCalendar; 8.57 import org.gege.caldavsyncadapter.caldav.entities.DavCalendar.CalendarSource; 8.58 -import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent; 8.59 -import org.gege.caldavsyncadapter.caldav.entities.CalendarList; 8.60 import org.gege.caldavsyncadapter.caldav.http.HttpPropFind; 8.61 import org.gege.caldavsyncadapter.caldav.http.HttpReport; 8.62 import org.gege.caldavsyncadapter.caldav.xml.CalendarHomeHandler; 8.63 @@ -96,388 +81,410 @@ 8.64 import org.xml.sax.SAXException; 8.65 import org.xml.sax.XMLReader; 8.66 8.67 -import android.accounts.Account; 8.68 -import android.content.ContentProviderClient; 8.69 -import android.content.Context; 8.70 -import android.util.Log; 8.71 +import java.io.ByteArrayInputStream; 8.72 +import java.io.FileNotFoundException; 8.73 +import java.io.IOException; 8.74 +import java.io.InputStream; 8.75 +import java.io.UnsupportedEncodingException; 8.76 +import java.net.MalformedURLException; 8.77 +import java.net.SocketException; 8.78 +import java.net.URI; 8.79 +import java.net.URISyntaxException; 8.80 +import java.net.URL; 8.81 +import java.util.ArrayList; 8.82 +import java.util.List; 8.83 + 8.84 +import javax.net.ssl.SSLException; 8.85 +import javax.xml.parsers.DocumentBuilder; 8.86 +import javax.xml.parsers.DocumentBuilderFactory; 8.87 +import javax.xml.parsers.ParserConfigurationException; 8.88 +import javax.xml.parsers.SAXParser; 8.89 +import javax.xml.parsers.SAXParserFactory; 8.90 8.91 public class CaldavFacade { 8.92 - private static final String TAG = "CaldavFacade"; 8.93 + private static final String TAG = "CaldavFacade"; 8.94 8.95 - private final static String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 8.96 + private final static String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 8.97 8.98 - private String USER_AGENT = "CalDAV Sync Adapter (Android) https://github.com/gggard/AndroidCaldavSyncAdapater"; 8.99 - private String VERSION = ""; 8.100 + private String USER_AGENT = "CalDAV Sync Adapter (Android) https://github.com/gggard/AndroidCaldavSyncAdapater"; 8.101 + private String VERSION = ""; 8.102 8.103 - private static HttpClient httpClient; 8.104 - private HttpContext mContext = null; 8.105 - private AuthState mLastAuthState = null; 8.106 - private AuthScope mLastAuthScope = null; 8.107 - 8.108 - private boolean trustAll = true; 8.109 + private static HttpClient httpClient; 8.110 + private HttpContext mContext = null; 8.111 + private AuthState mLastAuthState = null; 8.112 + private AuthScope mLastAuthScope = null; 8.113 8.114 - private URL url; 8.115 + private boolean mTrustAll = true; 8.116 8.117 - private static HttpHost targetHost; 8.118 - 8.119 - private int lastStatusCode; 8.120 - private String lastETag; 8.121 - private String lastDav; 8.122 + private URL url; 8.123 8.124 - private String mstrcHeaderIfMatch = "If-Match"; 8.125 - private String mstrcHeaderIfNoneMatch = "If-None-Match"; 8.126 - 8.127 - private Account mAccount = null; 8.128 - private ContentProviderClient mProvider; 8.129 - 8.130 - protected HttpClient getHttpClient() { 8.131 + private static HttpHost targetHost; 8.132 8.133 - HttpParams params = new BasicHttpParams(); 8.134 - params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30); 8.135 - params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30)); 8.136 - params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false); 8.137 - HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 8.138 + private int lastStatusCode; 8.139 + private String lastETag; 8.140 + private String lastDav; 8.141 8.142 - SchemeRegistry registry = new SchemeRegistry(); 8.143 - registry.register(new Scheme("http", new PlainSocketFactory(), 80)); 8.144 - registry.register(new Scheme("https", (trustAll ? EasySSLSocketFactory.getSocketFactory() : SSLSocketFactory.getSocketFactory()), 443)); 8.145 - DefaultHttpClient client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, registry), params); 8.146 - 8.147 - return client; 8.148 - } 8.149 + private String mstrcHeaderIfMatch = "If-Match"; 8.150 + private String mstrcHeaderIfNoneMatch = "If-None-Match"; 8.151 8.152 - public CaldavFacade(String mUser, String mPassword, String mURL) throws MalformedURLException { 8.153 - url = new URL(mURL); 8.154 + private Account mAccount = null; 8.155 + private ContentProviderClient mProvider; 8.156 8.157 - httpClient = getHttpClient(); 8.158 - UsernamePasswordCredentials upc = new UsernamePasswordCredentials(mUser, mPassword); 8.159 + protected HttpClient getHttpClient() { 8.160 8.161 - AuthScope as = null; 8.162 - as = new AuthScope(url.getHost(), -1); 8.163 - ((AbstractHttpClient) httpClient).getCredentialsProvider().setCredentials(as, upc); 8.164 - 8.165 - mContext = new BasicHttpContext(); 8.166 - CredentialsProvider credProvider = ((AbstractHttpClient) httpClient).getCredentialsProvider(); 8.167 - mContext.setAttribute(ClientContext.CREDS_PROVIDER, credProvider); 8.168 - 8.169 - //http://dlinsin.blogspot.de/2009/08/http-basic-authentication-with-android.html 8.170 - ((AbstractHttpClient) httpClient).addRequestInterceptor(preemptiveAuth, 0); 8.171 + HttpParams params = new BasicHttpParams(); 8.172 + params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30); 8.173 + params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30)); 8.174 + params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false); 8.175 + HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 8.176 8.177 - String proto = "http"; 8.178 - int port = 80; 8.179 + SchemeRegistry registry = new SchemeRegistry(); 8.180 + registry.register(new Scheme("http", new PlainSocketFactory(), 80)); 8.181 + registry.register(new Scheme("https", (mTrustAll ? EasySSLSocketFactory.getSocketFactory() : SSLSocketFactory 8.182 + .getSocketFactory()), 443)); 8.183 + DefaultHttpClient client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, registry), params); 8.184 8.185 - if (url.getProtocol().equalsIgnoreCase("https")) { 8.186 - proto = "https"; 8.187 - if (url.getPort() == -1) 8.188 - port = 443; 8.189 - else 8.190 - port = url.getPort(); 8.191 - } 8.192 + return client; 8.193 + } 8.194 8.195 - if (url.getProtocol().equalsIgnoreCase("http")) { 8.196 - proto = "http"; 8.197 - if (url.getPort() == -1) 8.198 - port = 80; 8.199 - else 8.200 - port = url.getPort(); 8.201 - } 8.202 - targetHost = new HttpHost(url.getHost(), port, proto); 8.203 - } 8.204 - 8.205 - //http://dlinsin.blogspot.de/2009/08/http-basic-authentication-with-android.html 8.206 - HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() { 8.207 - @Override 8.208 - public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { 8.209 - AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); 8.210 + public CaldavFacade(String mUser, String mPassword, String mURL, String trustAll) throws MalformedURLException { 8.211 + url = new URL(mURL); 8.212 8.213 - if (authState.getAuthScheme() == null) { 8.214 - if (mLastAuthState != null) { 8.215 - Log.d(TAG, "LastAuthState: restored with user " + mLastAuthState.getCredentials().getUserPrincipal().getName()); 8.216 - authState.setAuthScheme(mLastAuthState.getAuthScheme()); 8.217 - authState.setCredentials(mLastAuthState.getCredentials()); 8.218 - } else { 8.219 - Log.d(TAG, "LastAuthState: nothing to do"); 8.220 - } 8.221 - if (mLastAuthScope != null) { 8.222 - authState.setAuthScope(mLastAuthScope); 8.223 - Log.d(TAG, "LastAuthScope: restored"); 8.224 - } else { 8.225 - Log.d(TAG, "LastAuthScope: nothing to do"); 8.226 - } 8.227 - } else { 8.228 - //AuthState and AuthScope have to be saved separate because of the AuthScope within AuthState gets lost, so we save it in a separate var. 8.229 - mLastAuthState = authState; 8.230 - Log.d(TAG, "LastAuthState: new with user " + mLastAuthState.getCredentials().getUserPrincipal().getName()); 8.231 - if (authState.getAuthScope() != null) { 8.232 - mLastAuthScope = authState.getAuthScope(); 8.233 - Log.d(TAG, "LastAuthScope: new"); 8.234 - } 8.235 - } 8.236 - } 8.237 - }; 8.238 + this.mTrustAll = Boolean.valueOf(trustAll); 8.239 8.240 - public enum TestConnectionResult { 8.241 - WRONG_CREDENTIAL, 8.242 - WRONG_URL, 8.243 - WRONG_SERVER_STATUS, 8.244 - WRONG_ANSWER, 8.245 - SUCCESS 8.246 - } 8.247 + httpClient = getHttpClient(); 8.248 + UsernamePasswordCredentials upc = new UsernamePasswordCredentials(mUser, mPassword); 8.249 8.250 - /** 8.251 - * TODO: testConnection should return only an instance of 8.252 - * TestConnectionResult without throwing an exception or only throw checked 8.253 - * exceptions so you don't have to check the result of this function AND 8.254 - * handle the exceptions 8.255 - * @param context 8.256 - * 8.257 - * @return {@link TestConnectionResult} 8.258 - * @throws HttpHostConnectException 8.259 - * @throws IOException 8.260 - * @throws URISyntaxException 8.261 - * @throws ParserConfigurationException 8.262 - * @throws SAXException 8.263 - */ 8.264 - public TestConnectionResult testConnection() throws HttpHostConnectException, IOException, URISyntaxException, ParserConfigurationException, SAXException { 8.265 - Log.d(TAG, "start testConnection "); 8.266 - try { 8.267 - List<DavCalendar> calendars = new ArrayList<DavCalendar>(); 8.268 - calendars = forceGetCalendarsFromUri(null, url.toURI()); 8.269 - if (calendars.size() != 0) { 8.270 - return TestConnectionResult.SUCCESS; 8.271 - } 8.272 + AuthScope as = null; 8.273 + as = new AuthScope(url.getHost(), -1); 8.274 + ((AbstractHttpClient) httpClient).getCredentialsProvider().setCredentials(as, upc); 8.275 8.276 - URI userPrincipal = getUserPrincipal(); 8.277 - List<URI> calendarSets = getCalendarHomes(userPrincipal); 8.278 - for (URI calendarSet : calendarSets) { 8.279 - List<DavCalendar> calendarSetCalendars = getCalendarsFromSet(calendarSet); 8.280 - calendars.addAll(calendarSetCalendars); 8.281 - } 8.282 - if (calendarSets.size() == 0) { 8.283 - return TestConnectionResult.WRONG_ANSWER; 8.284 - } 8.285 - } catch (FileNotFoundException e) { 8.286 - return TestConnectionResult.WRONG_URL; 8.287 - } catch (SocketException e) { 8.288 - return TestConnectionResult.WRONG_URL; 8.289 - } catch (AuthenticationException e) { 8.290 - return TestConnectionResult.WRONG_CREDENTIAL; 8.291 - } catch (ClientProtocolException e) { 8.292 - return TestConnectionResult.WRONG_SERVER_STATUS; 8.293 - } catch (CaldavProtocolException e) { 8.294 - return TestConnectionResult.WRONG_ANSWER; 8.295 - } 8.296 - return TestConnectionResult.SUCCESS; 8.297 - } 8.298 + mContext = new BasicHttpContext(); 8.299 + CredentialsProvider credProvider = ((AbstractHttpClient) httpClient).getCredentialsProvider(); 8.300 + mContext.setAttribute(ClientContext.CREDS_PROVIDER, credProvider); 8.301 8.302 - /** 8.303 - * @param context May be null if no notification is needed 8.304 - * @param uri 8.305 - * @return 8.306 - * @throws AuthenticationException 8.307 - * @throws FileNotFoundException 8.308 - */ 8.309 - private List<DavCalendar> forceGetCalendarsFromUri(Context context, URI uri) throws AuthenticationException, FileNotFoundException { 8.310 - List<DavCalendar> calendars = new ArrayList<DavCalendar>(); 8.311 - Exception exception = null; 8.312 - try { 8.313 - calendars = getCalendarsFromSet(uri); 8.314 - } catch (ClientProtocolException e) { 8.315 - if (context != null) { 8.316 - NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.317 - //NotificationsHelper.getCurrentSyncLog().addException(e); 8.318 - } 8.319 - exception = e; 8.320 - } catch (FileNotFoundException e) { 8.321 - if (context != null) { 8.322 - NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.323 - //NotificationsHelper.getCurrentSyncLog().addException(e); 8.324 - } 8.325 - throw e; 8.326 - } catch (IOException e) { 8.327 - if (context != null) { 8.328 - NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.329 - //NotificationsHelper.getCurrentSyncLog().addException(e); 8.330 - } 8.331 - exception = e; 8.332 - } catch (CaldavProtocolException e) { 8.333 + //http://dlinsin.blogspot.de/2009/08/http-basic-authentication-with-android.html 8.334 + ((AbstractHttpClient) httpClient).addRequestInterceptor(preemptiveAuth, 0); 8.335 8.336 - if (context != null) { 8.337 - NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.338 - //NotificationsHelper.getCurrentSyncLog().addException(e); 8.339 - } 8.340 - exception = e; 8.341 - } 8.342 - if (exception != null && BuildConfig.DEBUG) { 8.343 - Log.e(TAG, "Force get calendars from '" + uri.toString() 8.344 - + "' failed " + exception.getClass().getCanonicalName() 8.345 - + ": " + exception.getMessage()); 8.346 - } 8.347 - return calendars; 8.348 - } 8.349 + String proto = "http"; 8.350 + int port = 80; 8.351 8.352 - private final static String PROPFIND_USER_PRINCIPAL = XML_VERSION + 8.353 - "<d:propfind xmlns:d=\"DAV:\">" + 8.354 - "<d:prop>" + 8.355 - "<d:current-user-principal />" + 8.356 - "<d:principal-URL />" + 8.357 - "</d:prop>" + 8.358 - "</d:propfind>"; 8.359 - 8.360 - private URI getUserPrincipal() throws SocketException, 8.361 - ClientProtocolException, AuthenticationException, 8.362 - FileNotFoundException, IOException, CaldavProtocolException, 8.363 - URISyntaxException { 8.364 - URI uri = this.url.toURI(); 8.365 - HttpPropFind request = createPropFindRequest(uri, 8.366 - PROPFIND_USER_PRINCIPAL, 0); 8.367 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.368 - checkStatus(response); 8.369 - ServerInfoHandler serverInfoHandler = new ServerInfoHandler(); 8.370 - parseXML(response, serverInfoHandler); 8.371 - String userPrincipal = null; 8.372 - if (serverInfoHandler.currentUserPrincipal != null) { 8.373 - userPrincipal = serverInfoHandler.currentUserPrincipal; 8.374 - } else if (serverInfoHandler.principalUrl != null) { 8.375 - userPrincipal = serverInfoHandler.principalUrl; 8.376 - } else { 8.377 - throw new CaldavProtocolException("no principal url found"); 8.378 - } 8.379 - try { 8.380 - URI userPrincipalUri = new URI(userPrincipal); 8.381 - userPrincipalUri = uri.resolve(userPrincipalUri); 8.382 - if (BuildConfig.DEBUG) { 8.383 - Log.d(TAG, 8.384 - "Found userPrincipal: " + userPrincipalUri.toString()); 8.385 - } 8.386 - return userPrincipalUri; 8.387 - } catch (URISyntaxException e) { 8.388 - throw new CaldavProtocolException("principal url '" + userPrincipal 8.389 - + "' malformed"); 8.390 - } 8.391 - } 8.392 + if (url.getProtocol().equalsIgnoreCase("https")) { 8.393 + proto = "https"; 8.394 + if (url.getPort() == -1) 8.395 + port = 443; 8.396 + else 8.397 + port = url.getPort(); 8.398 + } 8.399 8.400 - private final static String PROPFIND_CALENDAR_HOME_SET = XML_VERSION 8.401 - + "<d:propfind xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\"><d:prop><c:calendar-home-set/></d:prop></d:propfind>"; 8.402 + if (url.getProtocol().equalsIgnoreCase("http")) { 8.403 + proto = "http"; 8.404 + if (url.getPort() == -1) 8.405 + port = 80; 8.406 + else 8.407 + port = url.getPort(); 8.408 + } 8.409 + targetHost = new HttpHost(url.getHost(), port, proto); 8.410 + } 8.411 8.412 - private List<URI> getCalendarHomes(URI userPrincipal) 8.413 - throws ClientProtocolException, IOException, 8.414 - AuthenticationException, FileNotFoundException, 8.415 - CaldavProtocolException { 8.416 - HttpPropFind request = createPropFindRequest(userPrincipal, 8.417 - PROPFIND_CALENDAR_HOME_SET, 0); 8.418 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.419 - checkStatus(response); 8.420 - CalendarHomeHandler calendarHomeHandler = new CalendarHomeHandler( 8.421 - userPrincipal); 8.422 - parseXML(response, calendarHomeHandler); 8.423 - List<URI> result = calendarHomeHandler.calendarHomeSet; 8.424 - if (BuildConfig.DEBUG) { 8.425 - Log.d(TAG, result.size() + " calendar-home-set found in " 8.426 - + userPrincipal.toString()); 8.427 - } 8.428 - return result; 8.429 - } 8.430 + //http://dlinsin.blogspot.de/2009/08/http-basic-authentication-with-android.html 8.431 + HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() { 8.432 + @Override 8.433 + public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { 8.434 + AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); 8.435 8.436 - private final static String PROPFIND_CALENDER_LIST = XML_VERSION 8.437 - + "<d:propfind xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:cs=\"http://calendarserver.org/ns/\" xmlns:ic=\"http://apple.com/ns/ical/\">" 8.438 - + "<d:prop><d:displayname /><d:resourcetype />" 8.439 - // + 8.440 - // "<d:supported-method-set /><d:supported-report-set /><c:supported-calendar-component-set />" 8.441 - // + 8.442 - // "<c:calendar-description /><c:calendar-timezone /><c:calendar-free-busy-set /> 8.443 - + "<ic:calendar-color />" 8.444 - //<ic:calendar-order />" 8.445 - + "<cs:getctag /></d:prop></d:propfind>"; 8.446 + if (authState.getAuthScheme() == null) { 8.447 + if (mLastAuthState != null) { 8.448 + Log.d(TAG, "LastAuthState: restored with user " + mLastAuthState.getCredentials() 8.449 + .getUserPrincipal() 8.450 + .getName()); 8.451 + authState.setAuthScheme(mLastAuthState.getAuthScheme()); 8.452 + authState.setCredentials(mLastAuthState.getCredentials()); 8.453 + } else { 8.454 + Log.d(TAG, "LastAuthState: nothing to do"); 8.455 + } 8.456 + if (mLastAuthScope != null) { 8.457 + authState.setAuthScope(mLastAuthScope); 8.458 + Log.d(TAG, "LastAuthScope: restored"); 8.459 + } else { 8.460 + Log.d(TAG, "LastAuthScope: nothing to do"); 8.461 + } 8.462 + } else { 8.463 + //AuthState and AuthScope have to be saved separate because of the AuthScope within AuthState gets lost, so we save it in a separate var. 8.464 + mLastAuthState = authState; 8.465 + Log.d(TAG, "LastAuthState: new with user " + mLastAuthState.getCredentials() 8.466 + .getUserPrincipal() 8.467 + .getName()); 8.468 + if (authState.getAuthScope() != null) { 8.469 + mLastAuthScope = authState.getAuthScope(); 8.470 + Log.d(TAG, "LastAuthScope: new"); 8.471 + } 8.472 + } 8.473 + } 8.474 + }; 8.475 8.476 - 8.477 - private List<DavCalendar> getCalendarsFromSet(URI calendarSet) 8.478 - throws ClientProtocolException, IOException, 8.479 - CaldavProtocolException, AuthenticationException, 8.480 - FileNotFoundException { 8.481 - HttpPropFind request = createPropFindRequest(calendarSet, PROPFIND_CALENDER_LIST, 1); 8.482 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.483 - checkStatus(response); 8.484 - CalendarsHandler calendarsHandler = new CalendarsHandler(calendarSet); 8.485 - parseXML(response, calendarsHandler); 8.486 - List<DavCalendar> result = calendarsHandler.calendars; 8.487 - if (BuildConfig.DEBUG) { 8.488 - Log.i(TAG, 8.489 - result.size() + " calendars found in set " 8.490 - + calendarSet.toString()); 8.491 - } 8.492 - return result; 8.493 - } 8.494 - 8.495 - /** 8.496 - * Discover CalDAV Calendars Mentioned in 8.497 - * http://tools.ietf.org/html/draft-daboo-srv-caldav-10#section-6 and 8.498 - * http://code.google.com/p/sabredav/wiki/BuildingACalDAVClient#Discovery 8.499 - * <ol> 8.500 - * <li>PROPFIND calendar-home-set on url 8.501 - * <li>PROPFIND DAV:current-user-principal or principal-URL on url 8.502 - * <li>PROPFIND calendar-home-set on current-user-principal or principal-URL 8.503 - * <li>PROPFIND displayname, resourcetype, getctag on CalendarHomeSets 8.504 - * </ol> 8.505 - * @param context 8.506 - * 8.507 - * @return List of {@link DavCalendar} 8.508 - * @throws ClientProtocolException 8.509 - * http protocol error 8.510 - * @throws IOException 8.511 - * Connection lost 8.512 - * @throws URISyntaxException 8.513 - * url in Constructor malformed 8.514 - * @throws CaldavProtocolException 8.515 - * caldav protocol error 8.516 - */ 8.517 - //public Iterable<Calendar> getCalendarList(Context context) throws ClientProtocolException, 8.518 - public CalendarList getCalendarList(Context context) throws ClientProtocolException, 8.519 - IOException, URISyntaxException, ParserConfigurationException, 8.520 - CaldavProtocolException { 8.521 - try { 8.522 - CalendarList Result = new CalendarList(this.mAccount, this.mProvider, CalendarSource.CalDAV, this.url.toString()); 8.523 - List<DavCalendar> calendars = new ArrayList<DavCalendar>(); 8.524 - 8.525 - calendars = forceGetCalendarsFromUri(context, this.url.toURI()); 8.526 - 8.527 - if (calendars.size() == 0) { 8.528 - // no calendars found, try the home-set 8.529 - URI userPrincipal = getUserPrincipal(); 8.530 - List<URI> calendarSets = getCalendarHomes(userPrincipal); 8.531 - for (URI calendarSet : calendarSets) { 8.532 - List<DavCalendar> calendarSetCalendars = getCalendarsFromSet(calendarSet); 8.533 - calendars.addAll(calendarSetCalendars); 8.534 - } 8.535 - } 8.536 - for (DavCalendar cal : calendars) { 8.537 - Result.addCalendar(cal); 8.538 - } 8.539 - 8.540 - //return calendars; 8.541 - return Result; 8.542 - } catch (AuthenticationException e) { 8.543 - throw new IOException(e); 8.544 - } 8.545 - } 8.546 + public enum TestConnectionResult { 8.547 + WRONG_CREDENTIAL, 8.548 + WRONG_URL, 8.549 + WRONG_SERVER_STATUS, 8.550 + WRONG_ANSWER, 8.551 + SSL_ERROR, 8.552 + SUCCESS 8.553 + } 8.554 8.555 - //public Iterable<CalendarEvent> getCalendarEvents(DavCalendar calendar) 8.556 - public ArrayList<CalendarEvent> getCalendarEvents(DavCalendar calendar) 8.557 - throws URISyntaxException, ClientProtocolException, IOException, 8.558 - ParserConfigurationException, SAXException { 8.559 + /** 8.560 + * TODO: testConnection should return only an instance of 8.561 + * TestConnectionResult without throwing an exception or only throw checked 8.562 + * exceptions so you don't have to check the result of this function AND 8.563 + * handle the exceptions 8.564 + * 8.565 + * @return {@link TestConnectionResult} 8.566 + * @throws HttpHostConnectException 8.567 + * @throws IOException 8.568 + * @throws URISyntaxException 8.569 + * @throws ParserConfigurationException 8.570 + * @throws SAXException 8.571 + */ 8.572 + public TestConnectionResult testConnection() throws IOException, URISyntaxException, ParserConfigurationException, SAXException { 8.573 + Log.d(TAG, "start testConnection "); 8.574 + try { 8.575 + List<DavCalendar> calendars = new ArrayList<DavCalendar>(); 8.576 + calendars = forceGetCalendarsFromUri(null, url.toURI()); 8.577 + if (calendars.size() != 0) { 8.578 + return TestConnectionResult.SUCCESS; 8.579 + } 8.580 8.581 - ArrayList<CalendarEvent> calendarEventList = new ArrayList<CalendarEvent>(); 8.582 + URI userPrincipal = getUserPrincipal(); 8.583 + List<URI> calendarSets = getCalendarHomes(userPrincipal); 8.584 + for (URI calendarSet : calendarSets) { 8.585 + List<DavCalendar> calendarSetCalendars = getCalendarsFromSet(calendarSet); 8.586 + calendars.addAll(calendarSetCalendars); 8.587 + } 8.588 + if (calendarSets.size() == 0) { 8.589 + return TestConnectionResult.WRONG_ANSWER; 8.590 + } 8.591 + } catch (FileNotFoundException e) { 8.592 + return TestConnectionResult.WRONG_URL; 8.593 + } catch (SSLException e) { 8.594 + return TestConnectionResult.SSL_ERROR; 8.595 + } catch (SocketException e) { 8.596 + return TestConnectionResult.WRONG_URL; 8.597 + } catch (AuthenticationException e) { 8.598 + return TestConnectionResult.WRONG_CREDENTIAL; 8.599 + } catch (ClientProtocolException e) { 8.600 + return TestConnectionResult.WRONG_SERVER_STATUS; 8.601 + } catch (CaldavProtocolException e) { 8.602 + return TestConnectionResult.WRONG_ANSWER; 8.603 + } 8.604 + return TestConnectionResult.SUCCESS; 8.605 + } 8.606 8.607 - String requestBody = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 8.608 - + "<D:propfind xmlns:D=\"DAV:\">" + "<D:prop>" + "<D:getetag/>" 8.609 - + "</D:prop>" + "</D:propfind>"; 8.610 + /** 8.611 + * @param context May be null if no notification is needed 8.612 + * @param uri 8.613 + * @return 8.614 + * @throws AuthenticationException 8.615 + * @throws FileNotFoundException 8.616 + */ 8.617 + private List<DavCalendar> forceGetCalendarsFromUri(Context context, URI uri) throws AuthenticationException, FileNotFoundException { 8.618 + List<DavCalendar> calendars = new ArrayList<DavCalendar>(); 8.619 + Exception exception = null; 8.620 + try { 8.621 + calendars = getCalendarsFromSet(uri); 8.622 + } catch (ClientProtocolException e) { 8.623 + if (context != null) { 8.624 + NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.625 + //NotificationsHelper.getCurrentSyncLog().addException(e); 8.626 + } 8.627 + exception = e; 8.628 + } catch (FileNotFoundException e) { 8.629 + if (context != null) { 8.630 + NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.631 + //NotificationsHelper.getCurrentSyncLog().addException(e); 8.632 + } 8.633 + throw e; 8.634 + } catch (IOException e) { 8.635 + if (context != null) { 8.636 + NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.637 + //NotificationsHelper.getCurrentSyncLog().addException(e); 8.638 + } 8.639 + exception = e; 8.640 + } catch (CaldavProtocolException e) { 8.641 8.642 - HttpPropFind request = null; 8.643 - 8.644 - String EventUri; 8.645 + if (context != null) { 8.646 + NotificationsHelper.signalSyncErrors(context, "Caldav sync problem", e.getMessage()); 8.647 + //NotificationsHelper.getCurrentSyncLog().addException(e); 8.648 + } 8.649 + exception = e; 8.650 + } 8.651 + if (exception != null && BuildConfig.DEBUG) { 8.652 + Log.e(TAG, "Force get calendars from '" + uri.toString() 8.653 + + "' failed " + exception.getClass().getCanonicalName() 8.654 + + ": " + exception.getMessage()); 8.655 + } 8.656 + return calendars; 8.657 + } 8.658 + 8.659 + private final static String PROPFIND_USER_PRINCIPAL = XML_VERSION + 8.660 + "<d:propfind xmlns:d=\"DAV:\">" + 8.661 + "<d:prop>" + 8.662 + "<d:current-user-principal />" + 8.663 + "<d:principal-URL />" + 8.664 + "</d:prop>" + 8.665 + "</d:propfind>"; 8.666 + 8.667 + private URI getUserPrincipal() throws 8.668 + AuthenticationException, 8.669 + IOException, CaldavProtocolException, 8.670 + URISyntaxException { 8.671 + URI uri = this.url.toURI(); 8.672 + HttpPropFind request = createPropFindRequest(uri, 8.673 + PROPFIND_USER_PRINCIPAL, 0); 8.674 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.675 + checkStatus(response); 8.676 + ServerInfoHandler serverInfoHandler = new ServerInfoHandler(); 8.677 + parseXML(response, serverInfoHandler); 8.678 + String userPrincipal = null; 8.679 + if (serverInfoHandler.currentUserPrincipal != null) { 8.680 + userPrincipal = serverInfoHandler.currentUserPrincipal; 8.681 + } else if (serverInfoHandler.principalUrl != null) { 8.682 + userPrincipal = serverInfoHandler.principalUrl; 8.683 + } else { 8.684 + throw new CaldavProtocolException("no principal url found"); 8.685 + } 8.686 + try { 8.687 + URI userPrincipalUri = new URI(userPrincipal); 8.688 + userPrincipalUri = uri.resolve(userPrincipalUri); 8.689 + if (BuildConfig.DEBUG) { 8.690 + Log.d(TAG, 8.691 + "Found userPrincipal: " + userPrincipalUri.toString()); 8.692 + } 8.693 + return userPrincipalUri; 8.694 + } catch (URISyntaxException e) { 8.695 + throw new CaldavProtocolException("principal url '" + userPrincipal 8.696 + + "' malformed"); 8.697 + } 8.698 + } 8.699 + 8.700 + private final static String PROPFIND_CALENDAR_HOME_SET = XML_VERSION 8.701 + + "<d:propfind xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\"><d:prop><c:calendar-home-set/></d:prop></d:propfind>"; 8.702 + 8.703 + private List<URI> getCalendarHomes(URI userPrincipal) 8.704 + throws ClientProtocolException, IOException, 8.705 + AuthenticationException, FileNotFoundException, 8.706 + CaldavProtocolException { 8.707 + HttpPropFind request = createPropFindRequest(userPrincipal, 8.708 + PROPFIND_CALENDAR_HOME_SET, 0); 8.709 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.710 + checkStatus(response); 8.711 + CalendarHomeHandler calendarHomeHandler = new CalendarHomeHandler( 8.712 + userPrincipal); 8.713 + parseXML(response, calendarHomeHandler); 8.714 + List<URI> result = calendarHomeHandler.calendarHomeSet; 8.715 + if (BuildConfig.DEBUG) { 8.716 + Log.d(TAG, result.size() + " calendar-home-set found in " 8.717 + + userPrincipal.toString()); 8.718 + } 8.719 + return result; 8.720 + } 8.721 + 8.722 + private final static String PROPFIND_CALENDER_LIST = XML_VERSION 8.723 + + "<d:propfind xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:cs=\"http://calendarserver.org/ns/\" xmlns:ic=\"http://apple.com/ns/ical/\">" 8.724 + + "<d:prop><d:displayname /><d:resourcetype />" 8.725 + // + 8.726 + // "<d:supported-method-set /><d:supported-report-set /><c:supported-calendar-component-set />" 8.727 + // + 8.728 + // "<c:calendar-description /><c:calendar-timezone /><c:calendar-free-busy-set /> 8.729 + + "<ic:calendar-color />" 8.730 + //<ic:calendar-order />" 8.731 + + "<cs:getctag /></d:prop></d:propfind>"; 8.732 + 8.733 + 8.734 + private List<DavCalendar> getCalendarsFromSet(URI calendarSet) 8.735 + throws ClientProtocolException, IOException, 8.736 + CaldavProtocolException, AuthenticationException, 8.737 + FileNotFoundException { 8.738 + HttpPropFind request = createPropFindRequest(calendarSet, PROPFIND_CALENDER_LIST, 1); 8.739 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.740 + checkStatus(response); 8.741 + CalendarsHandler calendarsHandler = new CalendarsHandler(calendarSet); 8.742 + parseXML(response, calendarsHandler); 8.743 + List<DavCalendar> result = calendarsHandler.calendars; 8.744 + if (BuildConfig.DEBUG) { 8.745 + Log.i(TAG, 8.746 + result.size() + " calendars found in set " 8.747 + + calendarSet.toString() 8.748 + ); 8.749 + } 8.750 + return result; 8.751 + } 8.752 + 8.753 + /** 8.754 + * Discover CalDAV Calendars Mentioned in 8.755 + * http://tools.ietf.org/html/draft-daboo-srv-caldav-10#section-6 and 8.756 + * http://code.google.com/p/sabredav/wiki/BuildingACalDAVClient#Discovery 8.757 + * <ol> 8.758 + * <li>PROPFIND calendar-home-set on url 8.759 + * <li>PROPFIND DAV:current-user-principal or principal-URL on url 8.760 + * <li>PROPFIND calendar-home-set on current-user-principal or principal-URL 8.761 + * <li>PROPFIND displayname, resourcetype, getctag on CalendarHomeSets 8.762 + * </ol> 8.763 + * 8.764 + * @param context 8.765 + * @return List of {@link DavCalendar} 8.766 + * @throws ClientProtocolException http protocol error 8.767 + * @throws IOException Connection lost 8.768 + * @throws URISyntaxException url in Constructor malformed 8.769 + * @throws CaldavProtocolException caldav protocol error 8.770 + */ 8.771 + //public Iterable<Calendar> getCalendarList(Context context) throws ClientProtocolException, 8.772 + public CalendarList getCalendarList(Context context) throws ClientProtocolException, 8.773 + IOException, URISyntaxException, ParserConfigurationException, 8.774 + CaldavProtocolException { 8.775 + try { 8.776 + CalendarList Result = new CalendarList(this.mAccount, this.mProvider, CalendarSource.CalDAV, this.url 8.777 + .toString()); 8.778 + List<DavCalendar> calendars = new ArrayList<DavCalendar>(); 8.779 + 8.780 + calendars = forceGetCalendarsFromUri(context, this.url.toURI()); 8.781 + 8.782 + if (calendars.size() == 0) { 8.783 + // no calendars found, try the home-set 8.784 + URI userPrincipal = getUserPrincipal(); 8.785 + List<URI> calendarSets = getCalendarHomes(userPrincipal); 8.786 + for (URI calendarSet : calendarSets) { 8.787 + List<DavCalendar> calendarSetCalendars = getCalendarsFromSet(calendarSet); 8.788 + calendars.addAll(calendarSetCalendars); 8.789 + } 8.790 + } 8.791 + for (DavCalendar cal : calendars) { 8.792 + Result.addCalendar(cal); 8.793 + } 8.794 + 8.795 + //return calendars; 8.796 + return Result; 8.797 + } catch (AuthenticationException e) { 8.798 + throw new IOException(e); 8.799 + } 8.800 + } 8.801 + 8.802 + //public Iterable<CalendarEvent> getCalendarEvents(DavCalendar calendar) 8.803 + public ArrayList<CalendarEvent> getCalendarEvents(DavCalendar calendar) 8.804 + throws URISyntaxException, ClientProtocolException, IOException, 8.805 + ParserConfigurationException, SAXException { 8.806 + 8.807 + ArrayList<CalendarEvent> calendarEventList = new ArrayList<CalendarEvent>(); 8.808 + 8.809 + String requestBody = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 8.810 + + "<D:propfind xmlns:D=\"DAV:\">" + "<D:prop>" + "<D:getetag/>" 8.811 + + "</D:prop>" + "</D:propfind>"; 8.812 + 8.813 + HttpPropFind request = null; 8.814 + 8.815 + String EventUri; 8.816 8.817 /*request = new HttpPropFind(); 8.818 - request.setURI(calendar.getURI()); 8.819 + request.setURI(calendar.getURI()); 8.820 request.setHeader("Host", targetHost.getHostName()); 8.821 request.setHeader("Depth", "1"); 8.822 request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.823 @@ -487,380 +494,358 @@ 8.824 } catch (UnsupportedEncodingException e) { 8.825 throw new AssertionError("UTF-8 is unknown"); 8.826 }*/ 8.827 - request = this.createPropFindRequest(calendar.getURI(), requestBody, 1); 8.828 - 8.829 - Log.d(TAG, "Getting eTag by PROPFIND at " + request.getURI()); 8.830 + request = this.createPropFindRequest(calendar.getURI(), requestBody, 1); 8.831 8.832 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.833 + Log.d(TAG, "Getting eTag by PROPFIND at " + request.getURI()); 8.834 8.835 - BufferedReader reader = new BufferedReader(new InputStreamReader( 8.836 - response.getEntity().getContent(), "UTF-8")); 8.837 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.838 + String body = EntityUtils.toString(response.getEntity(), "UTF-8"); 8.839 8.840 - String line; 8.841 - String body = ""; 8.842 - do { 8.843 - line = reader.readLine(); 8.844 - if (line != null) 8.845 - body += line; 8.846 - } while (line != null); 8.847 + Log.d(TAG, "HttpResponse status=" + response.getStatusLine() 8.848 + + " body= " + body); 8.849 8.850 - Log.d(TAG, "HttpResponse status=" + response.getStatusLine() 8.851 - + " body= " + body); 8.852 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 8.853 + factory.setNamespaceAware(true); 8.854 + DocumentBuilder builder = factory.newDocumentBuilder(); 8.855 + Document dom = builder.parse(new InputSource(new ByteArrayInputStream( 8.856 + body.getBytes("utf-8")))); 8.857 + Element root = dom.getDocumentElement(); 8.858 + NodeList items = root.getElementsByTagNameNS("*", "getetag"); 8.859 8.860 - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 8.861 - factory.setNamespaceAware(true); 8.862 - DocumentBuilder builder = factory.newDocumentBuilder(); 8.863 - Document dom = builder.parse(new InputSource(new ByteArrayInputStream( 8.864 - body.getBytes("utf-8")))); 8.865 - Element root = dom.getDocumentElement(); 8.866 - NodeList items = root.getElementsByTagNameNS("*", "getetag"); 8.867 + for (int i = 0; i < items.getLength(); i++) { 8.868 + CalendarEvent calendarEvent = new CalendarEvent(this.mAccount, this.mProvider); 8.869 8.870 - for (int i = 0; i < items.getLength(); i++) { 8.871 - CalendarEvent calendarEvent = new CalendarEvent(this.mAccount, this.mProvider); 8.872 + Node node = items.item(i); 8.873 8.874 - Node node = items.item(i); 8.875 + if (node.getTextContent().trim().length() == 0) 8.876 + continue; // not an event 8.877 8.878 - if (node.getTextContent().trim().length() == 0) 8.879 - continue; // not an event 8.880 + calendarEvent.setETag(node.getTextContent().trim()); 8.881 + //calendarEvent.calendarURL = this.url; 8.882 + calendarEvent.calendarURL = calendar.getURI().toURL(); 8.883 8.884 - calendarEvent.setETag(node.getTextContent().trim()); 8.885 - //calendarEvent.calendarURL = this.url; 8.886 - calendarEvent.calendarURL = calendar.getURI().toURL(); 8.887 + node = node.getParentNode(); // prop 8.888 + node = node.getParentNode(); // propstat 8.889 + node = node.getParentNode(); // response 8.890 8.891 - node = node.getParentNode(); // prop 8.892 - node = node.getParentNode(); // propstat 8.893 - node = node.getParentNode(); // response 8.894 + NodeList children = node.getChildNodes(); 8.895 + for (int j = 0; j < children.getLength(); j++) { 8.896 + Node childNode = children.item(j); 8.897 + if ((childNode.getLocalName() != null) && (childNode.getLocalName() 8.898 + .equalsIgnoreCase("href"))) { 8.899 + EventUri = childNode.getTextContent().trim(); 8.900 + //HINT: bugfix for zimbra calendar: replace("@", "%40") 8.901 + EventUri = EventUri.replace("@", "%40"); 8.902 + calendarEvent.setUri(new URI(EventUri)); 8.903 + } 8.904 + } 8.905 8.906 - NodeList children = node.getChildNodes(); 8.907 - for (int j = 0; j < children.getLength(); j++) { 8.908 - Node childNode = children.item(j); 8.909 - if ((childNode.getLocalName()!=null) && (childNode.getLocalName().equalsIgnoreCase("href"))) { 8.910 - EventUri = childNode.getTextContent().trim(); 8.911 - //HINT: bugfix for zimbra calendar: replace("@", "%40") 8.912 - EventUri = EventUri.replace("@", "%40"); 8.913 - calendarEvent.setUri(new URI(EventUri)); 8.914 - } 8.915 - } 8.916 + calendarEventList.add(calendarEvent); 8.917 8.918 - calendarEventList.add(calendarEvent); 8.919 + } 8.920 8.921 - } 8.922 + return calendarEventList; 8.923 + } 8.924 8.925 - return calendarEventList; 8.926 - } 8.927 - 8.928 - private void parseXML(HttpResponse response, ContentHandler contentHandler) 8.929 - throws IOException, CaldavProtocolException { 8.930 - InputStream is = response.getEntity().getContent(); 8.931 - /*BufferedReader bReader = new BufferedReader(new InputStreamReader(is, "UTF-8")); 8.932 - String Content = ""; 8.933 + private void parseXML(HttpResponse response, ContentHandler contentHandler) 8.934 + throws IOException, CaldavProtocolException { 8.935 + InputStream is = response.getEntity().getContent(); 8.936 + /*BufferedReader bReader = new BufferedReader(new InputStreamReader(is, "UTF-8")); 8.937 + String Content = ""; 8.938 String Line = bReader.readLine(); 8.939 8.940 while (Line != null) { 8.941 Content += Line; 8.942 Line = bReader.readLine(); 8.943 }*/ 8.944 - 8.945 - SAXParserFactory factory = SAXParserFactory.newInstance(); 8.946 - try { 8.947 - SAXParser parser = factory.newSAXParser(); 8.948 - XMLReader reader = parser.getXMLReader(); 8.949 - reader.setContentHandler(contentHandler); 8.950 - reader.parse(new InputSource(is)); 8.951 - } catch (ParserConfigurationException e) { 8.952 - throw new AssertionError("ParserConfigurationException " 8.953 - + e.getMessage()); 8.954 - } catch (IllegalStateException e) { 8.955 - throw new CaldavProtocolException(e.getMessage()); 8.956 - } catch (SAXException e) { 8.957 - throw new CaldavProtocolException(e.getMessage()); 8.958 - } 8.959 - } 8.960 8.961 - private void checkStatus(HttpResponse response) 8.962 - throws AuthenticationException, FileNotFoundException, 8.963 - ClientProtocolException { 8.964 - final int statusCode = response.getStatusLine().getStatusCode(); 8.965 - lastStatusCode = statusCode; 8.966 - if (response.containsHeader("ETag")) 8.967 - lastETag = response.getFirstHeader("ETag").getValue(); 8.968 - else 8.969 - lastETag = ""; 8.970 - if (response.containsHeader("DAV")) 8.971 - lastDav = response.getFirstHeader("DAV").getValue(); 8.972 - else 8.973 - lastDav = ""; 8.974 - 8.975 - switch (statusCode) { 8.976 - case 401: 8.977 - throw new AuthenticationException(); 8.978 - case 404: 8.979 - throw new FileNotFoundException(); 8.980 - case 409: //Conflict 8.981 - case 412: 8.982 - case 200: 8.983 - case 201: 8.984 - case 204: 8.985 - case 207: 8.986 - return; 8.987 - default: 8.988 - throw new ClientProtocolException("StatusCode: " + statusCode); 8.989 - } 8.990 - } 8.991 + SAXParserFactory factory = SAXParserFactory.newInstance(); 8.992 + try { 8.993 + SAXParser parser = factory.newSAXParser(); 8.994 + XMLReader reader = parser.getXMLReader(); 8.995 + reader.setContentHandler(contentHandler); 8.996 + reader.parse(new InputSource(is)); 8.997 + } catch (ParserConfigurationException e) { 8.998 + throw new AssertionError("ParserConfigurationException " 8.999 + + e.getMessage()); 8.1000 + } catch (IllegalStateException e) { 8.1001 + throw new CaldavProtocolException(e.getMessage()); 8.1002 + } catch (SAXException e) { 8.1003 + throw new CaldavProtocolException(e.getMessage()); 8.1004 + } 8.1005 + } 8.1006 8.1007 - private HttpPropFind createPropFindRequest(URI uri, String data, int depth) { 8.1008 - HttpPropFind request = new HttpPropFind(); 8.1009 + private void checkStatus(HttpResponse response) 8.1010 + throws AuthenticationException, FileNotFoundException, 8.1011 + ClientProtocolException { 8.1012 + final int statusCode = response.getStatusLine().getStatusCode(); 8.1013 + lastStatusCode = statusCode; 8.1014 + if (response.containsHeader("ETag")) 8.1015 + lastETag = response.getFirstHeader("ETag").getValue(); 8.1016 + else 8.1017 + lastETag = ""; 8.1018 + if (response.containsHeader("DAV")) 8.1019 + lastDav = response.getFirstHeader("DAV").getValue(); 8.1020 + else 8.1021 + lastDav = ""; 8.1022 8.1023 - request.setURI(uri); 8.1024 - //request.setHeader("Host", targetHost.getHostName()); 8.1025 - request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1026 - request.setHeader("Depth", Integer.toString(depth)); 8.1027 - request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1028 - try { 8.1029 - request.setEntity(new StringEntity(data, "UTF-8")); 8.1030 - } catch (UnsupportedEncodingException e) { 8.1031 - throw new AssertionError("UTF-8 is unknown"); 8.1032 - } 8.1033 - return request; 8.1034 - } 8.1035 - 8.1036 - private HttpDelete createDeleteRequest(URI uri) { 8.1037 - HttpDelete request = new HttpDelete(); 8.1038 - request.setURI(uri); 8.1039 - //request.setHeader("Host", targetHost.getHostName()); 8.1040 - request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1041 - request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1042 - return request; 8.1043 - } 8.1044 + switch (statusCode) { 8.1045 + case 401: 8.1046 + throw new AuthenticationException(); 8.1047 + case 404: 8.1048 + throw new FileNotFoundException(); 8.1049 + case 409: //Conflict 8.1050 + case 412: 8.1051 + case 200: 8.1052 + case 201: 8.1053 + case 204: 8.1054 + case 207: 8.1055 + return; 8.1056 + default: 8.1057 + throw new ClientProtocolException("StatusCode: " + statusCode); 8.1058 + } 8.1059 + } 8.1060 8.1061 - private HttpPut createPutRequest(URI uri, String data, int depth) { 8.1062 - HttpPut request = new HttpPut(); 8.1063 - request.setURI(uri); 8.1064 - //request.setHeader("Host", targetHost.getHostName()); 8.1065 - request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1066 - //request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1067 - request.setHeader("Content-Type", "text/calendar; charset=UTF-8"); 8.1068 - try { 8.1069 - request.setEntity(new StringEntity(data, "UTF-8")); 8.1070 - //request.setEntity(new StringEntity(data)); 8.1071 - } catch (UnsupportedEncodingException e) { 8.1072 - throw new AssertionError("UTF-8 is unknown"); 8.1073 - } 8.1074 - return request; 8.1075 - } 8.1076 - 8.1077 - private static HttpReport createReportRequest(URI uri, String data, int depth) { 8.1078 - HttpReport request = new HttpReport(); 8.1079 - request.setURI(uri); 8.1080 - //request.setHeader("Host", targetHost.getHostName()); 8.1081 - request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1082 - request.setHeader("Depth", Integer.toString(depth)); 8.1083 - request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1084 - //request.setHeader("Content-Type", "text/xml;charset=\"UTF-8\""); 8.1085 - try { 8.1086 - request.setEntity(new StringEntity(data)); 8.1087 - } catch (UnsupportedEncodingException e) { 8.1088 - throw new AssertionError("UTF-8 is unknown"); 8.1089 - } 8.1090 - return request; 8.1091 - } 8.1092 - 8.1093 - public static void fetchEvent_old(CalendarEvent calendarEvent) 8.1094 - throws ClientProtocolException, IOException { 8.1095 - HttpGet request = null; 8.1096 + private HttpPropFind createPropFindRequest(URI uri, String data, int depth) { 8.1097 + HttpPropFind request = new HttpPropFind(); 8.1098 8.1099 - request = new HttpGet(); 8.1100 - request.setURI(calendarEvent.getUri()); 8.1101 - request.setHeader("Host", targetHost.getHostName()); 8.1102 - request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1103 + request.setURI(uri); 8.1104 + //request.setHeader("Host", targetHost.getHostName()); 8.1105 + request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1106 + request.setHeader("Depth", Integer.toString(depth)); 8.1107 + request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1108 + try { 8.1109 + request.setEntity(new StringEntity(data, "UTF-8")); 8.1110 + } catch (UnsupportedEncodingException e) { 8.1111 + throw new AssertionError("UTF-8 is unknown"); 8.1112 + } 8.1113 + return request; 8.1114 + } 8.1115 8.1116 - HttpResponse response = httpClient.execute(targetHost, request); 8.1117 + private HttpDelete createDeleteRequest(URI uri) { 8.1118 + HttpDelete request = new HttpDelete(); 8.1119 + request.setURI(uri); 8.1120 + //request.setHeader("Host", targetHost.getHostName()); 8.1121 + request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1122 + request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1123 + return request; 8.1124 + } 8.1125 8.1126 - BufferedReader reader = new BufferedReader(new InputStreamReader( 8.1127 - response.getEntity().getContent(), "UTF-8")); 8.1128 + private HttpPut createPutRequest(URI uri, String data, int depth) { 8.1129 + HttpPut request = new HttpPut(); 8.1130 + request.setURI(uri); 8.1131 + //request.setHeader("Host", targetHost.getHostName()); 8.1132 + request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1133 + //request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1134 + request.setHeader("Content-Type", "text/calendar; charset=UTF-8"); 8.1135 + try { 8.1136 + request.setEntity(new StringEntity(data, "UTF-8")); 8.1137 + //request.setEntity(new StringEntity(data)); 8.1138 + } catch (UnsupportedEncodingException e) { 8.1139 + throw new AssertionError("UTF-8 is unknown"); 8.1140 + } 8.1141 + return request; 8.1142 + } 8.1143 8.1144 - String line; 8.1145 - String body = ""; 8.1146 - do { 8.1147 - line = reader.readLine(); 8.1148 - if (line != null) 8.1149 - body += line + "\n"; 8.1150 - } while (line != null); 8.1151 + private static HttpReport createReportRequest(URI uri, String data, int depth) { 8.1152 + HttpReport request = new HttpReport(); 8.1153 + request.setURI(uri); 8.1154 + //request.setHeader("Host", targetHost.getHostName()); 8.1155 + request.setHeader("Host", targetHost.getHostName() + ":" + String.valueOf(targetHost.getPort())); 8.1156 + request.setHeader("Depth", Integer.toString(depth)); 8.1157 + request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1158 + //request.setHeader("Content-Type", "text/xml;charset=\"UTF-8\""); 8.1159 + try { 8.1160 + request.setEntity(new StringEntity(data)); 8.1161 + } catch (UnsupportedEncodingException e) { 8.1162 + throw new AssertionError("UTF-8 is unknown"); 8.1163 + } 8.1164 + return request; 8.1165 + } 8.1166 8.1167 - calendarEvent.setICSasString(body); 8.1168 + public static void fetchEvent_old(CalendarEvent calendarEvent) 8.1169 + throws ClientProtocolException, IOException { 8.1170 + HttpGet request = null; 8.1171 8.1172 - Log.d(TAG, "HttpResponse GET event status=" + response.getStatusLine() 8.1173 - + " body= " + body); 8.1174 - } 8.1175 - 8.1176 - public static boolean getEvent(CalendarEvent calendarEvent) throws ClientProtocolException, IOException { 8.1177 - boolean Result = false; 8.1178 - HttpReport request = null; 8.1179 + request = new HttpGet(); 8.1180 + request.setURI(calendarEvent.getUri()); 8.1181 + request.setHeader("Host", targetHost.getHostName()); 8.1182 + request.setHeader("Content-Type", "application/xml;charset=\"UTF-8\""); 8.1183 8.1184 - //HINT: bugfix for google calendar: replace("@", "%40") 8.1185 - String data = XML_VERSION + 8.1186 - "<C:calendar-multiget xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" + 8.1187 - "<D:prop>" + 8.1188 - "<D:getetag />" + 8.1189 - "<C:calendar-data />" + 8.1190 - "</D:prop>" + 8.1191 - "<D:href>" + calendarEvent.getUri().getRawPath().replace("@", "%40") + "</D:href>" + 8.1192 - "</C:calendar-multiget>"; 8.1193 + HttpResponse response = httpClient.execute(targetHost, request); 8.1194 + String body = EntityUtils.toString(response.getEntity(), "UTF-8"); 8.1195 8.1196 - URI calendarURI = null; 8.1197 - try { 8.1198 - calendarURI = calendarEvent.calendarURL.toURI(); 8.1199 - } catch (URISyntaxException e) { 8.1200 - e.printStackTrace(); 8.1201 - } 8.1202 - //request = createReportRequest(calendarEvent.getUri(), data, 1); 8.1203 - request = createReportRequest(calendarURI, data, 1); 8.1204 + calendarEvent.setICSasString(body); 8.1205 8.1206 - HttpResponse response = httpClient.execute(targetHost, request); 8.1207 + Log.d(TAG, "HttpResponse GET event status=" + response.getStatusLine() 8.1208 + + " body= " + body); 8.1209 + } 8.1210 8.1211 - BufferedReader reader = new BufferedReader(new InputStreamReader( 8.1212 - response.getEntity().getContent(), "UTF-8")); 8.1213 + public static boolean getEvent(CalendarEvent calendarEvent) throws ClientProtocolException, IOException { 8.1214 + boolean Result = false; 8.1215 + HttpReport request = null; 8.1216 8.1217 - String line; 8.1218 - String body = ""; 8.1219 - do { 8.1220 - line = reader.readLine(); 8.1221 - if (line != null) 8.1222 - body += line + "\n"; 8.1223 - } while (line != null); 8.1224 + //HINT: bugfix for google calendar: replace("@", "%40") 8.1225 + String data = XML_VERSION + 8.1226 + "<C:calendar-multiget xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" + 8.1227 + "<D:prop>" + 8.1228 + "<D:getetag />" + 8.1229 + "<C:calendar-data />" + 8.1230 + "</D:prop>" + 8.1231 + "<D:href>" + calendarEvent.getUri().getRawPath().replace("@", "%40") + "</D:href>" + 8.1232 + "</C:calendar-multiget>"; 8.1233 8.1234 - if (calendarEvent.setICSasMultiStatus(body)) 8.1235 - Result = true; 8.1236 + URI calendarURI = null; 8.1237 + try { 8.1238 + calendarURI = calendarEvent.calendarURL.toURI(); 8.1239 + } catch (URISyntaxException e) { 8.1240 + e.printStackTrace(); 8.1241 + } 8.1242 + //request = createReportRequest(calendarEvent.getUri(), data, 1); 8.1243 + request = createReportRequest(calendarURI, data, 1); 8.1244 8.1245 - return Result; 8.1246 - } 8.1247 - 8.1248 - 8.1249 - /** 8.1250 - * sends a update event request to the server 8.1251 - * @param uri the full URI of the event on server side. example: http://caldav.example.com/principal/user/calendar/e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter.ics 8.1252 - * @param data the full ical-data for the event 8.1253 - * @param ETag the ETAG of this event is send within the "If-Match" Parameter to tell the server only to update this version 8.1254 - * @return 8.1255 - */ 8.1256 - public boolean updateEvent(URI uri, String data, String ETag) { 8.1257 - boolean Result = false; 8.1258 - 8.1259 - try { 8.1260 - HttpPut request = createPutRequest(uri, data, 1); 8.1261 - request.addHeader(mstrcHeaderIfMatch, ETag); 8.1262 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.1263 - checkStatus(response); 8.1264 - if ((lastStatusCode == 200) || (lastStatusCode == 201) || (lastStatusCode == 204)) { 8.1265 - Result = true; 8.1266 - } else if (lastStatusCode == 412) { 8.1267 - //Precondition failed 8.1268 - Result = false; 8.1269 - } else if (lastStatusCode == 409) { 8.1270 - //Conflict 8.1271 - Result = false; 8.1272 - } else { 8.1273 - Log.w(TAG, "Unkown StatusCode during creation of an event"); 8.1274 - } 8.1275 - } catch (ClientProtocolException e) { 8.1276 - e.printStackTrace(); 8.1277 - } catch (IOException e) { 8.1278 - e.printStackTrace(); 8.1279 - } catch (AuthenticationException e) { 8.1280 - e.printStackTrace(); 8.1281 - } 8.1282 - return Result; 8.1283 - } 8.1284 - 8.1285 - /** 8.1286 - * sends a create event request to server 8.1287 - * @param uri the full URI of the new event on server side. example: http://caldav.example.com/principal/user/calendar/e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter.ics 8.1288 - * @param data the full ical-data for the new event 8.1289 - * @return success of this function 8.1290 - */ 8.1291 - public boolean createEvent(URI uri, String data) { 8.1292 - boolean Result = false; 8.1293 - 8.1294 - try { 8.1295 - HttpPut request = createPutRequest(uri, data, 1); 8.1296 - request.addHeader(mstrcHeaderIfNoneMatch, "*"); 8.1297 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.1298 - checkStatus(response); 8.1299 - if (lastStatusCode == 201) { 8.1300 - Result = true; 8.1301 - } else { 8.1302 - Log.w(TAG, "Unkown StatusCode during creation of an event"); 8.1303 - } 8.1304 - } catch (ClientProtocolException e) { 8.1305 - e.printStackTrace(); 8.1306 - } catch (IOException e) { 8.1307 - e.printStackTrace(); 8.1308 - } catch (AuthenticationException e) { 8.1309 - e.printStackTrace(); 8.1310 - } 8.1311 - return Result; 8.1312 - } 8.1313 - 8.1314 - /** 8.1315 - * sends a delete event request to the server 8.1316 - * @param calendarEventUri the full URI of the event on server side. example: http://caldav.example.com/principal/user/calendar/e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter.ics 8.1317 - * @param ETag the ETAG of this event is send within the "If-Match" Parameter to tell the server only to delete this version 8.1318 - * @return success of this function 8.1319 - */ 8.1320 - public boolean deleteEvent(URI calendarEventUri, String ETag) { 8.1321 - boolean Result = false; 8.1322 - 8.1323 - try { 8.1324 - HttpDelete request = createDeleteRequest(calendarEventUri); 8.1325 - request.addHeader(mstrcHeaderIfMatch, ETag); 8.1326 - HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.1327 - checkStatus(response); 8.1328 - if ((lastStatusCode == 204) || (lastStatusCode == 200)) { 8.1329 - Result = true; 8.1330 - } else { 8.1331 - Log.w(TAG, "Unkown StatusCode during deletion of an event"); 8.1332 - } 8.1333 - } catch (ClientProtocolException e) { 8.1334 - e.printStackTrace(); 8.1335 - } catch (IOException e) { 8.1336 - if (lastStatusCode == 404) { 8.1337 - //the event has already been deleted on server side. no action needed 8.1338 - Result = true; 8.1339 - } else { 8.1340 - e.printStackTrace(); 8.1341 - } 8.1342 - } catch (AuthenticationException e) { 8.1343 - e.printStackTrace(); 8.1344 - } 8.1345 - 8.1346 - return Result; 8.1347 - } 8.1348 - 8.1349 - /** 8.1350 - * returns the ETAG send by the last server response. 8.1351 - * @return the ETAG 8.1352 - */ 8.1353 - public String getLastETag() { 8.1354 - return lastETag; 8.1355 - } 8.1356 - 8.1357 - /** 8.1358 - * returns the DAV-Options send by the last server response. 8.1359 - * @return the DAV-Options 8.1360 - */ 8.1361 - public String getLastDav() { 8.1362 - return lastDav; 8.1363 - } 8.1364 - 8.1365 - public void setVersion(String version) { 8.1366 - VERSION = version; 8.1367 - ((AbstractHttpClient) httpClient).getParams().setParameter(CoreProtocolPNames.USER_AGENT, this.USER_AGENT + " Version:" + VERSION); 8.1368 - } 8.1369 - 8.1370 - public void setAccount(Account account) { 8.1371 - this.mAccount = account; 8.1372 - } 8.1373 - public void setProvider(ContentProviderClient provider) { 8.1374 - this.mProvider = provider; 8.1375 - } 8.1376 -} 8.1377 \ No newline at end of file 8.1378 + HttpResponse response = httpClient.execute(targetHost, request); 8.1379 + String body = EntityUtils.toString(response.getEntity(), "UTF-8"); 8.1380 + 8.1381 + if (calendarEvent.setICSasMultiStatus(body)) 8.1382 + Result = true; 8.1383 + 8.1384 + return Result; 8.1385 + } 8.1386 + 8.1387 + 8.1388 + /** 8.1389 + * sends a update event request to the server 8.1390 + * 8.1391 + * @param uri the full URI of the event on server side. example: http://caldav.example.com/principal/user/calendar/e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter.ics 8.1392 + * @param data the full ical-data for the event 8.1393 + * @param ETag the ETAG of this event is send within the "If-Match" Parameter to tell the server only to update this version 8.1394 + * @return 8.1395 + */ 8.1396 + public boolean updateEvent(URI uri, String data, String ETag) { 8.1397 + boolean Result = false; 8.1398 + 8.1399 + try { 8.1400 + HttpPut request = createPutRequest(uri, data, 1); 8.1401 + request.addHeader(mstrcHeaderIfMatch, ETag); 8.1402 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.1403 + checkStatus(response); 8.1404 + if ((lastStatusCode == 200) || (lastStatusCode == 201) || (lastStatusCode == 204)) { 8.1405 + Result = true; 8.1406 + } else if (lastStatusCode == 412) { 8.1407 + //Precondition failed 8.1408 + Result = false; 8.1409 + } else if (lastStatusCode == 409) { 8.1410 + //Conflict 8.1411 + Result = false; 8.1412 + } else { 8.1413 + Log.w(TAG, "Unkown StatusCode during creation of an event"); 8.1414 + } 8.1415 + } catch (ClientProtocolException e) { 8.1416 + e.printStackTrace(); 8.1417 + } catch (IOException e) { 8.1418 + e.printStackTrace(); 8.1419 + } catch (AuthenticationException e) { 8.1420 + e.printStackTrace(); 8.1421 + } 8.1422 + return Result; 8.1423 + } 8.1424 + 8.1425 + /** 8.1426 + * sends a create event request to server 8.1427 + * 8.1428 + * @param uri the full URI of the new event on server side. example: http://caldav.example.com/principal/user/calendar/e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter.ics 8.1429 + * @param data the full ical-data for the new event 8.1430 + * @return success of this function 8.1431 + */ 8.1432 + public boolean createEvent(URI uri, String data) { 8.1433 + boolean Result = false; 8.1434 + 8.1435 + try { 8.1436 + HttpPut request = createPutRequest(uri, data, 1); 8.1437 + request.addHeader(mstrcHeaderIfNoneMatch, "*"); 8.1438 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.1439 + checkStatus(response); 8.1440 + if (lastStatusCode == 201) { 8.1441 + Result = true; 8.1442 + } else { 8.1443 + Log.w(TAG, "Unkown StatusCode during creation of an event"); 8.1444 + } 8.1445 + } catch (ClientProtocolException e) { 8.1446 + e.printStackTrace(); 8.1447 + } catch (IOException e) { 8.1448 + e.printStackTrace(); 8.1449 + } catch (AuthenticationException e) { 8.1450 + e.printStackTrace(); 8.1451 + } 8.1452 + return Result; 8.1453 + } 8.1454 + 8.1455 + /** 8.1456 + * sends a delete event request to the server 8.1457 + * 8.1458 + * @param calendarEventUri the full URI of the event on server side. example: http://caldav.example.com/principal/user/calendar/e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter.ics 8.1459 + * @param ETag the ETAG of this event is send within the "If-Match" Parameter to tell the server only to delete this version 8.1460 + * @return success of this function 8.1461 + */ 8.1462 + public boolean deleteEvent(URI calendarEventUri, String ETag) { 8.1463 + boolean Result = false; 8.1464 + 8.1465 + try { 8.1466 + HttpDelete request = createDeleteRequest(calendarEventUri); 8.1467 + request.addHeader(mstrcHeaderIfMatch, ETag); 8.1468 + HttpResponse response = httpClient.execute(targetHost, request, mContext); 8.1469 + checkStatus(response); 8.1470 + if ((lastStatusCode == 204) || (lastStatusCode == 200)) { 8.1471 + Result = true; 8.1472 + } else { 8.1473 + Log.w(TAG, "Unkown StatusCode during deletion of an event"); 8.1474 + } 8.1475 + } catch (ClientProtocolException e) { 8.1476 + e.printStackTrace(); 8.1477 + } catch (IOException e) { 8.1478 + if (lastStatusCode == 404) { 8.1479 + //the event has already been deleted on server side. no action needed 8.1480 + Result = true; 8.1481 + } else { 8.1482 + e.printStackTrace(); 8.1483 + } 8.1484 + } catch (AuthenticationException e) { 8.1485 + e.printStackTrace(); 8.1486 + } 8.1487 + 8.1488 + return Result; 8.1489 + } 8.1490 + 8.1491 + /** 8.1492 + * returns the ETAG send by the last server response. 8.1493 + * 8.1494 + * @return the ETAG 8.1495 + */ 8.1496 + public String getLastETag() { 8.1497 + return lastETag; 8.1498 + } 8.1499 + 8.1500 + /** 8.1501 + * returns the DAV-Options send by the last server response. 8.1502 + * 8.1503 + * @return the DAV-Options 8.1504 + */ 8.1505 + public String getLastDav() { 8.1506 + return lastDav; 8.1507 + } 8.1508 + 8.1509 + public void setVersion(String version) { 8.1510 + VERSION = version; 8.1511 + ((AbstractHttpClient) httpClient).getParams() 8.1512 + .setParameter(CoreProtocolPNames.USER_AGENT, this.USER_AGENT + " Version:" + VERSION); 8.1513 + } 8.1514 + 8.1515 + public void setAccount(Account account) { 8.1516 + this.mAccount = account; 8.1517 + } 8.1518 + 8.1519 + public void setProvider(ContentProviderClient provider) { 8.1520 + this.mProvider = provider; 8.1521 + } 8.1522 +}
9.1 --- a/src/org/gege/caldavsyncadapter/caldav/CopyOfEasySSLSocketFactory.java Tue Feb 10 21:55:00 2015 +0100 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,159 +0,0 @@ 9.4 -/** 9.5 - * Copyright (c) 2012-2013, Gerald Garcia 9.6 - * 9.7 - * This file is part of Andoid Caldav Sync Adapter Free. 9.8 - * 9.9 - * Andoid Caldav Sync Adapter Free is free software: you can redistribute 9.10 - * it and/or modify it under the terms of the GNU General Public License 9.11 - * as published by the Free Software Foundation, either version 3 of the 9.12 - * License, or at your option any later version. 9.13 - * 9.14 - * Andoid Caldav Sync Adapter Free is distributed in the hope that 9.15 - * it will be useful, but WITHOUT ANY WARRANTY; without even the implied 9.16 - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9.17 - * GNU General Public License for more details. 9.18 - * 9.19 - * You should have received a copy of the GNU General Public License 9.20 - * along with Andoid Caldav Sync Adapter Free. 9.21 - * If not, see <http://www.gnu.org/licenses/>. 9.22 - * 9.23 - */ 9.24 - 9.25 -package org.gege.caldavsyncadapter.caldav; 9.26 - 9.27 -/* 9.28 - * Licensed to the Apache Software Foundation (ASF) under one 9.29 - * or more contributor license agreements. See the NOTICE file 9.30 - * distributed with this work for additional information 9.31 - * regarding copyright ownership. The ASF licenses this file 9.32 - * to you under the Apache License, Version 2.0 (the 9.33 - * "License"); you may not use this file except in compliance 9.34 - * with the License. You may obtain a copy of the License at 9.35 - * 9.36 - * http://www.apache.org/licenses/LICENSE-2.0 9.37 - * 9.38 - * Unless required by applicable law or agreed to in writing, 9.39 - * software distributed under the License is distributed on an 9.40 - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 9.41 - * KIND, either express or implied. See the License for the 9.42 - * specific language governing permissions and limitations 9.43 - * under the License. 9.44 - */ 9.45 - 9.46 -import java.io.IOException; 9.47 -import java.net.InetAddress; 9.48 -import java.net.InetSocketAddress; 9.49 -import java.net.Socket; 9.50 -import java.net.UnknownHostException; 9.51 - 9.52 -import javax.net.ssl.SSLContext; 9.53 -import javax.net.ssl.SSLSocket; 9.54 -import javax.net.ssl.TrustManager; 9.55 - 9.56 -import org.apache.http.conn.ConnectTimeoutException; 9.57 -import org.apache.http.conn.scheme.LayeredSocketFactory; 9.58 -import org.apache.http.conn.scheme.SocketFactory; 9.59 -import org.apache.http.params.HttpConnectionParams; 9.60 -import org.apache.http.params.HttpParams; 9.61 - 9.62 -/** 9.63 - * This socket factory will create ssl socket that accepts self signed 9.64 - * certificate 9.65 - * 9.66 - * @author olamy 9.67 - * @version $Id: EasySSLSocketFactory.java 765355 2009-04-15 20:59:07Z evenisse 9.68 - * $ 9.69 - * @since 1.2.3 9.70 - */ 9.71 -public class CopyOfEasySSLSocketFactory implements SocketFactory, 9.72 - LayeredSocketFactory { 9.73 - 9.74 - private SSLContext sslcontext = null; 9.75 - 9.76 - private static SSLContext createEasySSLContext() throws IOException { 9.77 - try { 9.78 - SSLContext context = SSLContext.getInstance("TLS"); 9.79 - context.init(null, new TrustManager[] { new EasyX509TrustManager( 9.80 - null) }, null); 9.81 - return context; 9.82 - } catch (Exception e) { 9.83 - throw new IOException(e.getMessage()); 9.84 - } 9.85 - } 9.86 - 9.87 - private SSLContext getSSLContext() throws IOException { 9.88 - if (this.sslcontext == null) { 9.89 - this.sslcontext = createEasySSLContext(); 9.90 - } 9.91 - return this.sslcontext; 9.92 - } 9.93 - 9.94 - /** 9.95 - * @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, 9.96 - * java.lang.String, int, java.net.InetAddress, int, 9.97 - * org.apache.http.params.HttpParams) 9.98 - */ 9.99 - public Socket connectSocket(Socket sock, String host, int port, 9.100 - InetAddress localAddress, int localPort, HttpParams params) 9.101 - throws IOException, UnknownHostException, ConnectTimeoutException { 9.102 - int connTimeout = HttpConnectionParams.getConnectionTimeout(params); 9.103 - int soTimeout = HttpConnectionParams.getSoTimeout(params); 9.104 - 9.105 - InetSocketAddress remoteAddress = new InetSocketAddress(host, port); 9.106 - SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket()); 9.107 - 9.108 - if ((localAddress != null) || (localPort > 0)) { 9.109 - // we need to bind explicitly 9.110 - if (localPort < 0) { 9.111 - localPort = 0; // indicates "any" 9.112 - } 9.113 - InetSocketAddress isa = new InetSocketAddress(localAddress, 9.114 - localPort); 9.115 - sslsock.bind(isa); 9.116 - } 9.117 - 9.118 - sslsock.connect(remoteAddress, connTimeout); 9.119 - sslsock.setSoTimeout(soTimeout); 9.120 - return sslsock; 9.121 - 9.122 - } 9.123 - 9.124 - /** 9.125 - * @see org.apache.http.conn.scheme.SocketFactory#createSocket() 9.126 - */ 9.127 - public Socket createSocket() throws IOException { 9.128 - return getSSLContext().getSocketFactory().createSocket(); 9.129 - } 9.130 - 9.131 - /** 9.132 - * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket) 9.133 - */ 9.134 - public boolean isSecure(Socket socket) throws IllegalArgumentException { 9.135 - return true; 9.136 - } 9.137 - 9.138 - /** 9.139 - * @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, 9.140 - * java.lang.String, int, boolean) 9.141 - */ 9.142 - public Socket createSocket(Socket socket, String host, int port, 9.143 - boolean autoClose) throws IOException, UnknownHostException { 9.144 - return getSSLContext().getSocketFactory().createSocket(); 9.145 - } 9.146 - 9.147 - // ------------------------------------------------------------------- 9.148 - // javadoc in org.apache.http.conn.scheme.SocketFactory says : 9.149 - // Both Object.equals() and Object.hashCode() must be overridden 9.150 - // for the correct operation of some connection managers 9.151 - // ------------------------------------------------------------------- 9.152 - 9.153 - public boolean equals(Object obj) { 9.154 - return ((obj != null) && obj.getClass().equals( 9.155 - CopyOfEasySSLSocketFactory.class)); 9.156 - } 9.157 - 9.158 - public int hashCode() { 9.159 - return CopyOfEasySSLSocketFactory.class.hashCode(); 9.160 - } 9.161 - 9.162 -} 9.163 \ No newline at end of file
10.1 --- a/src/org/gege/caldavsyncadapter/caldav/EasySSLSocketFactory.java Tue Feb 10 21:55:00 2015 +0100 10.2 +++ b/src/org/gege/caldavsyncadapter/caldav/EasySSLSocketFactory.java Tue Feb 10 22:40:00 2015 +0100 10.3 @@ -54,7 +54,8 @@ 10.4 10.5 private static final EasySSLSocketFactory DEFAULT_FACTORY = new EasySSLSocketFactory(); 10.6 10.7 - public static EasySSLSocketFactory getSocketFactory() { 10.8 + public static EasySSLSocketFactory getSocketFactory 10.9 + () { 10.10 return DEFAULT_FACTORY; 10.11 } 10.12
11.1 --- a/src/org/gege/caldavsyncadapter/caldav/entities/DavCalendar.java Tue Feb 10 21:55:00 2015 +0100 11.2 +++ b/src/org/gege/caldavsyncadapter/caldav/entities/DavCalendar.java Tue Feb 10 22:40:00 2015 +0100 11.3 @@ -1,6 +1,6 @@ 11.4 /** 11.5 * Copyright (c) 2012-2013, Gerald Garcia, Timo Berger 11.6 - * 11.7 + * 11.8 * This file is part of Andoid Caldav Sync Adapter Free. 11.9 * 11.10 * Andoid Caldav Sync Adapter Free is free software: you can redistribute 11.11 @@ -16,27 +16,11 @@ 11.12 * You should have received a copy of the GNU General Public License 11.13 * along with Andoid Caldav Sync Adapter Free. 11.14 * If not, see <http://www.gnu.org/licenses/>. 11.15 - * 11.16 + * 11.17 */ 11.18 11.19 package org.gege.caldavsyncadapter.caldav.entities; 11.20 11.21 -import java.io.IOException; 11.22 -import java.net.URI; 11.23 -import java.net.URISyntaxException; 11.24 -import java.util.ArrayList; 11.25 - 11.26 -import javax.xml.parsers.ParserConfigurationException; 11.27 - 11.28 -import org.apache.http.client.ClientProtocolException; 11.29 -import org.gege.caldavsyncadapter.CalendarColors; 11.30 -import org.gege.caldavsyncadapter.Event; 11.31 -import org.gege.caldavsyncadapter.android.entities.AndroidEvent; 11.32 -import org.gege.caldavsyncadapter.caldav.CaldavFacade; 11.33 -import org.gege.caldavsyncadapter.syncadapter.SyncAdapter; 11.34 -import org.gege.caldavsyncadapter.syncadapter.notifications.NotificationsHelper; 11.35 -import org.xml.sax.SAXException; 11.36 - 11.37 import android.accounts.Account; 11.38 import android.content.ContentProviderClient; 11.39 import android.content.ContentUris; 11.40 @@ -49,618 +33,674 @@ 11.41 import android.provider.CalendarContract.Events; 11.42 import android.util.Log; 11.43 11.44 +import org.apache.http.client.ClientProtocolException; 11.45 +import org.gege.caldavsyncadapter.CalendarColors; 11.46 +import org.gege.caldavsyncadapter.Event; 11.47 +import org.gege.caldavsyncadapter.android.entities.AndroidEvent; 11.48 +import org.gege.caldavsyncadapter.caldav.CaldavFacade; 11.49 +import org.gege.caldavsyncadapter.syncadapter.SyncAdapter; 11.50 +import org.gege.caldavsyncadapter.syncadapter.notifications.NotificationsHelper; 11.51 +import org.xml.sax.SAXException; 11.52 + 11.53 +import java.io.IOException; 11.54 +import java.net.URI; 11.55 +import java.net.URISyntaxException; 11.56 +import java.util.ArrayList; 11.57 +import java.util.regex.Matcher; 11.58 +import java.util.regex.Pattern; 11.59 + 11.60 +import javax.xml.parsers.ParserConfigurationException; 11.61 + 11.62 public class DavCalendar { 11.63 - public enum CalendarSource { 11.64 - undefined, Android, CalDAV 11.65 - } 11.66 - 11.67 - private static final String TAG = "Calendar"; 11.68 - 11.69 - /** 11.70 - * stores the CTAG of a calendar 11.71 - */ 11.72 - public static String CTAG = Calendars.CAL_SYNC1; 11.73 - 11.74 - /** 11.75 - * stores the URI of a calendar 11.76 - * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname 11.77 - */ 11.78 - public static String URI = Calendars._SYNC_ID; 11.79 - 11.80 - public static String SERVERURL = Calendars.CAL_SYNC2; 11.81 - 11.82 - private String strCalendarColor = ""; 11.83 - 11.84 - private ArrayList<Uri> mNotifyList = new ArrayList<Uri>(); 11.85 + public enum CalendarSource { 11.86 + undefined, Android, CalDAV 11.87 + } 11.88 11.89 - /** 11.90 - * the event transformed into ContentValues 11.91 - */ 11.92 - public ContentValues ContentValues = new ContentValues(); 11.93 - 11.94 - private Account mAccount = null; 11.95 - private ContentProviderClient mProvider = null; 11.96 - 11.97 - public boolean foundServerSide = false; 11.98 - public boolean foundClientSide = false; 11.99 - public CalendarSource Source = CalendarSource.undefined; 11.100 - 11.101 - public String ServerUrl = ""; 11.102 - 11.103 - private ArrayList<CalendarEvent> mCalendarEvents = new ArrayList<CalendarEvent>(); 11.104 - 11.105 - private int mTagCounter = 1; 11.106 - 11.107 - /** 11.108 - * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname 11.109 - */ 11.110 - public URI getURI() { 11.111 - String strUri = this.getContentValueAsString(DavCalendar.URI); 11.112 - URI result = null; 11.113 - try { 11.114 - result = new URI(strUri); 11.115 - } catch (URISyntaxException e) { 11.116 - e.printStackTrace(); 11.117 - } 11.118 - return result; 11.119 - } 11.120 + private static final String TAG = "Calendar"; 11.121 11.122 - /** 11.123 - * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname 11.124 - */ 11.125 - public void setURI(URI uri) { 11.126 - this.setContentValueAsString(DavCalendar.URI, uri.toString()); 11.127 - } 11.128 + /** 11.129 + * stores the CTAG of a calendar 11.130 + */ 11.131 + public static String CTAG = Calendars.CAL_SYNC1; 11.132 11.133 - /** 11.134 - * example: Cleartext Display Name 11.135 - */ 11.136 - public String getCalendarDisplayName() { 11.137 - return this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME); 11.138 - } 11.139 + /** 11.140 + * stores the URI of a calendar 11.141 + * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname 11.142 + */ 11.143 + public static String URI = Calendars._SYNC_ID; 11.144 11.145 - /** 11.146 - * example: Cleartext Display Name 11.147 - */ 11.148 - public void setCalendarDisplayName(String displayName) { 11.149 - this.setContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME, displayName); 11.150 - } 11.151 - 11.152 + public static String SERVERURL = Calendars.CAL_SYNC2; 11.153 11.154 - /** 11.155 - * example: 1143 11.156 - */ 11.157 - public void setCTag(String cTag, boolean Update) { 11.158 - this.setContentValueAsString(DavCalendar.CTAG, cTag); 11.159 - if (Update) { 11.160 - //serverCalendar.updateAndroidCalendar(androidCalendarUri, Calendar.CTAG, serverCalendar.getcTag()); 11.161 - try { 11.162 - this.updateAndroidCalendar(this.getAndroidCalendarUri(), CTAG, cTag); 11.163 - } catch (RemoteException e) { 11.164 - e.printStackTrace(); 11.165 - } 11.166 - } 11.167 - } 11.168 - 11.169 - /** 11.170 - * example: 1143 11.171 - */ 11.172 - public String getcTag() { 11.173 - return this.getContentValueAsString(DavCalendar.CTAG); 11.174 - } 11.175 - 11.176 - /** 11.177 - * example: #FFCCAA 11.178 - */ 11.179 - public void setCalendarColorAsString(String color) { 11.180 - int maxlen = 6; 11.181 - 11.182 - this.strCalendarColor = color; 11.183 - if (!color.equals("")) { 11.184 - String strColor = color.replace("#", ""); 11.185 - if (strColor.length() > maxlen) 11.186 - strColor = strColor.substring(0, maxlen); 11.187 - int intColor = Integer.parseInt(strColor, 16); 11.188 - this.setContentValueAsInt(Calendars.CALENDAR_COLOR, intColor); 11.189 - } 11.190 - } 11.191 + private String strCalendarColor = ""; 11.192 11.193 - /** 11.194 - * example: #FFCCAA 11.195 - */ 11.196 - public String getCalendarColorAsString() { 11.197 - return this.strCalendarColor; 11.198 - } 11.199 + private ArrayList<Uri> mNotifyList = new ArrayList<Uri>(); 11.200 11.201 - /** 11.202 - * example 12345 11.203 - */ 11.204 - public int getCalendarColor() { 11.205 - return this.getContentValueAsInt(Calendars.CALENDAR_COLOR); 11.206 - } 11.207 - 11.208 - /** 11.209 - * example 12345 11.210 - */ 11.211 - public void setCalendarColor(int color) { 11.212 - this.setContentValueAsInt(Calendars.CALENDAR_COLOR, color); 11.213 - } 11.214 + /** 11.215 + * the event transformed into ContentValues 11.216 + */ 11.217 + public ContentValues ContentValues = new ContentValues(); 11.218 11.219 - /** 11.220 - * example: 11.221 - * should be: calendarname 11.222 - * but is: http://caldav.example.com/calendarserver.php/calendars/username/calendarname/ 11.223 - */ 11.224 - public String getCalendarName() { 11.225 - return this.getContentValueAsString(Calendars.NAME); 11.226 - } 11.227 + private Account mAccount = null; 11.228 + private ContentProviderClient mProvider = null; 11.229 11.230 - /** 11.231 - * example: 11.232 - * should be: calendarname 11.233 - * but is: http://caldav.example.com/calendarserver.php/calendars/username/calendarname/ 11.234 - */ 11.235 - public void setCalendarName(String calendarName) { 11.236 - this.setContentValueAsString(Calendars.NAME, calendarName); 11.237 - } 11.238 + public boolean foundServerSide = false; 11.239 + public boolean foundClientSide = false; 11.240 + public CalendarSource Source = CalendarSource.undefined; 11.241 11.242 - /** 11.243 - * example: 8 11.244 - */ 11.245 - public int getAndroidCalendarId() { 11.246 - return this.getContentValueAsInt(Calendars._ID); 11.247 - } 11.248 + public String ServerUrl = ""; 11.249 11.250 - /** 11.251 - * example: 8 11.252 - */ 11.253 - public void setAndroidCalendarId(int androidCalendarId) { 11.254 - this.setContentValueAsInt(Calendars._ID, androidCalendarId); 11.255 - } 11.256 + private ArrayList<CalendarEvent> mCalendarEvents = new ArrayList<CalendarEvent>(); 11.257 11.258 - /** 11.259 - * example: content://com.android.calendar/calendars/8 11.260 - */ 11.261 - public Uri getAndroidCalendarUri() { 11.262 - return ContentUris.withAppendedId(Calendars.CONTENT_URI, this.getAndroidCalendarId()); 11.263 - } 11.264 - 11.265 - /** 11.266 - * empty constructor 11.267 - */ 11.268 - public DavCalendar(CalendarSource source) { 11.269 - this.Source = source; 11.270 - } 11.271 - 11.272 - /** 11.273 - * creates an new instance from a cursor 11.274 - * @param cur must be a cursor from "ContentProviderClient" with Uri Calendars.CONTENT_URI 11.275 - */ 11.276 - public DavCalendar(Account account, ContentProviderClient provider, Cursor cur, CalendarSource source, String serverUrl) { 11.277 - this.mAccount = account; 11.278 - this.mProvider = provider; 11.279 - this.foundClientSide = true; 11.280 - this.Source = source; 11.281 - this.ServerUrl = serverUrl; 11.282 + private int mTagCounter = 1; 11.283 11.284 - String strSyncID = cur.getString(cur.getColumnIndex(Calendars._SYNC_ID)); 11.285 - String strName = cur.getString(cur.getColumnIndex(Calendars.NAME)); 11.286 - String strDisplayName = cur.getString(cur.getColumnIndex(Calendars.CALENDAR_DISPLAY_NAME)); 11.287 - String strCTAG = cur.getString(cur.getColumnIndex(DavCalendar.CTAG)); 11.288 - String strServerUrl = cur.getString(cur.getColumnIndex(DavCalendar.SERVERURL)); 11.289 - int intAndroidCalendarId = cur.getInt(cur.getColumnIndex(Calendars._ID)); 11.290 + /** 11.291 + * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname 11.292 + */ 11.293 + public URI getURI() { 11.294 + String strUri = this.getContentValueAsString(DavCalendar.URI); 11.295 + URI result = null; 11.296 + try { 11.297 + result = new URI(strUri); 11.298 + } catch (URISyntaxException e) { 11.299 + e.printStackTrace(); 11.300 + } 11.301 + return result; 11.302 + } 11.303 11.304 - this.setCalendarName(strName); 11.305 - this.setCalendarDisplayName(strDisplayName); 11.306 - this.setCTag(strCTAG, false); 11.307 - this.setAndroidCalendarId(intAndroidCalendarId); 11.308 - 11.309 - if (strSyncID == null) { 11.310 - this.correctSyncID(strName); 11.311 - strSyncID = strName; 11.312 - } 11.313 - if (strServerUrl == null) { 11.314 - this.correctServerUrl(serverUrl); 11.315 - } 11.316 - URI uri = null; 11.317 - try { 11.318 - uri = new URI(strSyncID); 11.319 - } catch (URISyntaxException e) { 11.320 - e.printStackTrace(); 11.321 - } 11.322 - this.setURI(uri); 11.323 - } 11.324 - 11.325 - /** 11.326 - * checks a given list of android calendars for a specific android calendar. 11.327 - * this calendar should be a server calendar as it is searched for. 11.328 - * if the calendar is not found, it will be created. 11.329 - * @param androidCalList the list of android calendars 11.330 - * @param context 11.331 - * @return the found android calendar or null of fails 11.332 - * @throws RemoteException 11.333 - */ 11.334 - public Uri checkAndroidCalendarList(CalendarList androidCalList, android.content.Context context) throws RemoteException { 11.335 - Uri androidCalendarUri = null; 11.336 - boolean isCalendarExist = false; 11.337 - 11.338 - DavCalendar androidCalendar = androidCalList.getCalendarByURI(this.getURI()); 11.339 - if (androidCalendar != null) { 11.340 - isCalendarExist = true; 11.341 - androidCalendar.foundServerSide = true; 11.342 - } 11.343 - 11.344 + /** 11.345 + * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname 11.346 + */ 11.347 + public void setURI(URI uri) { 11.348 + this.setContentValueAsString(DavCalendar.URI, uri.toString()); 11.349 + } 11.350 11.351 - if (!isCalendarExist) { 11.352 - DavCalendar newCal = this.createNewAndroidCalendar(this, androidCalList.getCalendarList().size(), context); 11.353 - if (newCal != null) { 11.354 - androidCalList.addCalendar(newCal); 11.355 - androidCalendarUri = newCal.getAndroidCalendarUri(); 11.356 - } 11.357 - } else { 11.358 - androidCalendarUri = androidCalendar.getAndroidCalendarUri(); 11.359 - if (!this.getCalendarColorAsString().equals("")) { 11.360 - //serverCalendar.updateCalendarColor(returnedCalendarUri, serverCalendar); 11.361 - this.updateAndroidCalendar(androidCalendarUri, Calendars.CALENDAR_COLOR, this.getCalendarColor()); 11.362 - } 11.363 - if ((this.ContentValues.containsKey(Calendars.CALENDAR_DISPLAY_NAME)) && 11.364 - (androidCalendar.ContentValues.containsKey(Calendars.CALENDAR_DISPLAY_NAME))) { 11.365 - String serverDisplayName = this.ContentValues.getAsString(Calendars.CALENDAR_DISPLAY_NAME); 11.366 - String clientDisplayName = androidCalendar.ContentValues.getAsString(Calendars.CALENDAR_DISPLAY_NAME); 11.367 - if (!serverDisplayName.equals(clientDisplayName)) 11.368 - this.updateAndroidCalendar(androidCalendarUri, Calendars.CALENDAR_DISPLAY_NAME, serverDisplayName); 11.369 - } 11.370 - } 11.371 - 11.372 - return androidCalendarUri; 11.373 - } 11.374 - 11.375 - /** 11.376 - * COMPAT: the calendar Uri was stored as calendar Name. this function updates the URI (_SYNC_ID) 11.377 - * @param calendarUri the real calendarUri 11.378 - * @return success of this function 11.379 - */ 11.380 - private boolean correctSyncID(String calendarUri) { 11.381 - boolean Result = false; 11.382 - Log.v(TAG, "correcting SyncID for calendar:" + this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME)); 11.383 - 11.384 - ContentValues mUpdateValues = new ContentValues(); 11.385 - mUpdateValues.put(DavCalendar.URI, calendarUri); 11.386 - 11.387 - try { 11.388 - mProvider.update(this.SyncAdapterCalendar(), mUpdateValues, null, null); 11.389 - Result = true; 11.390 - } catch (RemoteException e) { 11.391 - e.printStackTrace(); 11.392 - } 11.393 - 11.394 - return Result; 11.395 - } 11.396 - 11.397 - /** 11.398 - * COMPAT: the serverurl (CAL_SYNC2) was not sored within a calendar. this fixes it. (see #98) 11.399 - * @param serverUrl the current serverurl 11.400 - * @return success of this function 11.401 - */ 11.402 - private boolean correctServerUrl(String serverUrl) { 11.403 - boolean Result = false; 11.404 - Log.v(TAG, "correcting ServerUrl for calendar:" + this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME)); 11.405 - 11.406 - ContentValues mUpdateValues = new ContentValues(); 11.407 - mUpdateValues.put(DavCalendar.SERVERURL, serverUrl); 11.408 - 11.409 - try { 11.410 - mProvider.update(this.SyncAdapterCalendar(), mUpdateValues, null, null); 11.411 - Result = true; 11.412 - } catch (RemoteException e) { 11.413 - e.printStackTrace(); 11.414 - } 11.415 - 11.416 - return Result; 11.417 - } 11.418 - 11.419 - /** 11.420 - * creates a new androidCalendar 11.421 - * @param serverCalendar 11.422 - * @param index 11.423 - * @param context 11.424 - * @return the new androidCalendar or null if fails 11.425 - */ 11.426 - private DavCalendar createNewAndroidCalendar(DavCalendar serverCalendar, int index, android.content.Context context) { 11.427 - Uri newUri = null; 11.428 - DavCalendar Result = null; 11.429 - 11.430 - final ContentValues contentValues = new ContentValues(); 11.431 - contentValues.put(DavCalendar.URI, serverCalendar.getURI().toString()); 11.432 - contentValues.put(DavCalendar.SERVERURL, this.ServerUrl); 11.433 + /** 11.434 + * example: Cleartext Display Name 11.435 + */ 11.436 + public String getCalendarDisplayName() { 11.437 + return this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME); 11.438 + } 11.439 11.440 - contentValues.put(Calendars.VISIBLE, 1); 11.441 - contentValues.put(Calendars.CALENDAR_DISPLAY_NAME, serverCalendar.getCalendarDisplayName()); 11.442 - contentValues.put(Calendars.ACCOUNT_NAME, mAccount.name); 11.443 - contentValues.put(Calendars.ACCOUNT_TYPE, mAccount.type); 11.444 - contentValues.put(Calendars.OWNER_ACCOUNT, mAccount.name); 11.445 - contentValues.put(Calendars.SYNC_EVENTS, 1); 11.446 - contentValues.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER); 11.447 - 11.448 - if (!serverCalendar.getCalendarColorAsString().equals("")) { 11.449 - contentValues.put(Calendars.CALENDAR_COLOR, serverCalendar.getCalendarColor()); 11.450 - } else { 11.451 - // find a color 11.452 - //int index = mList.size(); 11.453 - index = index % CalendarColors.colors.length; 11.454 - contentValues.put(Calendars.CALENDAR_COLOR, CalendarColors.colors[index]); 11.455 - } 11.456 + /** 11.457 + * example: Cleartext Display Name 11.458 + */ 11.459 + public void setCalendarDisplayName(String displayName) { 11.460 + this.setContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME, displayName); 11.461 + } 11.462 11.463 - try { 11.464 - newUri = mProvider.insert(asSyncAdapter(Calendars.CONTENT_URI, mAccount.name, mAccount.type), contentValues); 11.465 - } catch (RemoteException e) { 11.466 - e.printStackTrace(); 11.467 - } 11.468 11.469 - // it is possible that this calendar already exists but the provider failed to find it within isCalendarExist() 11.470 - // the adapter would try to create a new calendar but the provider fails again to create a new calendar. 11.471 - if (newUri != null) { 11.472 - long newCalendarId = ContentUris.parseId(newUri); 11.473 + /** 11.474 + * example: 1143 11.475 + */ 11.476 + public void setCTag(String cTag, boolean Update) { 11.477 + this.setContentValueAsString(DavCalendar.CTAG, cTag); 11.478 + if (Update) { 11.479 + //serverCalendar.updateAndroidCalendar(androidCalendarUri, Calendar.CTAG, serverCalendar.getcTag()); 11.480 + try { 11.481 + this.updateAndroidCalendar(this.getAndroidCalendarUri(), CTAG, cTag); 11.482 + } catch (RemoteException e) { 11.483 + e.printStackTrace(); 11.484 + } 11.485 + } 11.486 + } 11.487 11.488 - Cursor cur = null; 11.489 - Uri uri = Calendars.CONTENT_URI; 11.490 - String selection = "(" + Calendars._ID + " = ?)"; 11.491 - String[] selectionArgs = new String[] {String.valueOf(newCalendarId)}; 11.492 + /** 11.493 + * example: 1143 11.494 + */ 11.495 + public String getcTag() { 11.496 + return this.getContentValueAsString(DavCalendar.CTAG); 11.497 + } 11.498 11.499 - // Submit the query and get a Cursor object back. 11.500 - try { 11.501 - cur = mProvider.query(uri, null, selection, selectionArgs, null); 11.502 - } catch (RemoteException e) { 11.503 - e.printStackTrace(); 11.504 - } 11.505 - 11.506 - if (cur != null) { 11.507 - while (cur.moveToNext()) { 11.508 - Result = new DavCalendar(mAccount, mProvider, cur, this.Source, this.ServerUrl); 11.509 - Result.foundServerSide = true; 11.510 - } 11.511 - cur.close(); 11.512 - //if (Result != null) 11.513 - // this.mList.add(Result); 11.514 - } 11.515 - Log.i(TAG, "New calendar created : URI=" + Result.getAndroidCalendarUri()); 11.516 - NotificationsHelper.signalSyncErrors(context, "CalDAV Sync Adapter", "new calendar found: " + Result.getCalendarDisplayName()); 11.517 - mNotifyList.add(Result.getAndroidCalendarUri()); 11.518 - } 11.519 - 11.520 - return Result; 11.521 - } 11.522 - 11.523 - /** 11.524 - * there is no corresponding calendar on server side. time to delete this calendar on android side. 11.525 - * @return 11.526 - */ 11.527 - public boolean deleteAndroidCalendar() { 11.528 - boolean Result = false; 11.529 - 11.530 - String mSelectionClause = "(" + Calendars._ID + " = ?)"; 11.531 - int calendarId = this.getAndroidCalendarId(); 11.532 - String[] mSelectionArgs = {Long.toString(calendarId)}; 11.533 - 11.534 - int CountDeleted = 0; 11.535 - try { 11.536 - CountDeleted = mProvider.delete(this.SyncAdapter(), mSelectionClause, mSelectionArgs); 11.537 - Log.i(TAG,"Calendar deleted: " + String.valueOf(calendarId)); 11.538 - this.mNotifyList.add(this.getAndroidCalendarUri()); 11.539 - Result = true; 11.540 - } catch (RemoteException e) { 11.541 - e.printStackTrace(); 11.542 - } 11.543 - Log.d(TAG, "Android Calendars deleted: " + Integer.toString(CountDeleted)); 11.544 - 11.545 - return Result; 11.546 - } 11.547 + /** 11.548 + * example: #FFCCAA 11.549 + */ 11.550 + public void setCalendarColorAsString(String color) { 11.551 + int maxlen = 6; 11.552 11.553 - /** 11.554 - * updates the android calendar 11.555 - * @param calendarUri the uri of the androidCalendar 11.556 - * @param target must be from android.provider.CalendarContract.Calendars 11.557 - * @param value the new value for the target 11.558 - * @throws RemoteException 11.559 - */ 11.560 - private void updateAndroidCalendar(Uri calendarUri, String target, int value) throws RemoteException { 11.561 - ContentValues mUpdateValues = new ContentValues(); 11.562 - mUpdateValues.put(target, value); 11.563 - 11.564 - mProvider.update(asSyncAdapter(calendarUri, mAccount.name, mAccount.type), mUpdateValues, null, null); 11.565 - } 11.566 + this.strCalendarColor = color; 11.567 + if (!color.equals("")) { 11.568 + String strColor = color.replace("#", ""); 11.569 + if (strColor.length() > maxlen) 11.570 + strColor = strColor.substring(0, maxlen); 11.571 + int intColor = Integer.parseInt(strColor, 16); 11.572 + this.setContentValueAsInt(Calendars.CALENDAR_COLOR, intColor); 11.573 + } 11.574 + } 11.575 11.576 - /** 11.577 - * updates the android calendar 11.578 - * @param calendarUri the uri of the androidCalendar 11.579 - * @param target must be from android.provider.CalendarContract.Calendars 11.580 - * @param value the new value for the target 11.581 - * @throws RemoteException 11.582 - */ 11.583 - private void updateAndroidCalendar(Uri calendarUri, String target, String value) throws RemoteException { 11.584 - ContentValues mUpdateValues = new ContentValues(); 11.585 - mUpdateValues.put(target, value); 11.586 - 11.587 - mProvider.update(asSyncAdapter(calendarUri, mAccount.name, mAccount.type), mUpdateValues, null, null); 11.588 - } 11.589 - 11.590 - /** 11.591 - * marks the android event as already handled 11.592 - * @return 11.593 - * @see AndroidEvent#cInternalTag 11.594 - * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 11.595 - * @throws RemoteException 11.596 - */ 11.597 - public boolean tagAndroidEvent(AndroidEvent androidEvent) throws RemoteException { 11.598 - boolean Result = false; 11.599 - 11.600 - ContentValues values = new ContentValues(); 11.601 - //values.put(Event.INTERNALTAG, 1); 11.602 - values.put(Event.INTERNALTAG, mTagCounter); 11.603 - //values.put(Event.INTERNALTAG, String.valueOf(mTagCounter)); 11.604 - 11.605 - int RowCount = this.mProvider.update(asSyncAdapter(androidEvent.getUri(), this.mAccount.name, this.mAccount.type), values, null, null); 11.606 - //Log.v(TAG,"event tag nr: " + String.valueOf(mTagCounter)); 11.607 - //Log.v(TAG,"Rows updated: " + String.valueOf(RowCount)); 11.608 - 11.609 - if (RowCount == 1) { 11.610 - Result = true; 11.611 - mTagCounter += 1; 11.612 - } else { 11.613 - Log.v(TAG,"EVENT NOT TAGGED!"); 11.614 - } 11.615 - 11.616 - return Result; 11.617 - } 11.618 - 11.619 - /** 11.620 - * removes the tag of all android events 11.621 - * @return 11.622 - * @see AndroidEvent#cInternalTag 11.623 - * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 11.624 - * @throws RemoteException 11.625 - */ 11.626 - public int untagAndroidEvents() throws RemoteException { 11.627 - int RowCount = 0; 11.628 - int Steps = 100; 11.629 - ContentValues values = new ContentValues(); 11.630 - values.put(Event.INTERNALTAG, 0); 11.631 + /** 11.632 + * example: #FFCCAA 11.633 + */ 11.634 + public String getCalendarColorAsString() { 11.635 + return this.strCalendarColor; 11.636 + } 11.637 11.638 - for (int i=1; i < this.mTagCounter; i = i + Steps) { 11.639 - String mSelectionClause = "(CAST(" + Event.INTERNALTAG + " AS INT) >= ?) AND (CAST(" + Event.INTERNALTAG + " AS INT) < ?) AND (" + Events.CALENDAR_ID + " = ?)"; 11.640 - String[] mSelectionArgs = {String.valueOf(i), String.valueOf(i + Steps), Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; 11.641 - RowCount += this.mProvider.update(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), values, mSelectionClause, mSelectionArgs); 11.642 - } 11.643 - /*String mSelectionClause = "(" + Event.INTERNALTAG + " > ?) AND (" + Events.CALENDAR_ID + " = ?)"; 11.644 - String[] mSelectionArgs = {"0", Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; 11.645 + /** 11.646 + * example 12345 11.647 + */ 11.648 + public int getCalendarColor() { 11.649 + return this.getContentValueAsInt(Calendars.CALENDAR_COLOR); 11.650 + } 11.651 + 11.652 + /** 11.653 + * example 12345 11.654 + */ 11.655 + public void setCalendarColor(int color) { 11.656 + this.setContentValueAsInt(Calendars.CALENDAR_COLOR, color); 11.657 + } 11.658 + 11.659 + /** 11.660 + * example: 11.661 + * should be: calendarname 11.662 + * but is: http://caldav.example.com/calendarserver.php/calendars/username/calendarname/ 11.663 + */ 11.664 + public String getCalendarName() { 11.665 + return this.getContentValueAsString(Calendars.NAME); 11.666 + } 11.667 + 11.668 + /** 11.669 + * example: 11.670 + * should be: calendarname 11.671 + * but is: http://caldav.example.com/calendarserver.php/calendars/username/calendarname/ 11.672 + */ 11.673 + public void setCalendarName(String calendarName) { 11.674 + this.setContentValueAsString(Calendars.NAME, calendarName); 11.675 + } 11.676 + 11.677 + /** 11.678 + * example: 8 11.679 + */ 11.680 + public int getAndroidCalendarId() { 11.681 + return this.getContentValueAsInt(Calendars._ID); 11.682 + } 11.683 + 11.684 + /** 11.685 + * example: 8 11.686 + */ 11.687 + public void setAndroidCalendarId(int androidCalendarId) { 11.688 + this.setContentValueAsInt(Calendars._ID, androidCalendarId); 11.689 + } 11.690 + 11.691 + /** 11.692 + * example: content://com.android.calendar/calendars/8 11.693 + */ 11.694 + public Uri getAndroidCalendarUri() { 11.695 + return ContentUris.withAppendedId(Calendars.CONTENT_URI, this.getAndroidCalendarId()); 11.696 + } 11.697 + 11.698 + /** 11.699 + * empty constructor 11.700 + */ 11.701 + public DavCalendar(CalendarSource source) { 11.702 + this.Source = source; 11.703 + } 11.704 + 11.705 + /** 11.706 + * creates an new instance from a cursor 11.707 + * 11.708 + * @param cur must be a cursor from "ContentProviderClient" with Uri Calendars.CONTENT_URI 11.709 + */ 11.710 + public DavCalendar(Account account, ContentProviderClient provider, Cursor cur, CalendarSource source, String serverUrl) { 11.711 + this.mAccount = account; 11.712 + this.mProvider = provider; 11.713 + this.foundClientSide = true; 11.714 + this.Source = source; 11.715 + this.ServerUrl = serverUrl; 11.716 + 11.717 + String strSyncID = cur.getString(cur.getColumnIndex(Calendars._SYNC_ID)); 11.718 + String strName = cur.getString(cur.getColumnIndex(Calendars.NAME)); 11.719 + String strDisplayName = cur.getString(cur.getColumnIndex(Calendars.CALENDAR_DISPLAY_NAME)); 11.720 + String strCTAG = cur.getString(cur.getColumnIndex(DavCalendar.CTAG)); 11.721 + String strServerUrl = cur.getString(cur.getColumnIndex(DavCalendar.SERVERURL)); 11.722 + String strCalendarColor = cur.getString(cur.getColumnIndex(Calendars.CALENDAR_COLOR)); 11.723 + int intAndroidCalendarId = cur.getInt(cur.getColumnIndex(Calendars._ID)); 11.724 + 11.725 + this.setCalendarName(strName); 11.726 + this.setCalendarDisplayName(strDisplayName); 11.727 + this.setCTag(strCTAG, false); 11.728 + this.setAndroidCalendarId(intAndroidCalendarId); 11.729 + this.setCalendarColor(Integer.parseInt(strCalendarColor)); 11.730 + 11.731 + if (strSyncID == null) { 11.732 + this.correctSyncID(strName); 11.733 + strSyncID = strName; 11.734 + } 11.735 + if (strServerUrl == null) { 11.736 + this.correctServerUrl(serverUrl); 11.737 + } 11.738 + URI uri = null; 11.739 + try { 11.740 + uri = new URI(strSyncID); 11.741 + } catch (URISyntaxException e) { 11.742 + e.printStackTrace(); 11.743 + } 11.744 + this.setURI(uri); 11.745 + } 11.746 + 11.747 + /** 11.748 + * checks a given list of android calendars for a specific android calendar. 11.749 + * this calendar should be a server calendar as it is searched for. 11.750 + * if the calendar is not found, it will be created. 11.751 + * 11.752 + * @param androidCalList the list of android calendars 11.753 + * @param context 11.754 + * @return the found android calendar or null of fails 11.755 + * @throws RemoteException 11.756 + */ 11.757 + public Uri checkAndroidCalendarList(CalendarList androidCalList, android.content.Context context) throws RemoteException { 11.758 + Uri androidCalendarUri = null; 11.759 + boolean isCalendarExist = false; 11.760 + 11.761 + DavCalendar androidCalendar = androidCalList.getCalendarByURI(this.getURI()); 11.762 + if (androidCalendar != null) { 11.763 + isCalendarExist = true; 11.764 + androidCalendar.foundServerSide = true; 11.765 + } 11.766 + 11.767 + 11.768 + if (!isCalendarExist) { 11.769 + DavCalendar newCal = this.createNewAndroidCalendar(this, androidCalList.getCalendarList() 11.770 + .size(), context); 11.771 + if (newCal != null) { 11.772 + androidCalList.addCalendar(newCal); 11.773 + androidCalendarUri = newCal.getAndroidCalendarUri(); 11.774 + } 11.775 + } else { 11.776 + androidCalendarUri = androidCalendar.getAndroidCalendarUri(); 11.777 + if (!this.getCalendarColorAsString().equals("")) { 11.778 + this.updateAndroidCalendar(androidCalendarUri, Calendars.CALENDAR_COLOR, getColorAsHex(this.getCalendarColorAsString())); 11.779 + } 11.780 + if ((this.ContentValues.containsKey(Calendars.CALENDAR_DISPLAY_NAME)) && 11.781 + (androidCalendar.ContentValues.containsKey(Calendars.CALENDAR_DISPLAY_NAME))) { 11.782 + String serverDisplayName = this.ContentValues.getAsString(Calendars.CALENDAR_DISPLAY_NAME); 11.783 + String clientDisplayName = androidCalendar.ContentValues.getAsString(Calendars.CALENDAR_DISPLAY_NAME); 11.784 + if (!serverDisplayName.equals(clientDisplayName)) 11.785 + this.updateAndroidCalendar(androidCalendarUri, Calendars.CALENDAR_DISPLAY_NAME, serverDisplayName); 11.786 + } 11.787 + } 11.788 + 11.789 + return androidCalendarUri; 11.790 + } 11.791 + 11.792 + /** 11.793 + * COMPAT: the calendar Uri was stored as calendar Name. this function updates the URI (_SYNC_ID) 11.794 + * 11.795 + * @param calendarUri the real calendarUri 11.796 + * @return success of this function 11.797 + */ 11.798 + private boolean correctSyncID(String calendarUri) { 11.799 + boolean Result = false; 11.800 + Log.v(TAG, "correcting SyncID for calendar:" + this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME)); 11.801 + 11.802 + ContentValues mUpdateValues = new ContentValues(); 11.803 + mUpdateValues.put(DavCalendar.URI, calendarUri); 11.804 + 11.805 + try { 11.806 + mProvider.update(this.SyncAdapterCalendar(), mUpdateValues, null, null); 11.807 + Result = true; 11.808 + } catch (RemoteException e) { 11.809 + e.printStackTrace(); 11.810 + } 11.811 + 11.812 + return Result; 11.813 + } 11.814 + 11.815 + /** 11.816 + * COMPAT: the serverurl (CAL_SYNC2) was not sored within a calendar. this fixes it. (see #98) 11.817 + * 11.818 + * @param serverUrl the current serverurl 11.819 + * @return success of this function 11.820 + */ 11.821 + private boolean correctServerUrl(String serverUrl) { 11.822 + boolean Result = false; 11.823 + Log.v(TAG, "correcting ServerUrl for calendar:" + this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME)); 11.824 + 11.825 + ContentValues mUpdateValues = new ContentValues(); 11.826 + mUpdateValues.put(DavCalendar.SERVERURL, serverUrl); 11.827 + 11.828 + try { 11.829 + mProvider.update(this.SyncAdapterCalendar(), mUpdateValues, null, null); 11.830 + Result = true; 11.831 + } catch (RemoteException e) { 11.832 + e.printStackTrace(); 11.833 + } 11.834 + 11.835 + return Result; 11.836 + } 11.837 + 11.838 + /** 11.839 + * creates a new androidCalendar 11.840 + * 11.841 + * @param serverCalendar 11.842 + * @param index 11.843 + * @param context 11.844 + * @return the new androidCalendar or null if fails 11.845 + */ 11.846 + private DavCalendar createNewAndroidCalendar(DavCalendar serverCalendar, int index, android.content.Context context) { 11.847 + Uri newUri = null; 11.848 + DavCalendar Result = null; 11.849 + 11.850 + final ContentValues contentValues = new ContentValues(); 11.851 + contentValues.put(DavCalendar.URI, serverCalendar.getURI().toString()); 11.852 + contentValues.put(DavCalendar.SERVERURL, this.ServerUrl); 11.853 + 11.854 + contentValues.put(Calendars.VISIBLE, 1); 11.855 + contentValues.put(Calendars.CALENDAR_DISPLAY_NAME, serverCalendar.getCalendarDisplayName()); 11.856 + contentValues.put(Calendars.ACCOUNT_NAME, mAccount.name); 11.857 + contentValues.put(Calendars.ACCOUNT_TYPE, mAccount.type); 11.858 + contentValues.put(Calendars.OWNER_ACCOUNT, mAccount.name); 11.859 + contentValues.put(Calendars.SYNC_EVENTS, 1); 11.860 + contentValues.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER); 11.861 + 11.862 + String calendarColorAsString = serverCalendar.getCalendarColorAsString(); 11.863 + if (!calendarColorAsString.isEmpty()) { 11.864 + int color = getColorAsHex(calendarColorAsString); 11.865 + contentValues.put(Calendars.CALENDAR_COLOR, color); 11.866 + } else { 11.867 + // find a color 11.868 + //int index = mList.size(); 11.869 + index = index % CalendarColors.colors.length; 11.870 + contentValues.put(Calendars.CALENDAR_COLOR, CalendarColors.colors[2]); 11.871 + } 11.872 + 11.873 + try { 11.874 + newUri = mProvider.insert(asSyncAdapter(Calendars.CONTENT_URI, mAccount.name, mAccount.type), contentValues); 11.875 + } catch (RemoteException e) { 11.876 + e.printStackTrace(); 11.877 + } 11.878 + 11.879 + // it is possible that this calendar already exists but the provider failed to find it within isCalendarExist() 11.880 + // the adapter would try to create a new calendar but the provider fails again to create a new calendar. 11.881 + if (newUri != null) { 11.882 + long newCalendarId = ContentUris.parseId(newUri); 11.883 + 11.884 + Cursor cur = null; 11.885 + Uri uri = Calendars.CONTENT_URI; 11.886 + String selection = "(" + Calendars._ID + " = ?)"; 11.887 + String[] selectionArgs = new String[]{String.valueOf(newCalendarId)}; 11.888 + 11.889 + // Submit the query and get a Cursor object back. 11.890 + try { 11.891 + cur = mProvider.query(uri, null, selection, selectionArgs, null); 11.892 + } catch (RemoteException e) { 11.893 + e.printStackTrace(); 11.894 + } 11.895 + 11.896 + if (cur != null) { 11.897 + while (cur.moveToNext()) { 11.898 + Result = new DavCalendar(mAccount, mProvider, cur, this.Source, this.ServerUrl); 11.899 + Result.foundServerSide = true; 11.900 + } 11.901 + cur.close(); 11.902 + //if (Result != null) 11.903 + // this.mList.add(Result); 11.904 + } 11.905 + Log.i(TAG, "New calendar created : URI=" + Result.getAndroidCalendarUri()); 11.906 + NotificationsHelper.signalSyncErrors(context, "CalDAV Sync Adapter", "new calendar found: " + Result 11.907 + .getCalendarDisplayName()); 11.908 + mNotifyList.add(Result.getAndroidCalendarUri()); 11.909 + } 11.910 + 11.911 + return Result; 11.912 + } 11.913 + 11.914 + private int getColorAsHex(String calendarColorAsString) { 11.915 + int color = 0x0000FF00; 11.916 + Pattern p = Pattern.compile("#?(\\p{XDigit}{6})(\\p{XDigit}{2})?"); 11.917 + Matcher m = p.matcher(calendarColorAsString); 11.918 + if (m.find()) { 11.919 + int color_rgb = Integer.parseInt(m.group(1), 16); 11.920 + int color_alpha = m.group(2) != null ? (Integer.parseInt(m.group(2), 16) & 0xFF) : 0xFF; 11.921 + color = (color_alpha << 24) | color_rgb; 11.922 + } 11.923 + return color; 11.924 + } 11.925 + 11.926 + /** 11.927 + * there is no corresponding calendar on server side. time to delete this calendar on android side. 11.928 + * 11.929 + * @return 11.930 + */ 11.931 + public boolean deleteAndroidCalendar() { 11.932 + boolean Result = false; 11.933 + 11.934 + String mSelectionClause = "(" + Calendars._ID + " = ?)"; 11.935 + int calendarId = this.getAndroidCalendarId(); 11.936 + String[] mSelectionArgs = {Long.toString(calendarId)}; 11.937 + 11.938 + int CountDeleted = 0; 11.939 + try { 11.940 + CountDeleted = mProvider.delete(this.SyncAdapter(), mSelectionClause, mSelectionArgs); 11.941 + Log.i(TAG, "Calendar deleted: " + String.valueOf(calendarId)); 11.942 + this.mNotifyList.add(this.getAndroidCalendarUri()); 11.943 + Result = true; 11.944 + } catch (RemoteException e) { 11.945 + e.printStackTrace(); 11.946 + } 11.947 + Log.d(TAG, "Android Calendars deleted: " + Integer.toString(CountDeleted)); 11.948 + 11.949 + return Result; 11.950 + } 11.951 + 11.952 + /** 11.953 + * updates the android calendar 11.954 + * 11.955 + * @param calendarUri the uri of the androidCalendar 11.956 + * @param target must be from android.provider.CalendarContract.Calendars 11.957 + * @param value the new value for the target 11.958 + * @throws RemoteException 11.959 + */ 11.960 + private void updateAndroidCalendar(Uri calendarUri, String target, int value) throws RemoteException { 11.961 + ContentValues mUpdateValues = new ContentValues(); 11.962 + mUpdateValues.put(target, value); 11.963 + 11.964 + mProvider.update(asSyncAdapter(calendarUri, mAccount.name, mAccount.type), mUpdateValues, null, null); 11.965 + } 11.966 + 11.967 + /** 11.968 + * updates the android calendar 11.969 + * 11.970 + * @param calendarUri the uri of the androidCalendar 11.971 + * @param target must be from android.provider.CalendarContract.Calendars 11.972 + * @param value the new value for the target 11.973 + * @throws RemoteException 11.974 + */ 11.975 + private void updateAndroidCalendar(Uri calendarUri, String target, String value) throws RemoteException { 11.976 + ContentValues mUpdateValues = new ContentValues(); 11.977 + mUpdateValues.put(target, value); 11.978 + 11.979 + mProvider.update(asSyncAdapter(calendarUri, mAccount.name, mAccount.type), mUpdateValues, null, null); 11.980 + } 11.981 + 11.982 + /** 11.983 + * marks the android event as already handled 11.984 + * 11.985 + * @return 11.986 + * @throws RemoteException 11.987 + * @see AndroidEvent#cInternalTag 11.988 + * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 11.989 + */ 11.990 + public boolean tagAndroidEvent(AndroidEvent androidEvent) throws RemoteException { 11.991 + boolean Result = false; 11.992 + 11.993 + ContentValues values = new ContentValues(); 11.994 + //values.put(Event.INTERNALTAG, 1); 11.995 + values.put(Event.INTERNALTAG, mTagCounter); 11.996 + //values.put(Event.INTERNALTAG, String.valueOf(mTagCounter)); 11.997 + 11.998 + int RowCount = this.mProvider.update(asSyncAdapter(androidEvent.getUri(), this.mAccount.name, this.mAccount.type), values, null, null); 11.999 + //Log.v(TAG,"event tag nr: " + String.valueOf(mTagCounter)); 11.1000 + //Log.v(TAG,"Rows updated: " + String.valueOf(RowCount)); 11.1001 + 11.1002 + if (RowCount == 1) { 11.1003 + Result = true; 11.1004 + mTagCounter += 1; 11.1005 + } else { 11.1006 + Log.v(TAG, "EVENT NOT TAGGED!"); 11.1007 + } 11.1008 + 11.1009 + return Result; 11.1010 + } 11.1011 + 11.1012 + /** 11.1013 + * removes the tag of all android events 11.1014 + * 11.1015 + * @return 11.1016 + * @throws RemoteException 11.1017 + * @see AndroidEvent#cInternalTag 11.1018 + * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 11.1019 + */ 11.1020 + public int untagAndroidEvents() throws RemoteException { 11.1021 + int RowCount = 0; 11.1022 + int Steps = 100; 11.1023 + ContentValues values = new ContentValues(); 11.1024 + values.put(Event.INTERNALTAG, 0); 11.1025 + 11.1026 + for (int i = 1; i < this.mTagCounter; i = i + Steps) { 11.1027 + String mSelectionClause = "(CAST(" + Event.INTERNALTAG + " AS INT) >= ?) AND (CAST(" + Event.INTERNALTAG + " AS INT) < ?) AND (" + Events.CALENDAR_ID + " = ?)"; 11.1028 + String[] mSelectionArgs = {String.valueOf(i), String.valueOf(i + Steps), Long.toString(ContentUris 11.1029 + .parseId(this.getAndroidCalendarUri()))}; 11.1030 + RowCount += this.mProvider.update(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), values, mSelectionClause, mSelectionArgs); 11.1031 + } 11.1032 + /*String mSelectionClause = "(" + Event.INTERNALTAG + " > ?) AND (" + Events.CALENDAR_ID + " = ?)"; 11.1033 + String[] mSelectionArgs = {"0", Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; 11.1034 RowCount += this.mProvider.update(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), values, mSelectionClause, mSelectionArgs);*/ 11.1035 - 11.1036 - //Log.d(TAG, "Rows reseted: " + RowCount.toString()); 11.1037 - return RowCount; 11.1038 - } 11.1039 - /** 11.1040 - * Events not being tagged are for deletion 11.1041 - * @return 11.1042 - * @see AndroidEvent#cInternalTag 11.1043 - * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 11.1044 - * @throws RemoteException 11.1045 - */ 11.1046 - public int deleteUntaggedEvents() throws RemoteException { 11.1047 - String mSelectionClause = "(" + Event.INTERNALTAG + " < ?) AND (" + Events.CALENDAR_ID + " = ?)"; 11.1048 - String[] mSelectionArgs = {"1", Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; 11.1049 - 11.1050 - int CountDeleted = this.mProvider.delete(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), mSelectionClause, mSelectionArgs); 11.1051 - //Log.d(TAG, "Rows deleted: " + CountDeleted.toString()); 11.1052 - return CountDeleted; 11.1053 - } 11.1054 - 11.1055 - private Uri SyncAdapterCalendar() { 11.1056 - return asSyncAdapter(this.getAndroidCalendarUri(), mAccount.name, mAccount.type); 11.1057 - } 11.1058 - private Uri SyncAdapter() { 11.1059 - return asSyncAdapter(Calendars.CONTENT_URI, mAccount.name, mAccount.type); 11.1060 - } 11.1061 - private static Uri asSyncAdapter(Uri uri, String account, String accountType) { 11.1062 - return uri.buildUpon() 11.1063 - .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true") 11.1064 - .appendQueryParameter(Calendars.ACCOUNT_NAME, account) 11.1065 - .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); 11.1066 - } 11.1067 - 11.1068 - public void setAccount(Account account) { 11.1069 - this.mAccount = account; 11.1070 - } 11.1071 - public void setProvider(ContentProviderClient provider) { 11.1072 - this.mProvider = provider; 11.1073 - } 11.1074 - 11.1075 - /** 11.1076 - * general access function to ContentValues 11.1077 - * @param Item the item name from Calendars.* 11.1078 - * @return the value for the item 11.1079 - */ 11.1080 - private String getContentValueAsString(String Item) { 11.1081 - String Result = ""; 11.1082 - if (this.ContentValues.containsKey(Item)) 11.1083 - Result = this.ContentValues.getAsString(Item); 11.1084 - return Result; 11.1085 - } 11.1086 - /** 11.1087 - * general access function to ContentValues 11.1088 - * @param Item the item name from Calendars.* 11.1089 - * @return the value for the item 11.1090 - */ 11.1091 - private int getContentValueAsInt(String Item) { 11.1092 - int Result = 0; 11.1093 - if (this.ContentValues.containsKey(Item)) 11.1094 - Result = this.ContentValues.getAsInteger(Item); 11.1095 - return Result; 11.1096 - } 11.1097 - 11.1098 - /** 11.1099 - * general access function to ContentValues 11.1100 - * @param Item the item name from Calendars.* 11.1101 - * @param Value the value for the item 11.1102 - * @return success of this function 11.1103 - */ 11.1104 - private boolean setContentValueAsString(String Item, String Value) { 11.1105 - boolean Result = false; 11.1106 - 11.1107 - if (this.ContentValues.containsKey(Item)) 11.1108 - this.ContentValues.remove(Item); 11.1109 - this.ContentValues.put(Item, Value); 11.1110 - 11.1111 - return Result; 11.1112 - } 11.1113 - 11.1114 - /** 11.1115 - * general access function to ContentValues 11.1116 - * @param Item the item name from Calendars.* 11.1117 - * @param Value the value for the item 11.1118 - * @return success of this function 11.1119 - */ 11.1120 - private boolean setContentValueAsInt(String Item, int Value) { 11.1121 - boolean Result = false; 11.1122 - 11.1123 - if (this.ContentValues.containsKey(Item)) 11.1124 - this.ContentValues.remove(Item); 11.1125 - this.ContentValues.put(Item, Value); 11.1126 - 11.1127 - return Result; 11.1128 - } 11.1129 - 11.1130 - public ArrayList<Uri> getNotifyList() { 11.1131 - return this.mNotifyList; 11.1132 - } 11.1133 11.1134 - public ArrayList<CalendarEvent> getCalendarEvents() { 11.1135 - return this.mCalendarEvents; 11.1136 - } 11.1137 - 11.1138 - public boolean readCalendarEvents(CaldavFacade facade) { 11.1139 - boolean Result = false; 11.1140 - 11.1141 - try { 11.1142 - this.mCalendarEvents = facade.getCalendarEvents(this); 11.1143 - Result = true; 11.1144 - } catch (ClientProtocolException e) { 11.1145 - e.printStackTrace(); 11.1146 - Result = false; 11.1147 - } catch (URISyntaxException e) { 11.1148 - e.printStackTrace(); 11.1149 - Result = false; 11.1150 - } catch (IOException e) { 11.1151 - e.printStackTrace(); 11.1152 - Result = false; 11.1153 - } catch (ParserConfigurationException e) { 11.1154 - e.printStackTrace(); 11.1155 - Result = false; 11.1156 - } catch (SAXException e) { 11.1157 - e.printStackTrace(); 11.1158 - Result = false; 11.1159 - } 11.1160 - 11.1161 - return Result; 11.1162 - } 11.1163 - 11.1164 + //Log.d(TAG, "Rows reseted: " + RowCount.toString()); 11.1165 + return RowCount; 11.1166 + } 11.1167 + 11.1168 + /** 11.1169 + * Events not being tagged are for deletion 11.1170 + * 11.1171 + * @return 11.1172 + * @throws RemoteException 11.1173 + * @see AndroidEvent#cInternalTag 11.1174 + * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) 11.1175 + */ 11.1176 + public int deleteUntaggedEvents() throws RemoteException { 11.1177 + String mSelectionClause = "(" + Event.INTERNALTAG + " < ?) AND (" + Events.CALENDAR_ID + " = ?)"; 11.1178 + String[] mSelectionArgs = {"1", Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; 11.1179 + 11.1180 + int CountDeleted = this.mProvider.delete(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), mSelectionClause, mSelectionArgs); 11.1181 + //Log.d(TAG, "Rows deleted: " + CountDeleted.toString()); 11.1182 + return CountDeleted; 11.1183 + } 11.1184 + 11.1185 + private Uri SyncAdapterCalendar() { 11.1186 + return asSyncAdapter(this.getAndroidCalendarUri(), mAccount.name, mAccount.type); 11.1187 + } 11.1188 + 11.1189 + private Uri SyncAdapter() { 11.1190 + return asSyncAdapter(Calendars.CONTENT_URI, mAccount.name, mAccount.type); 11.1191 + } 11.1192 + 11.1193 + private static Uri asSyncAdapter(Uri uri, String account, String accountType) { 11.1194 + return uri.buildUpon() 11.1195 + .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER, "true") 11.1196 + .appendQueryParameter(Calendars.ACCOUNT_NAME, account) 11.1197 + .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); 11.1198 + } 11.1199 + 11.1200 + public void setAccount(Account account) { 11.1201 + this.mAccount = account; 11.1202 + } 11.1203 + 11.1204 + public void setProvider(ContentProviderClient provider) { 11.1205 + this.mProvider = provider; 11.1206 + } 11.1207 + 11.1208 + /** 11.1209 + * general access function to ContentValues 11.1210 + * 11.1211 + * @param Item the item name from Calendars.* 11.1212 + * @return the value for the item 11.1213 + */ 11.1214 + private String getContentValueAsString(String Item) { 11.1215 + String Result = ""; 11.1216 + if (this.ContentValues.containsKey(Item)) 11.1217 + Result = this.ContentValues.getAsString(Item); 11.1218 + return Result; 11.1219 + } 11.1220 + 11.1221 + /** 11.1222 + * general access function to ContentValues 11.1223 + * 11.1224 + * @param Item the item name from Calendars.* 11.1225 + * @return the value for the item 11.1226 + */ 11.1227 + private int getContentValueAsInt(String Item) { 11.1228 + int Result = 0; 11.1229 + if (this.ContentValues.containsKey(Item)) 11.1230 + Result = this.ContentValues.getAsInteger(Item); 11.1231 + return Result; 11.1232 + } 11.1233 + 11.1234 + /** 11.1235 + * general access function to ContentValues 11.1236 + * 11.1237 + * @param Item the item name from Calendars.* 11.1238 + * @param Value the value for the item 11.1239 + * @return success of this function 11.1240 + */ 11.1241 + private boolean setContentValueAsString(String Item, String Value) { 11.1242 + boolean Result = false; 11.1243 + 11.1244 + if (this.ContentValues.containsKey(Item)) 11.1245 + this.ContentValues.remove(Item); 11.1246 + this.ContentValues.put(Item, Value); 11.1247 + 11.1248 + return Result; 11.1249 + } 11.1250 + 11.1251 + /** 11.1252 + * general access function to ContentValues 11.1253 + * 11.1254 + * @param Item the item name from Calendars.* 11.1255 + * @param Value the value for the item 11.1256 + * @return success of this function 11.1257 + */ 11.1258 + private boolean setContentValueAsInt(String Item, int Value) { 11.1259 + boolean Result = false; 11.1260 + 11.1261 + if (this.ContentValues.containsKey(Item)) 11.1262 + this.ContentValues.remove(Item); 11.1263 + this.ContentValues.put(Item, Value); 11.1264 + 11.1265 + return Result; 11.1266 + } 11.1267 + 11.1268 + public ArrayList<Uri> getNotifyList() { 11.1269 + return this.mNotifyList; 11.1270 + } 11.1271 + 11.1272 + public ArrayList<CalendarEvent> getCalendarEvents() { 11.1273 + return this.mCalendarEvents; 11.1274 + } 11.1275 + 11.1276 + public boolean readCalendarEvents(CaldavFacade facade) { 11.1277 + boolean Result = false; 11.1278 + 11.1279 + try { 11.1280 + this.mCalendarEvents = facade.getCalendarEvents(this); 11.1281 + Result = true; 11.1282 + } catch (ClientProtocolException e) { 11.1283 + e.printStackTrace(); 11.1284 + Result = false; 11.1285 + } catch (URISyntaxException e) { 11.1286 + e.printStackTrace(); 11.1287 + Result = false; 11.1288 + } catch (IOException e) { 11.1289 + e.printStackTrace(); 11.1290 + Result = false; 11.1291 + } catch (ParserConfigurationException e) { 11.1292 + e.printStackTrace(); 11.1293 + Result = false; 11.1294 + } catch (SAXException e) { 11.1295 + e.printStackTrace(); 11.1296 + Result = false; 11.1297 + } 11.1298 + 11.1299 + return Result; 11.1300 + } 11.1301 + 11.1302 }
12.1 --- a/src/org/gege/caldavsyncadapter/caldav/http/HttpReport.java Tue Feb 10 21:55:00 2015 +0100 12.2 +++ b/src/org/gege/caldavsyncadapter/caldav/http/HttpReport.java Tue Feb 10 22:40:00 2015 +0100 12.3 @@ -26,6 +26,8 @@ 12.4 12.5 public class HttpReport extends HttpEntityEnclosingRequestBase implements HttpUriRequest { 12.6 12.7 + public static final String USER_DATA_TRUST_ALL_KEY = "USER_DATA_TRUSTALL_KEY"; 12.8 + 12.9 @Override 12.10 public String getMethod() { 12.11 return "REPORT";
13.1 --- a/src/org/gege/caldavsyncadapter/syncadapter/SyncAdapter.java Tue Feb 10 21:55:00 2015 +0100 13.2 +++ b/src/org/gege/caldavsyncadapter/syncadapter/SyncAdapter.java Tue Feb 10 22:40:00 2015 +0100 13.3 @@ -1,6 +1,6 @@ 13.4 /** 13.5 * Copyright (c) 2012-2013, Gerald Garcia, David Wiesner, Timo Berger 13.6 - * 13.7 + * 13.8 * This file is part of Andoid Caldav Sync Adapter Free. 13.9 * 13.10 * Andoid Caldav Sync Adapter Free is free software: you can redistribute 13.11 @@ -16,36 +16,11 @@ 13.12 * You should have received a copy of the GNU General Public License 13.13 * along with Andoid Caldav Sync Adapter Free. 13.14 * If not, see <http://www.gnu.org/licenses/>. 13.15 - * 13.16 + * 13.17 */ 13.18 13.19 package org.gege.caldavsyncadapter.syncadapter; 13.20 13.21 -import java.io.IOException; 13.22 -import java.net.URI; 13.23 -//import java.net.MalformedURLException; 13.24 -import java.net.URISyntaxException; 13.25 -import java.util.ArrayList; 13.26 -//import java.security.GeneralSecurityException; 13.27 - 13.28 -import javax.xml.parsers.ParserConfigurationException; 13.29 - 13.30 -import net.fortuna.ical4j.data.ParserException; 13.31 - 13.32 -import org.apache.http.ParseException; 13.33 -import org.apache.http.client.ClientProtocolException; 13.34 -import org.gege.caldavsyncadapter.Event; 13.35 -import org.gege.caldavsyncadapter.android.entities.AndroidEvent; 13.36 -import org.gege.caldavsyncadapter.authenticator.AuthenticatorActivity; 13.37 -import org.gege.caldavsyncadapter.caldav.CaldavFacade; 13.38 -import org.gege.caldavsyncadapter.caldav.CaldavProtocolException; 13.39 -import org.gege.caldavsyncadapter.caldav.entities.DavCalendar; 13.40 -import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent; 13.41 -import org.gege.caldavsyncadapter.caldav.entities.CalendarList; 13.42 -import org.gege.caldavsyncadapter.caldav.entities.DavCalendar.CalendarSource; 13.43 -import org.gege.caldavsyncadapter.syncadapter.notifications.NotificationsHelper; 13.44 -import org.xml.sax.SAXException; 13.45 - 13.46 import android.accounts.Account; 13.47 import android.accounts.AccountManager; 13.48 import android.content.AbstractThreadedSyncAdapter; 13.49 @@ -66,18 +41,45 @@ 13.50 import android.provider.CalendarContract.Reminders; 13.51 import android.util.Log; 13.52 13.53 +import net.fortuna.ical4j.data.ParserException; 13.54 + 13.55 +import org.apache.http.ParseException; 13.56 +import org.apache.http.client.ClientProtocolException; 13.57 +import org.gege.caldavsyncadapter.Constants; 13.58 +import org.gege.caldavsyncadapter.Event; 13.59 +import org.gege.caldavsyncadapter.android.entities.AndroidEvent; 13.60 +import org.gege.caldavsyncadapter.authenticator.AuthenticatorActivity; 13.61 +import org.gege.caldavsyncadapter.caldav.CaldavFacade; 13.62 +import org.gege.caldavsyncadapter.caldav.CaldavProtocolException; 13.63 +import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent; 13.64 +import org.gege.caldavsyncadapter.caldav.entities.CalendarList; 13.65 +import org.gege.caldavsyncadapter.caldav.entities.DavCalendar; 13.66 +import org.gege.caldavsyncadapter.caldav.entities.DavCalendar.CalendarSource; 13.67 +import org.gege.caldavsyncadapter.syncadapter.notifications.NotificationsHelper; 13.68 +import org.xml.sax.SAXException; 13.69 + 13.70 +import java.io.IOException; 13.71 +import java.net.URI; 13.72 +import java.net.URISyntaxException; 13.73 +import java.util.ArrayList; 13.74 + 13.75 +import javax.xml.parsers.ParserConfigurationException; 13.76 + 13.77 +//import java.net.MalformedURLException; 13.78 +//import java.security.GeneralSecurityException; 13.79 + 13.80 public class SyncAdapter extends AbstractThreadedSyncAdapter { 13.81 13.82 - private static final String TAG = "SyncAdapter"; 13.83 - private AccountManager mAccountManager; 13.84 - private String mVersion = ""; 13.85 - private int mCountPerformSync = 0; 13.86 - private int mCountSyncCanceled = 0; 13.87 - private int mCountProviderFailed = 0; 13.88 - 13.89 - private int mCountProviderFailedMax = 3; 13.90 + private static final String TAG = "SyncAdapter"; 13.91 + private AccountManager mAccountManager; 13.92 + private String mVersion = ""; 13.93 + private int mCountPerformSync = 0; 13.94 + private int mCountSyncCanceled = 0; 13.95 + private int mCountProviderFailed = 0; 13.96 + 13.97 + private int mCountProviderFailedMax = 3; 13.98 // private Context mContext; 13.99 - 13.100 + 13.101 13.102 /* private static final String[] CALENDAR_PROJECTION = new String[] { 13.103 Calendars._ID, // 0 13.104 @@ -102,81 +104,87 @@ 13.105 Events.CALENDAR_ID 13.106 }; 13.107 */ 13.108 - 13.109 - // ignore same CTag 13.110 - //private static final boolean FORCE_SYNCHRONIZE = false; 13.111 - // drop all calendar before synchro 13.112 - //private static final boolean DROP_CALENDAR_EVENTS = false; 13.113 - 13.114 - public SyncAdapter(Context context, boolean autoInitialize) { 13.115 - super(context, autoInitialize); 13.116 - //android.os.Debug.waitForDebugger(); 13.117 - mAccountManager = AccountManager.get(context); 13.118 - try { 13.119 - mVersion = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; 13.120 - } catch (NameNotFoundException e) { 13.121 - e.printStackTrace(); 13.122 - } 13.123 + 13.124 + // ignore same CTag 13.125 + //private static final boolean FORCE_SYNCHRONIZE = false; 13.126 + // drop all calendar before synchro 13.127 + //private static final boolean DROP_CALENDAR_EVENTS = false; 13.128 + 13.129 + public SyncAdapter(Context context, boolean autoInitialize) { 13.130 + super(context, autoInitialize); 13.131 + //android.os.Debug.waitForDebugger(); 13.132 + mAccountManager = AccountManager.get(context); 13.133 + try { 13.134 + mVersion = context.getPackageManager() 13.135 + .getPackageInfo(context.getPackageName(), 0).versionName; 13.136 + } catch (NameNotFoundException e) { 13.137 + e.printStackTrace(); 13.138 + } 13.139 // mContext = context; 13.140 - } 13.141 + } 13.142 13.143 - @Override 13.144 - public void onPerformSync(Account account, Bundle extras, String authority, 13.145 - ContentProviderClient provider, SyncResult syncResult) { 13.146 - boolean bolError = false; 13.147 - 13.148 - String url = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_URL_KEY); 13.149 - this.mCountPerformSync += 1; 13.150 - Log.v(TAG, "onPerformSync() count:" + String.valueOf(this.mCountPerformSync) + " on " + account.name + " with URL " + url); 13.151 + @Override 13.152 + public void onPerformSync(Account account, Bundle extras, String authority, 13.153 + ContentProviderClient provider, SyncResult syncResult) { 13.154 + boolean bolError = false; 13.155 13.156 - CalendarList serverCalList; 13.157 - 13.158 - CalendarList androidCalList = new CalendarList(account, provider, CalendarSource.Android, url); 13.159 - androidCalList.readCalendarFromClient(); 13.160 - ArrayList<Uri> notifyList = new ArrayList<Uri>(); 13.161 + String url = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_URL_KEY); 13.162 + String trust = mAccountManager.getUserData(account, Constants.USER_DATA_TRUST_ALL_KEY); 13.163 + this.mCountPerformSync += 1; 13.164 + Log.v(TAG, "onPerformSync() count:" + String.valueOf(this.mCountPerformSync) + " on " + account.name + " with URL " + url); 13.165 13.166 - try { 13.167 - String Username = ""; 13.168 - String UserDataVersion = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_VERSION); 13.169 - if (UserDataVersion == null) { 13.170 - Username = account.name; 13.171 - } else { 13.172 - Username = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_USERNAME); 13.173 - } 13.174 + CalendarList serverCalList; 13.175 13.176 - CaldavFacade facade = new CaldavFacade(Username, mAccountManager.getPassword(account), url); 13.177 - facade.setAccount(account); 13.178 - facade.setProvider(provider); 13.179 - facade.setVersion(mVersion); 13.180 - serverCalList = facade.getCalendarList(this.getContext()); 13.181 - //String davProperties = facade.getLastDav(); 13.182 - Log.i(TAG, String.valueOf(androidCalList.getCalendarList().size()) + " calendars found at android"); 13.183 - 13.184 - for (DavCalendar serverCalendar : serverCalList.getCalendarList()) { 13.185 - Log.i(TAG, "Detected calendar name=" + serverCalendar.getCalendarDisplayName() + " URI=" + serverCalendar.getURI()); 13.186 + CalendarList androidCalList = new CalendarList(account, provider, CalendarSource.Android, url); 13.187 + androidCalList.readCalendarFromClient(); 13.188 + ArrayList<Uri> notifyList = new ArrayList<Uri>(); 13.189 13.190 - Uri androidCalendarUri = serverCalendar.checkAndroidCalendarList(androidCalList, this.getContext()); 13.191 + try { 13.192 + String Username = ""; 13.193 + String UserDataVersion = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_VERSION); 13.194 + if (UserDataVersion == null) { 13.195 + Username = account.name; 13.196 + } else { 13.197 + Username = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_USERNAME); 13.198 + } 13.199 13.200 - // check if the adapter was able to get an existing calendar or create a new one 13.201 - if (androidCalendarUri != null) { 13.202 - // the provider seems to work correct, reset the counter 13.203 - mCountProviderFailed = 0; 13.204 - DavCalendar androidCalendar = androidCalList.getCalendarByAndroidUri(androidCalendarUri); 13.205 - 13.206 - //if ((FORCE_SYNCHRONIZE) || (androidCalendar.getcTag() == null) || (!androidCalendar.getcTag().equals(serverCalendar.getcTag()))) { 13.207 - if ((androidCalendar.getcTag() == null) || (!androidCalendar.getcTag().equals(serverCalendar.getcTag()))) { 13.208 - Log.d(TAG, "CTag has changed, something to synchronise"); 13.209 - if (serverCalendar.readCalendarEvents(facade)) { 13.210 - this.synchroniseEvents(androidCalendar, serverCalendar, syncResult.stats, notifyList); 13.211 + CaldavFacade facade = new CaldavFacade(Username, mAccountManager.getPassword(account), url, trust); 13.212 + facade.setAccount(account); 13.213 + facade.setProvider(provider); 13.214 + facade.setVersion(mVersion); 13.215 + serverCalList = facade.getCalendarList(this.getContext()); 13.216 + //String davProperties = facade.getLastDav(); 13.217 + Log.i(TAG, String.valueOf(androidCalList.getCalendarList() 13.218 + .size()) + " calendars found at android"); 13.219 13.220 - Log.d(TAG, "Updating stored CTag"); 13.221 - //serverCalendar.updateAndroidCalendar(androidCalendarUri, Calendar.CTAG, serverCalendar.getcTag()); 13.222 - androidCalendar.setCTag(serverCalendar.getcTag(), true); 13.223 - } else { 13.224 - Log.d(TAG, "unable to read events from server calendar"); 13.225 - } 13.226 - } else { 13.227 - Log.d(TAG, "CTag has not changed, nothing to do"); 13.228 + for (DavCalendar serverCalendar : serverCalList.getCalendarList()) { 13.229 + Log.i(TAG, "Detected calendar name=" + serverCalendar.getCalendarDisplayName() + " URI=" + serverCalendar 13.230 + .getURI()); 13.231 + 13.232 + Uri androidCalendarUri = serverCalendar.checkAndroidCalendarList(androidCalList, this 13.233 + .getContext()); 13.234 + 13.235 + // check if the adapter was able to get an existing calendar or create a new one 13.236 + if (androidCalendarUri != null) { 13.237 + // the provider seems to work correct, reset the counter 13.238 + mCountProviderFailed = 0; 13.239 + DavCalendar androidCalendar = androidCalList.getCalendarByAndroidUri(androidCalendarUri); 13.240 + 13.241 + //if ((FORCE_SYNCHRONIZE) || (androidCalendar.getcTag() == null) || (!androidCalendar.getcTag().equals(serverCalendar.getcTag()))) { 13.242 + if ((androidCalendar.getcTag() == null) || (!androidCalendar.getcTag() 13.243 + .equals(serverCalendar.getcTag()))) { 13.244 + Log.d(TAG, "CTag has changed, something to synchronise"); 13.245 + if (serverCalendar.readCalendarEvents(facade)) { 13.246 + this.synchroniseEvents(androidCalendar, serverCalendar, syncResult.stats, notifyList); 13.247 + 13.248 + Log.d(TAG, "Updating stored CTag"); 13.249 + //serverCalendar.updateAndroidCalendar(androidCalendarUri, Calendar.CTAG, serverCalendar.getcTag()); 13.250 + androidCalendar.setCTag(serverCalendar.getcTag(), true); 13.251 + } else { 13.252 + Log.d(TAG, "unable to read events from server calendar"); 13.253 + } 13.254 + } else { 13.255 + Log.d(TAG, "CTag has not changed, nothing to do"); 13.256 13.257 /* this is unnecessary. "SkippedEntries" are: 13.258 * Counter for tracking how many entries, either from the server or the local store, 13.259 @@ -196,52 +204,53 @@ 13.260 int count = countCursor.getInt(0); 13.261 syncResult.stats.numSkippedEntries += count; 13.262 countCursor.close();*/ 13.263 - 13.264 - } 13.265 - 13.266 - this.checkDirtyAndroidEvents(provider, account, androidCalendarUri, facade, serverCalendar.getURI(), syncResult.stats, notifyList); 13.267 - } else { 13.268 - // this happens if the data provider failes to get an existing or create a new calendar 13.269 - mCountProviderFailed += 1; 13.270 - Log.e(TAG, "failed to get an existing or create a new calendar"); 13.271 - syncResult.stats.numIoExceptions += 1; 13.272 - if (mCountProviderFailed >= mCountProviderFailedMax) { 13.273 - // see issue #96 13.274 - NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (provider failed)", "are you using CyanogenMod in Incognito Mode?"); 13.275 - } else { 13.276 - NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (provider failed)", "the provider failed to get an existing or create a new calendar"); 13.277 - } 13.278 - bolError = true; 13.279 - } 13.280 - } 13.281 - 13.282 - if (!bolError) { 13.283 - // check whether a calendar is not synced -> delete it at android 13.284 - androidCalList.deleteCalendarOnClientSideOnly(this.getContext()); 13.285 - } 13.286 - 13.287 - // notify the ContentResolver 13.288 - for (Uri uri : androidCalList.getNotifyList()) { 13.289 - this.getContext().getContentResolver().notifyChange(uri, null); 13.290 - } 13.291 - for (Uri uri : serverCalList.getNotifyList()) { 13.292 - this.getContext().getContentResolver().notifyChange(uri, null); 13.293 - } 13.294 - for (Uri uri : notifyList) { 13.295 - this.getContext().getContentResolver().notifyChange(uri, null); 13.296 - } 13.297 - 13.298 - //Log.i(TAG,"Statistiks for Calendar: " + serverCalendar.getURI().toString()); 13.299 - //Log.i(TAG,"Statistiks for AndroidCalendar: " + androidCalendar.getAndroidCalendarUri().toString()); 13.300 - Log.i(TAG,"Entries: " + String.valueOf(syncResult.stats.numEntries)); 13.301 - Log.i(TAG,"Rows inserted: " + String.valueOf(syncResult.stats.numInserts)); 13.302 - Log.i(TAG,"Rows updated: " + String.valueOf(syncResult.stats.numUpdates)); 13.303 - Log.i(TAG,"Rows deleted: " + String.valueOf(syncResult.stats.numDeletes)); 13.304 - Log.i(TAG,"Rows skipped: " + String.valueOf(syncResult.stats.numSkippedEntries)); 13.305 - Log.i(TAG,"Io Exceptions: " + String.valueOf(syncResult.stats.numIoExceptions)); 13.306 - Log.i(TAG,"Parse Exceptions: " + String.valueOf(syncResult.stats.numParseExceptions)); 13.307 - Log.i(TAG,"Auth Exceptions: " + String.valueOf(syncResult.stats.numAuthExceptions)); 13.308 - Log.i(TAG,"Conflict Detected Exceptions: " + String.valueOf(syncResult.stats.numConflictDetectedExceptions)); 13.309 + 13.310 + } 13.311 + 13.312 + this.checkDirtyAndroidEvents(provider, account, androidCalendarUri, facade, serverCalendar 13.313 + .getURI(), syncResult.stats, notifyList); 13.314 + } else { 13.315 + // this happens if the data provider failes to get an existing or create a new calendar 13.316 + mCountProviderFailed += 1; 13.317 + Log.e(TAG, "failed to get an existing or create a new calendar"); 13.318 + syncResult.stats.numIoExceptions += 1; 13.319 + if (mCountProviderFailed >= mCountProviderFailedMax) { 13.320 + // see issue #96 13.321 + NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (provider failed)", "are you using CyanogenMod in Incognito Mode?"); 13.322 + } else { 13.323 + NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (provider failed)", "the provider failed to get an existing or create a new calendar"); 13.324 + } 13.325 + bolError = true; 13.326 + } 13.327 + } 13.328 + 13.329 + if (!bolError) { 13.330 + // check whether a calendar is not synced -> delete it at android 13.331 + androidCalList.deleteCalendarOnClientSideOnly(this.getContext()); 13.332 + } 13.333 + 13.334 + // notify the ContentResolver 13.335 + for (Uri uri : androidCalList.getNotifyList()) { 13.336 + this.getContext().getContentResolver().notifyChange(uri, null); 13.337 + } 13.338 + for (Uri uri : serverCalList.getNotifyList()) { 13.339 + this.getContext().getContentResolver().notifyChange(uri, null); 13.340 + } 13.341 + for (Uri uri : notifyList) { 13.342 + this.getContext().getContentResolver().notifyChange(uri, null); 13.343 + } 13.344 + 13.345 + //Log.i(TAG,"Statistiks for Calendar: " + serverCalendar.getURI().toString()); 13.346 + //Log.i(TAG,"Statistiks for AndroidCalendar: " + androidCalendar.getAndroidCalendarUri().toString()); 13.347 + Log.i(TAG, "Entries: " + String.valueOf(syncResult.stats.numEntries)); 13.348 + Log.i(TAG, "Rows inserted: " + String.valueOf(syncResult.stats.numInserts)); 13.349 + Log.i(TAG, "Rows updated: " + String.valueOf(syncResult.stats.numUpdates)); 13.350 + Log.i(TAG, "Rows deleted: " + String.valueOf(syncResult.stats.numDeletes)); 13.351 + Log.i(TAG, "Rows skipped: " + String.valueOf(syncResult.stats.numSkippedEntries)); 13.352 + Log.i(TAG, "Io Exceptions: " + String.valueOf(syncResult.stats.numIoExceptions)); 13.353 + Log.i(TAG, "Parse Exceptions: " + String.valueOf(syncResult.stats.numParseExceptions)); 13.354 + Log.i(TAG, "Auth Exceptions: " + String.valueOf(syncResult.stats.numAuthExceptions)); 13.355 + Log.i(TAG, "Conflict Detected Exceptions: " + String.valueOf(syncResult.stats.numConflictDetectedExceptions)); 13.356 13.357 /*} catch (final AuthenticatorException e) { 13.358 syncResult.stats.numParseExceptions++; 13.359 @@ -260,119 +269,125 @@ 13.360 } catch (final ParseException e) { 13.361 syncResult.stats.numParseExceptions++; 13.362 Log.e(TAG, "ParseException", e); 13.363 - NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (parsing)", e.getMessage()); 13.364 + NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (parsing)", e 13.365 + .getMessage()); 13.366 //NotificationsHelper.getCurrentSyncLog().addException(e); 13.367 /*} catch (final JSONException e) { 13.368 syncResult.stats.numParseExceptions++; 13.369 Log.e(TAG, "JSONException", e);*/ 13.370 - } catch (Exception e) { 13.371 - Log.e(TAG, "Updating calendar exception " + e.getClass().getName(), e); 13.372 + } catch (Exception e) { 13.373 + Log.e(TAG, "Updating calendar exception " + e.getClass().getName(), e); 13.374 syncResult.stats.numParseExceptions++; 13.375 - NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (general)", e.getMessage()); 13.376 + NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (general)", e 13.377 + .getMessage()); 13.378 //NotificationsHelper.getCurrentSyncLog().addException(e); 13.379 - //throw new RuntimeException(e); 13.380 - } 13.381 - } 13.382 + //throw new RuntimeException(e); 13.383 + } 13.384 + } 13.385 13.386 - public void onSyncCanceled () { 13.387 - //TODO: implement SyncCanceled 13.388 - this.mCountSyncCanceled += 1; 13.389 - Log.v(TAG, "onSyncCanceled() count:" + String.valueOf(this.mCountSyncCanceled)); 13.390 - } 13.391 + public void onSyncCanceled() { 13.392 + //TODO: implement SyncCanceled 13.393 + this.mCountSyncCanceled += 1; 13.394 + Log.v(TAG, "onSyncCanceled() count:" + String.valueOf(this.mCountSyncCanceled)); 13.395 + } 13.396 13.397 - 13.398 - /** 13.399 - * both calender event and android event have been found. 13.400 - * server wins always at the moment. 13.401 - * @param androidCalendar 13.402 - * @param serverCalendar 13.403 - * @param stats 13.404 - * @param notifyList 13.405 - * @throws ClientProtocolException 13.406 - * @throws URISyntaxException 13.407 - * @throws IOException 13.408 - * @throws ParserConfigurationException 13.409 - * @throws SAXException 13.410 - * @throws RemoteException 13.411 - * @throws CaldavProtocolException 13.412 - * @throws ParserException 13.413 - * @see SyncAdapter#updateAndroidEvent(ContentProviderClient, Account, AndroidEvent, CalendarEvent) 13.414 - * @see SyncAdapter#tagAndroidEvent(ContentProviderClient, Account, AndroidEvent) 13.415 - * @see SyncAdapter#untagAndroidEvents(ContentProviderClient, Account, Uri) 13.416 - * @see SyncAdapter#deleteUntaggedEvents(ContentProviderClient, Account, Uri) 13.417 - */ 13.418 - private void synchroniseEvents( 13.419 - DavCalendar androidCalendar, 13.420 - DavCalendar serverCalendar, 13.421 - SyncStats stats, 13.422 - ArrayList<Uri> notifyList 13.423 - ) throws ClientProtocolException, URISyntaxException, IOException, ParserConfigurationException, SAXException, RemoteException, CaldavProtocolException, ParserException { 13.424 + 13.425 + /** 13.426 + * both calender event and android event have been found. 13.427 + * server wins always at the moment. 13.428 + * 13.429 + * @param androidCalendar 13.430 + * @param serverCalendar 13.431 + * @param stats 13.432 + * @param notifyList 13.433 + * @throws ClientProtocolException 13.434 + * @throws URISyntaxException 13.435 + * @throws IOException 13.436 + * @throws ParserConfigurationException 13.437 + * @throws SAXException 13.438 + * @throws RemoteException 13.439 + * @throws CaldavProtocolException 13.440 + * @throws ParserException 13.441 + * @see SyncAdapter#updateAndroidEvent(ContentProviderClient, Account, AndroidEvent, CalendarEvent) 13.442 + * @see SyncAdapter#tagAndroidEvent(ContentProviderClient, Account, AndroidEvent) 13.443 + * @see SyncAdapter#untagAndroidEvents(ContentProviderClient, Account, Uri) 13.444 + * @see SyncAdapter#deleteUntaggedEvents(ContentProviderClient, Account, Uri) 13.445 + */ 13.446 + private void synchroniseEvents( 13.447 + DavCalendar androidCalendar, 13.448 + DavCalendar serverCalendar, 13.449 + SyncStats stats, 13.450 + ArrayList<Uri> notifyList 13.451 + ) throws ClientProtocolException, URISyntaxException, IOException, ParserConfigurationException, SAXException, RemoteException, CaldavProtocolException, ParserException { 13.452 13.453 /*if (DROP_CALENDAR_EVENTS) { 13.454 dropAllEvents(account, provider, androidCalendar.getAndroidCalendarUri()); 13.455 }*/ 13.456 - 13.457 - int rowInsert = 0; 13.458 - int rowUpdate = 0; 13.459 - int rowTag = 0; 13.460 - int rowDelete = 0; 13.461 - int rowUntag = 0; 13.462 - int rowSkip = 0; 13.463 - 13.464 - for (CalendarEvent calendarEvent : serverCalendar.getCalendarEvents()) { 13.465 - try { 13.466 - AndroidEvent androidEvent = calendarEvent.getAndroidEvent(androidCalendar); 13.467 - 13.468 - Log.i(TAG, "Event " + calendarEvent.getUri().toString()+ " androidUri="+androidEvent); 13.469 - 13.470 - if (androidEvent == null) { 13.471 + 13.472 + int rowInsert = 0; 13.473 + int rowUpdate = 0; 13.474 + int rowTag = 0; 13.475 + int rowDelete = 0; 13.476 + int rowUntag = 0; 13.477 + int rowSkip = 0; 13.478 + 13.479 + for (CalendarEvent calendarEvent : serverCalendar.getCalendarEvents()) { 13.480 + try { 13.481 + AndroidEvent androidEvent = calendarEvent.getAndroidEvent(androidCalendar); 13.482 + 13.483 + Log.i(TAG, "Event " + calendarEvent.getUri() 13.484 + .toString() + " androidUri=" + androidEvent); 13.485 + 13.486 + if (androidEvent == null) { 13.487 /* new android event */ 13.488 - if (calendarEvent.createAndroidEvent(androidCalendar)) { 13.489 - rowInsert += 1; 13.490 - androidEvent = calendarEvent.getAndroidEvent(androidCalendar); 13.491 - notifyList.add(androidEvent.getUri()); 13.492 - } else { 13.493 - rowSkip += 1; 13.494 - } 13.495 - } else { 13.496 + if (calendarEvent.createAndroidEvent(androidCalendar)) { 13.497 + rowInsert += 1; 13.498 + androidEvent = calendarEvent.getAndroidEvent(androidCalendar); 13.499 + notifyList.add(androidEvent.getUri()); 13.500 + } else { 13.501 + rowSkip += 1; 13.502 + } 13.503 + } else { 13.504 /* the android exists */ 13.505 - String androidETag = androidEvent.getETag(); 13.506 - if (androidETag == null) 13.507 - androidETag = ""; 13.508 - Log.d(TAG, "Event compare: " + androidETag + " <> " + calendarEvent.getETag().toString()); 13.509 - if ((androidEvent.getETag() == null) || (!androidETag.equals(calendarEvent.getETag()))) { 13.510 + String androidETag = androidEvent.getETag(); 13.511 + if (androidETag == null) 13.512 + androidETag = ""; 13.513 + Log.d(TAG, "Event compare: " + androidETag + " <> " + calendarEvent.getETag() 13.514 + .toString()); 13.515 + if ((androidEvent.getETag() == null) || (!androidETag.equals(calendarEvent.getETag()))) { 13.516 /* the android event is getting updated */ 13.517 - if (calendarEvent.updateAndroidEvent(androidEvent)) { 13.518 - rowUpdate += 1; 13.519 - notifyList.add(androidEvent.getUri()); 13.520 - } else { 13.521 - rowSkip += 1; 13.522 - } 13.523 - } 13.524 - } 13.525 - if (androidEvent != null) 13.526 - //if (androidEvent.tagAndroidEvent()) 13.527 - if (androidCalendar.tagAndroidEvent(androidEvent)) 13.528 - rowTag += 1; 13.529 - 13.530 - 13.531 - } catch (ParserException ex) { 13.532 - Log.e(TAG, "Parser exception", ex); 13.533 - stats.numParseExceptions++; 13.534 + if (calendarEvent.updateAndroidEvent(androidEvent)) { 13.535 + rowUpdate += 1; 13.536 + notifyList.add(androidEvent.getUri()); 13.537 + } else { 13.538 + rowSkip += 1; 13.539 + } 13.540 + } 13.541 + } 13.542 + if (androidEvent != null) 13.543 + //if (androidEvent.tagAndroidEvent()) 13.544 + if (androidCalendar.tagAndroidEvent(androidEvent)) 13.545 + rowTag += 1; 13.546 13.547 - NotificationsHelper.signalSyncErrors(getContext(), "Caldav sync error (parsing)", ex.getMessage()); 13.548 - //NotificationsHelper.getCurrentSyncLog().addException(ex); 13.549 - } catch (CaldavProtocolException ex) { 13.550 - Log.e(TAG, "Caldav exception", ex); 13.551 - stats.numParseExceptions++; 13.552 13.553 - NotificationsHelper.signalSyncErrors(getContext(), "Caldav sync error (caldav)", ex.getMessage()); 13.554 - //NotificationsHelper.getCurrentSyncLog().addException(ex); 13.555 - } 13.556 - } 13.557 - 13.558 - rowDelete = androidCalendar.deleteUntaggedEvents(); 13.559 - rowUntag = androidCalendar.untagAndroidEvents(); 13.560 + } catch (ParserException ex) { 13.561 + Log.e(TAG, "Parser exception", ex); 13.562 + stats.numParseExceptions++; 13.563 + 13.564 + NotificationsHelper.signalSyncErrors(getContext(), "Caldav sync error (parsing)", ex 13.565 + .getMessage()); 13.566 + //NotificationsHelper.getCurrentSyncLog().addException(ex); 13.567 + } catch (CaldavProtocolException ex) { 13.568 + Log.e(TAG, "Caldav exception", ex); 13.569 + stats.numParseExceptions++; 13.570 + 13.571 + NotificationsHelper.signalSyncErrors(getContext(), "Caldav sync error (caldav)", ex.getMessage()); 13.572 + //NotificationsHelper.getCurrentSyncLog().addException(ex); 13.573 + } 13.574 + } 13.575 + 13.576 + rowDelete = androidCalendar.deleteUntaggedEvents(); 13.577 + rowUntag = androidCalendar.untagAndroidEvents(); 13.578 13.579 /*Log.i(TAG,"Statistiks for Calendar: " + serverCalendar.getURI().toString()); 13.580 Log.i(TAG,"Statistiks for AndroidCalendar: " + androidCalendar.getAndroidCalendarUri().toString()); 13.581 @@ -380,188 +395,192 @@ 13.582 Log.i(TAG,"Rows updated: " + String.valueOf(rowUpdate)); 13.583 Log.i(TAG,"Rows deleted: " + String.valueOf(rowDelete)); 13.584 Log.i(TAG,"Rows skipped: " + String.valueOf(rowSkip));*/ 13.585 - Log.i(TAG,"Rows tagged: " + String.valueOf(rowTag)); 13.586 - Log.i(TAG,"Rows untagged: " + String.valueOf(rowUntag)); 13.587 - 13.588 - stats.numInserts += rowInsert; 13.589 - stats.numUpdates += rowUpdate; 13.590 - stats.numDeletes += rowDelete; 13.591 - stats.numSkippedEntries += rowSkip; 13.592 - stats.numEntries += rowInsert + rowUpdate + rowDelete; 13.593 + Log.i(TAG, "Rows tagged: " + String.valueOf(rowTag)); 13.594 + Log.i(TAG, "Rows untagged: " + String.valueOf(rowUntag)); 13.595 13.596 - } 13.597 - 13.598 - /** 13.599 - * checks the android events for the dirty flag. 13.600 - * the flag is set by android when the event has been changed. 13.601 - * the dirty flag is removed when an android event has been updated from calendar event 13.602 - * @param provider 13.603 - * @param account 13.604 - * @param calendarUri 13.605 - * @param facade 13.606 - * @param caldavCalendarUri 13.607 - * @param stats 13.608 - * @param notifyList 13.609 - * @return count of dirty events 13.610 - */ 13.611 - private int checkDirtyAndroidEvents( 13.612 - ContentProviderClient provider, 13.613 - Account account, 13.614 - Uri calendarUri, 13.615 - CaldavFacade facade, 13.616 - URI caldavCalendarUri, 13.617 - SyncStats stats, 13.618 - ArrayList<Uri> notifyList 13.619 - ) { 13.620 - Cursor curEvent = null; 13.621 - Cursor curAttendee = null; 13.622 - Cursor curReminder = null; 13.623 - Long EventID; 13.624 - Long CalendarID; 13.625 - AndroidEvent androidEvent = null; 13.626 - int rowDirty = 0; 13.627 - int rowInsert = 0; 13.628 - int rowUpdate = 0; 13.629 - int rowDelete = 0; 13.630 - 13.631 - try { 13.632 - CalendarID = ContentUris.parseId(calendarUri); 13.633 - String selection = "(" + Events.DIRTY + " = ?) AND (" + Events.CALENDAR_ID + " = ?)"; 13.634 - String[] selectionArgs = new String[] {"1", CalendarID.toString()}; 13.635 - curEvent = provider.query(Events.CONTENT_URI, null, selection, selectionArgs, null); 13.636 - 13.637 - while (curEvent.moveToNext()) { 13.638 - EventID = curEvent.getLong(curEvent.getColumnIndex(Events._ID)); 13.639 - Uri returnedUri = ContentUris.withAppendedId(Events.CONTENT_URI, EventID); 13.640 - 13.641 - //androidEvent = new AndroidEvent(account, provider, returnedUri, calendarUri); 13.642 - androidEvent = new AndroidEvent(returnedUri, calendarUri); 13.643 - androidEvent.readContentValues(curEvent); 13.644 - 13.645 - selection = "(" + Attendees.EVENT_ID + " = ?)"; 13.646 - selectionArgs = new String[] {String.valueOf(EventID)}; 13.647 - curAttendee = provider.query(Attendees.CONTENT_URI, null, selection, selectionArgs, null); 13.648 - selection = "(" + Reminders.EVENT_ID + " = ?)"; 13.649 - selectionArgs = new String[] {String.valueOf(EventID)}; 13.650 - curReminder = provider.query(Reminders.CONTENT_URI, null, selection, selectionArgs, null); 13.651 - androidEvent.readAttendees(curAttendee); 13.652 - androidEvent.readReminder(curReminder); 13.653 - curAttendee.close(); 13.654 - curReminder.close(); 13.655 - 13.656 - String SyncID = androidEvent.ContentValues.getAsString(Events._SYNC_ID); 13.657 - 13.658 - boolean Deleted = false; 13.659 - int intDeleted = 0; 13.660 - intDeleted = curEvent.getInt(curEvent.getColumnIndex(Events.DELETED)); 13.661 - Deleted = (intDeleted == 1); 13.662 + stats.numInserts += rowInsert; 13.663 + stats.numUpdates += rowUpdate; 13.664 + stats.numDeletes += rowDelete; 13.665 + stats.numSkippedEntries += rowSkip; 13.666 + stats.numEntries += rowInsert + rowUpdate + rowDelete; 13.667 13.668 - if (SyncID == null) { 13.669 - // new Android event 13.670 - String newGUID = java.util.UUID.randomUUID().toString() + "-caldavsyncadapter"; 13.671 - String calendarPath = caldavCalendarUri.getPath(); 13.672 - if (!calendarPath.endsWith("/")) 13.673 - calendarPath += "/"; 13.674 + } 13.675 13.676 - SyncID = calendarPath + newGUID + ".ics"; 13.677 - 13.678 - androidEvent.createIcs(newGUID); 13.679 - 13.680 - if (facade.createEvent(URI.create(SyncID), androidEvent.getIcsEvent().toString())) { 13.681 - //HINT: bugfix for google calendar replace("@", "%40") 13.682 - if (SyncID.contains("@")) 13.683 - SyncID = SyncID.replace("@", "%40"); 13.684 - ContentValues values = new ContentValues(); 13.685 - values.put(Events._SYNC_ID, SyncID); 13.686 + /** 13.687 + * checks the android events for the dirty flag. 13.688 + * the flag is set by android when the event has been changed. 13.689 + * the dirty flag is removed when an android event has been updated from calendar event 13.690 + * 13.691 + * @param provider 13.692 + * @param account 13.693 + * @param calendarUri 13.694 + * @param facade 13.695 + * @param caldavCalendarUri 13.696 + * @param stats 13.697 + * @param notifyList 13.698 + * @return count of dirty events 13.699 + */ 13.700 + private int checkDirtyAndroidEvents( 13.701 + ContentProviderClient provider, 13.702 + Account account, 13.703 + Uri calendarUri, 13.704 + CaldavFacade facade, 13.705 + URI caldavCalendarUri, 13.706 + SyncStats stats, 13.707 + ArrayList<Uri> notifyList 13.708 + ) { 13.709 + Cursor curEvent = null; 13.710 + Cursor curAttendee = null; 13.711 + Cursor curReminder = null; 13.712 + Long EventID; 13.713 + Long CalendarID; 13.714 + AndroidEvent androidEvent = null; 13.715 + int rowDirty = 0; 13.716 + int rowInsert = 0; 13.717 + int rowUpdate = 0; 13.718 + int rowDelete = 0; 13.719 13.720 - //google doesn't send the etag after creation 13.721 - //HINT: my SabreDAV send always the same etag after putting a new event 13.722 - //String LastETag = facade.getLastETag(); 13.723 - //if (!LastETag.equals("")) { 13.724 - // values.put(Event.ETAG, LastETag); 13.725 - //} else { 13.726 - //so get the etag with a new REPORT 13.727 - CalendarEvent calendarEvent = new CalendarEvent(account, provider); 13.728 - calendarEvent.calendarURL = caldavCalendarUri.toURL(); 13.729 - URI SyncURI = new URI(SyncID); 13.730 - calendarEvent.setUri(SyncURI); 13.731 - CaldavFacade.getEvent(calendarEvent); 13.732 - values.put(Event.ETAG, calendarEvent.getETag()); 13.733 - //} 13.734 - values.put(Event.UID, newGUID); 13.735 - values.put(Events.DIRTY, 0); 13.736 - values.put(Event.RAWDATA, androidEvent.getIcsEvent().toString()); 13.737 - 13.738 - int rowCount = provider.update(asSyncAdapter(androidEvent.getUri(), account.name, account.type), values, null, null); 13.739 - if (rowCount == 1) { 13.740 - rowInsert += 1; 13.741 - notifyList.add(androidEvent.getUri()); 13.742 - } 13.743 - } 13.744 - } else if (Deleted) { 13.745 - // deleted Android event 13.746 - if (facade.deleteEvent(URI.create(SyncID), androidEvent.getETag())) { 13.747 - String mSelectionClause = "(" + Events._ID + "= ?)"; 13.748 - String[] mSelectionArgs = {String.valueOf(EventID)}; 13.749 - 13.750 - int countDeleted = provider.delete(asSyncAdapter(Events.CONTENT_URI, account.name, account.type), mSelectionClause, mSelectionArgs); 13.751 - 13.752 - if (countDeleted == 1) { 13.753 - rowDelete += 1; 13.754 - notifyList.add(androidEvent.getUri()); 13.755 - } 13.756 - } 13.757 - } else { 13.758 - //update the android event to the server 13.759 - String uid = androidEvent.getUID(); 13.760 - if ((uid == null) || (uid.equals(""))) { 13.761 - //COMPAT: this is needed because in the past, the UID was not stored in the android event 13.762 - CalendarEvent calendarEvent = new CalendarEvent(account, provider); 13.763 - URI syncURI = new URI(SyncID); 13.764 - calendarEvent.setUri(syncURI); 13.765 - calendarEvent.calendarURL = caldavCalendarUri.toURL(); 13.766 - if (calendarEvent.fetchBody()) { 13.767 - calendarEvent.readContentValues(); 13.768 - uid = calendarEvent.getUID(); 13.769 - } 13.770 - } 13.771 - if (uid != null) { 13.772 - androidEvent.createIcs(uid); 13.773 - 13.774 - if (facade.updateEvent(URI.create(SyncID), androidEvent.getIcsEvent().toString(), androidEvent.getETag())) { 13.775 - selection = "(" + Events._ID + "= ?)"; 13.776 - selectionArgs = new String[] {EventID.toString()}; 13.777 - androidEvent.ContentValues.put(Events.DIRTY, 0); 13.778 + try { 13.779 + CalendarID = ContentUris.parseId(calendarUri); 13.780 + String selection = "(" + Events.DIRTY + " = ?) AND (" + Events.CALENDAR_ID + " = ?)"; 13.781 + String[] selectionArgs = new String[]{"1", CalendarID.toString()}; 13.782 + curEvent = provider.query(Events.CONTENT_URI, null, selection, selectionArgs, null); 13.783 13.784 - //google doesn't send the etag after update 13.785 - String LastETag = facade.getLastETag(); 13.786 - if (!LastETag.equals("")) { 13.787 - androidEvent.ContentValues.put(Event.ETAG, LastETag); 13.788 - } else { 13.789 - //so get the etag with a new REPORT 13.790 - CalendarEvent calendarEvent = new CalendarEvent(account, provider); 13.791 - calendarEvent.calendarURL = caldavCalendarUri.toURL(); 13.792 - URI SyncURI = new URI(SyncID); 13.793 - calendarEvent.setUri(SyncURI); 13.794 - CaldavFacade.getEvent(calendarEvent); 13.795 - androidEvent.ContentValues.put(Event.ETAG, calendarEvent.getETag()); 13.796 - } 13.797 - androidEvent.ContentValues.put(Event.RAWDATA, androidEvent.getIcsEvent().toString()); 13.798 - int RowCount = provider.update(asSyncAdapter(androidEvent.getUri(), account.name, account.type), androidEvent.ContentValues, null, null); 13.799 - 13.800 - if (RowCount == 1) { 13.801 - rowUpdate += 1; 13.802 - notifyList.add(androidEvent.getUri()); 13.803 - } 13.804 - } else { 13.805 - rowDirty += 1; 13.806 - } 13.807 - } else { 13.808 - rowDirty += 1; 13.809 - } 13.810 - } 13.811 - } 13.812 - curEvent.close(); 13.813 + while (curEvent.moveToNext()) { 13.814 + EventID = curEvent.getLong(curEvent.getColumnIndex(Events._ID)); 13.815 + Uri returnedUri = ContentUris.withAppendedId(Events.CONTENT_URI, EventID); 13.816 + 13.817 + //androidEvent = new AndroidEvent(account, provider, returnedUri, calendarUri); 13.818 + androidEvent = new AndroidEvent(returnedUri, calendarUri); 13.819 + androidEvent.readContentValues(curEvent); 13.820 + 13.821 + selection = "(" + Attendees.EVENT_ID + " = ?)"; 13.822 + selectionArgs = new String[]{String.valueOf(EventID)}; 13.823 + curAttendee = provider.query(Attendees.CONTENT_URI, null, selection, selectionArgs, null); 13.824 + selection = "(" + Reminders.EVENT_ID + " = ?)"; 13.825 + selectionArgs = new String[]{String.valueOf(EventID)}; 13.826 + curReminder = provider.query(Reminders.CONTENT_URI, null, selection, selectionArgs, null); 13.827 + androidEvent.readAttendees(curAttendee); 13.828 + androidEvent.readReminder(curReminder); 13.829 + curAttendee.close(); 13.830 + curReminder.close(); 13.831 + 13.832 + String SyncID = androidEvent.ContentValues.getAsString(Events._SYNC_ID); 13.833 + 13.834 + boolean Deleted = false; 13.835 + int intDeleted = 0; 13.836 + intDeleted = curEvent.getInt(curEvent.getColumnIndex(Events.DELETED)); 13.837 + Deleted = (intDeleted == 1); 13.838 + 13.839 + if (SyncID == null) { 13.840 + // new Android event 13.841 + String newGUID = java.util.UUID.randomUUID().toString() + "-caldavsyncadapter"; 13.842 + String calendarPath = caldavCalendarUri.getPath(); 13.843 + if (!calendarPath.endsWith("/")) 13.844 + calendarPath += "/"; 13.845 + 13.846 + SyncID = calendarPath + newGUID + ".ics"; 13.847 + 13.848 + androidEvent.createIcs(newGUID); 13.849 + 13.850 + if (facade.createEvent(URI.create(SyncID), androidEvent.getIcsEvent() 13.851 + .toString())) { 13.852 + //HINT: bugfix for google calendar replace("@", "%40") 13.853 + if (SyncID.contains("@")) 13.854 + SyncID = SyncID.replace("@", "%40"); 13.855 + ContentValues values = new ContentValues(); 13.856 + values.put(Events._SYNC_ID, SyncID); 13.857 + 13.858 + //google doesn't send the etag after creation 13.859 + //HINT: my SabreDAV send always the same etag after putting a new event 13.860 + //String LastETag = facade.getLastETag(); 13.861 + //if (!LastETag.equals("")) { 13.862 + // values.put(Event.ETAG, LastETag); 13.863 + //} else { 13.864 + //so get the etag with a new REPORT 13.865 + CalendarEvent calendarEvent = new CalendarEvent(account, provider); 13.866 + calendarEvent.calendarURL = caldavCalendarUri.toURL(); 13.867 + URI SyncURI = new URI(SyncID); 13.868 + calendarEvent.setUri(SyncURI); 13.869 + CaldavFacade.getEvent(calendarEvent); 13.870 + values.put(Event.ETAG, calendarEvent.getETag()); 13.871 + //} 13.872 + values.put(Event.UID, newGUID); 13.873 + values.put(Events.DIRTY, 0); 13.874 + values.put(Event.RAWDATA, androidEvent.getIcsEvent().toString()); 13.875 + 13.876 + int rowCount = provider.update(asSyncAdapter(androidEvent.getUri(), account.name, account.type), values, null, null); 13.877 + if (rowCount == 1) { 13.878 + rowInsert += 1; 13.879 + notifyList.add(androidEvent.getUri()); 13.880 + } 13.881 + } 13.882 + } else if (Deleted) { 13.883 + // deleted Android event 13.884 + if (facade.deleteEvent(URI.create(SyncID), androidEvent.getETag())) { 13.885 + String mSelectionClause = "(" + Events._ID + "= ?)"; 13.886 + String[] mSelectionArgs = {String.valueOf(EventID)}; 13.887 + 13.888 + int countDeleted = provider.delete(asSyncAdapter(Events.CONTENT_URI, account.name, account.type), mSelectionClause, mSelectionArgs); 13.889 + 13.890 + if (countDeleted == 1) { 13.891 + rowDelete += 1; 13.892 + notifyList.add(androidEvent.getUri()); 13.893 + } 13.894 + } 13.895 + } else { 13.896 + //update the android event to the server 13.897 + String uid = androidEvent.getUID(); 13.898 + if ((uid == null) || (uid.equals(""))) { 13.899 + //COMPAT: this is needed because in the past, the UID was not stored in the android event 13.900 + CalendarEvent calendarEvent = new CalendarEvent(account, provider); 13.901 + URI syncURI = new URI(SyncID); 13.902 + calendarEvent.setUri(syncURI); 13.903 + calendarEvent.calendarURL = caldavCalendarUri.toURL(); 13.904 + if (calendarEvent.fetchBody()) { 13.905 + calendarEvent.readContentValues(); 13.906 + uid = calendarEvent.getUID(); 13.907 + } 13.908 + } 13.909 + if (uid != null) { 13.910 + androidEvent.createIcs(uid); 13.911 + 13.912 + if (facade.updateEvent(URI.create(SyncID), androidEvent.getIcsEvent() 13.913 + .toString(), androidEvent.getETag())) { 13.914 + selection = "(" + Events._ID + "= ?)"; 13.915 + selectionArgs = new String[]{EventID.toString()}; 13.916 + androidEvent.ContentValues.put(Events.DIRTY, 0); 13.917 + 13.918 + //google doesn't send the etag after update 13.919 + String LastETag = facade.getLastETag(); 13.920 + if (!LastETag.equals("")) { 13.921 + androidEvent.ContentValues.put(Event.ETAG, LastETag); 13.922 + } else { 13.923 + //so get the etag with a new REPORT 13.924 + CalendarEvent calendarEvent = new CalendarEvent(account, provider); 13.925 + calendarEvent.calendarURL = caldavCalendarUri.toURL(); 13.926 + URI SyncURI = new URI(SyncID); 13.927 + calendarEvent.setUri(SyncURI); 13.928 + CaldavFacade.getEvent(calendarEvent); 13.929 + androidEvent.ContentValues.put(Event.ETAG, calendarEvent.getETag()); 13.930 + } 13.931 + androidEvent.ContentValues.put(Event.RAWDATA, androidEvent.getIcsEvent() 13.932 + .toString()); 13.933 + int RowCount = provider.update(asSyncAdapter(androidEvent.getUri(), account.name, account.type), androidEvent.ContentValues, null, null); 13.934 + 13.935 + if (RowCount == 1) { 13.936 + rowUpdate += 1; 13.937 + notifyList.add(androidEvent.getUri()); 13.938 + } 13.939 + } else { 13.940 + rowDirty += 1; 13.941 + } 13.942 + } else { 13.943 + rowDirty += 1; 13.944 + } 13.945 + } 13.946 + } 13.947 + curEvent.close(); 13.948 13.949 /*if ((rowInsert > 0) || (rowUpdate > 0) || (rowDelete > 0) || (rowDirty > 0)) { 13.950 Log.i(TAG,"Android Rows inserted: " + String.valueOf(rowInsert)); 13.951 @@ -569,33 +588,33 @@ 13.952 Log.i(TAG,"Android Rows deleted: " + String.valueOf(rowDelete)); 13.953 Log.i(TAG,"Android Rows dirty: " + String.valueOf(rowDirty)); 13.954 }*/ 13.955 - 13.956 - stats.numInserts += rowInsert; 13.957 - stats.numUpdates += rowUpdate; 13.958 - stats.numDeletes += rowDelete; 13.959 - stats.numSkippedEntries += rowDirty; 13.960 - stats.numEntries += rowInsert + rowUpdate + rowDelete; 13.961 - } catch (RemoteException e) { 13.962 - e.printStackTrace(); 13.963 - } catch (URISyntaxException e) { 13.964 - // TODO Automatisch generierter Erfassungsblock 13.965 - e.printStackTrace(); 13.966 - } catch (ClientProtocolException e) { 13.967 - // TODO Automatisch generierter Erfassungsblock 13.968 - e.printStackTrace(); 13.969 - } catch (IOException e) { 13.970 - // TODO Automatisch generierter Erfassungsblock 13.971 - e.printStackTrace(); 13.972 - } catch (CaldavProtocolException e) { 13.973 - // TODO Automatisch generierter Erfassungsblock 13.974 - e.printStackTrace(); 13.975 - } catch (ParserException e) { 13.976 - // TODO Automatisch generierter Erfassungsblock 13.977 - e.printStackTrace(); 13.978 - } 13.979 - 13.980 - return rowDirty; 13.981 - } 13.982 + 13.983 + stats.numInserts += rowInsert; 13.984 + stats.numUpdates += rowUpdate; 13.985 + stats.numDeletes += rowDelete; 13.986 + stats.numSkippedEntries += rowDirty; 13.987 + stats.numEntries += rowInsert + rowUpdate + rowDelete; 13.988 + } catch (RemoteException e) { 13.989 + e.printStackTrace(); 13.990 + } catch (URISyntaxException e) { 13.991 + // TODO Automatisch generierter Erfassungsblock 13.992 + e.printStackTrace(); 13.993 + } catch (ClientProtocolException e) { 13.994 + // TODO Automatisch generierter Erfassungsblock 13.995 + e.printStackTrace(); 13.996 + } catch (IOException e) { 13.997 + // TODO Automatisch generierter Erfassungsblock 13.998 + e.printStackTrace(); 13.999 + } catch (CaldavProtocolException e) { 13.1000 + // TODO Automatisch generierter Erfassungsblock 13.1001 + e.printStackTrace(); 13.1002 + } catch (ParserException e) { 13.1003 + // TODO Automatisch generierter Erfassungsblock 13.1004 + e.printStackTrace(); 13.1005 + } 13.1006 + 13.1007 + return rowDirty; 13.1008 + } 13.1009 13.1010 /* private Account UpgradeAccount(Account OldAccount) { 13.1011 String Username = OldAccount.name; 13.1012 @@ -624,13 +643,13 @@ 13.1013 selection, selectionArgs); 13.1014 13.1015 }*/ 13.1016 - 13.1017 - private static Uri asSyncAdapter(Uri uri, String account, String accountType) { 13.1018 - return uri.buildUpon() 13.1019 - .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true") 13.1020 - .appendQueryParameter(Calendars.ACCOUNT_NAME, account) 13.1021 - .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); 13.1022 - } 13.1023 + 13.1024 + private static Uri asSyncAdapter(Uri uri, String account, String accountType) { 13.1025 + return uri.buildUpon() 13.1026 + .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER, "true") 13.1027 + .appendQueryParameter(Calendars.ACCOUNT_NAME, account) 13.1028 + .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); 13.1029 + } 13.1030 13.1031 } 13.1032