static gboolean do_mail_to_event (AsyncData *data) { EClient *client; CamelFolder *folder = data->folder; GPtrArray *uids = data->uids; GError *error = NULL; client = e_client_cache_get_client_sync (data->client_cache, data->source, data->extension_name, 30, NULL, &error); /* Sanity check. */ g_return_val_if_fail ( ((client != NULL) && (error == NULL)) || ((client == NULL) && (error != NULL)), TRUE); if (error != NULL) { report_error_idle (_("Cannot open calendar. %s"), error->message); } else if (e_client_is_readonly (E_CLIENT (client))) { switch (data->source_type) { case E_CAL_CLIENT_SOURCE_TYPE_EVENTS: report_error_idle (_("Selected calendar is read only, thus cannot create event there. Select other calendar, please."), NULL); break; case E_CAL_CLIENT_SOURCE_TYPE_TASKS: report_error_idle (_("Selected task list is read only, thus cannot create task there. Select other task list, please."), NULL); break; case E_CAL_CLIENT_SOURCE_TYPE_MEMOS: report_error_idle (_("Selected memo list is read only, thus cannot create memo there. Select other memo list, please."), NULL); break; default: g_warn_if_reached (); break; } } else { gint i; ECalComponentDateTime dt, dt2; struct icaltimetype tt, tt2; struct _manage_comp *oldmc = NULL; #define cache_backend_prop(prop) { \ gchar *val = NULL; \ e_client_get_backend_property_sync (E_CLIENT (client), prop, &val, NULL, NULL); \ g_free (val); \ } /* precache backend properties, thus editor have them ready when needed */ cache_backend_prop (CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS); cache_backend_prop (CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS); cache_backend_prop (CAL_BACKEND_PROPERTY_DEFAULT_OBJECT); e_client_get_capabilities (E_CLIENT (client)); #undef cache_backend_prop /* set start day of the event as today, without time - easier than looking for a calendar's time zone */ tt = icaltime_today (); dt.value = &tt; dt.tzid = NULL; tt2 = tt; icaltime_adjust (&tt2, 1, 0, 0, 0); dt2.value = &tt2; dt2.tzid = NULL; for (i = 0; i < (uids ? uids->len : 0); i++) { CamelMimeMessage *message; ECalComponent *comp; ECalComponentText text; icalproperty *icalprop; icalcomponent *icalcomp; struct _manage_comp *mc; /* retrieve the message from the CamelFolder */ /* FIXME Not passing a GCancellable or GError. */ message = camel_folder_get_message_sync ( folder, g_ptr_array_index (uids, i), NULL, NULL); if (!message) { continue; } comp = e_cal_component_new (); switch (data->source_type) { case E_CAL_CLIENT_SOURCE_TYPE_EVENTS: e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT); break; case E_CAL_CLIENT_SOURCE_TYPE_TASKS: e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO); break; case E_CAL_CLIENT_SOURCE_TYPE_MEMOS: e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL); break; default: g_warn_if_reached (); break; } e_cal_component_set_uid (comp, camel_mime_message_get_message_id (message)); e_cal_component_set_dtstart (comp, &dt); if (data->source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS) { /* make it an all-day event */ e_cal_component_set_dtend (comp, &dt2); } /* set the summary */ text.value = camel_mime_message_get_subject (message); text.altrep = NULL; e_cal_component_set_summary (comp, &text); /* set all fields */ if (data->selected_text) { GSList sl; text.value = data->selected_text; text.altrep = NULL; sl.next = NULL; sl.data = &text; e_cal_component_set_description_list (comp, &sl); } else set_description (comp, message); if (data->with_attendees) { gchar *organizer; /* set actual user as organizer, to be able to change event's properties */ organizer = set_organizer (comp, data->folder); set_attendees (comp, message, organizer); g_free (organizer); } /* set attachment files */ set_attachments (E_CAL_CLIENT (client), comp, message); /* priority */ set_priority (comp, CAMEL_MIME_PART (message)); /* no need to increment a sequence number, this is a new component */ e_cal_component_abort_sequence (comp); icalcomp = e_cal_component_get_icalcomponent (comp); icalprop = icalproperty_new_x ("1"); icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR"); icalcomponent_add_property (icalcomp, icalprop); mc = g_new0 (struct _manage_comp, 1); mc->client = g_object_ref (client); mc->comp = g_object_ref (comp); g_mutex_init (&mc->mutex); g_cond_init (&mc->cond); mc->mails_count = uids->len; mc->mails_done = i + 1; /* Current task */ mc->editor_title = NULL; mc->can_continue = TRUE; if (oldmc) { /* Wait for user to quit the editor created in previous iteration * before displaying next one */ gboolean can_continue; g_mutex_lock (&oldmc->mutex); g_cond_wait (&oldmc->cond, &oldmc->mutex); g_mutex_unlock (&oldmc->mutex); can_continue = oldmc->can_continue; free_manage_comp_struct (oldmc); oldmc = NULL; if (!can_continue) break; } e_cal_client_get_object_sync ( E_CAL_CLIENT (client), icalcomponent_get_uid (icalcomp), NULL, &mc->stored_comp, NULL, NULL); /* Prioritize ahead of GTK+ redraws. */ g_idle_add_full ( G_PRIORITY_HIGH_IDLE, (GSourceFunc) do_manage_comp_idle, mc, NULL); oldmc = mc; g_object_unref (comp); g_object_unref (message); } /* Wait for the last editor and then clean up */ if (oldmc) { g_mutex_lock (&oldmc->mutex); g_cond_wait (&oldmc->cond, &oldmc->mutex); g_mutex_unlock (&oldmc->mutex); free_manage_comp_struct (oldmc); } } /* free memory */ if (client != NULL) g_object_unref (client); g_ptr_array_unref (uids); g_object_unref (folder); g_object_unref (data->client_cache); g_object_unref (data->source); g_free (data->selected_text); g_free (data); data = NULL; if (error != NULL) g_error_free (error); return TRUE; }
/** Collect recipients from the iTip (based on the METHOD). * * To exclude username from the list, pass his name using @a sender * parameter. * * @param icomp iCal component. * @param sender Username to exclude from the list. * @param recipients Pointer to the list of recipients' emails. It will be * appended to. */ void icalcomponent_collect_recipients(icalcomponent *icomp, const char *sender, GSList * *recipients) { GSList *to_list = NULL, *attendees = NULL, *iter; ECalComponentOrganizer organizer; icalproperty_method method; icalcomponent *payload; ECalComponent *ecomp = NULL; payload = icalcomponent_get_itip_payload(icomp); method = icalcomponent_get_itip_method(icomp); if (payload == NULL) { goto out; } ecomp = e_cal_component_new(); e_cal_component_set_icalcomponent(ecomp, icalcomponent_new_clone(payload)); e_cal_component_get_attendee_list(ecomp, &attendees); e_cal_component_get_organizer(ecomp, &organizer); if (organizer.value == NULL) { goto out; } switch (method) { case ICAL_METHOD_REQUEST: case ICAL_METHOD_CANCEL: for (iter = attendees; iter; iter = iter->next) { ECalComponentAttendee *att = iter->data; if (!g_ascii_strcasecmp(att->value, organizer.value)) { continue; } else if (att->sentby && !g_ascii_strcasecmp(att->sentby, organizer.sentby)) { continue; } else if (!g_ascii_strcasecmp(strip_mailto(att->value), sender)) { continue; } else if (att->status == ICAL_PARTSTAT_DELEGATED && (att->delto && *att->delto) && !(att->rsvp) && method == ICAL_METHOD_REQUEST) { continue; } to_list = g_slist_append(to_list, g_strdup(strip_mailto(att->value))); } break; case ICAL_METHOD_REPLY: to_list = g_slist_append(to_list, g_strdup(strip_mailto(organizer.value))); break; case ICAL_METHOD_ADD: case ICAL_METHOD_REFRESH: case ICAL_METHOD_COUNTER: case ICAL_METHOD_DECLINECOUNTER: to_list = g_slist_append(to_list, g_strdup(strip_mailto(organizer.value))); // send the status to delegatee to the delegate also is missing break; case ICAL_METHOD_PUBLISH: default: break; } out: e_cal_component_free_attendee_list(attendees); if (ecomp) { g_object_unref(ecomp); } if (recipients) { *recipients = to_list; } }
static gboolean do_manage_comp_idle (struct _manage_comp *mc) { GError *error = NULL; ECalClientSourceType source_type = E_CAL_CLIENT_SOURCE_TYPE_LAST; ECalComponent *edit_comp = NULL; g_return_val_if_fail (mc, FALSE); source_type = e_cal_client_get_source_type (mc->client); if (source_type == E_CAL_CLIENT_SOURCE_TYPE_LAST) { free_manage_comp_struct (mc); g_warning ("mail-to-task: Incorrect call of %s, no data given", G_STRFUNC); return FALSE; } if (mc->stored_comp) { const gchar *ask = get_question_edit_old (source_type); if (ask) { gchar *msg = g_strdup_printf (ask, icalcomponent_get_summary (mc->stored_comp) ? icalcomponent_get_summary (mc->stored_comp) : _("[No Summary]")); gint chosen; chosen = do_ask (msg, TRUE); if (chosen == GTK_RESPONSE_YES) { edit_comp = e_cal_component_new (); if (!e_cal_component_set_icalcomponent (edit_comp, icalcomponent_new_clone (mc->stored_comp))) { g_object_unref (edit_comp); edit_comp = NULL; error = g_error_new ( E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_INVALID_OBJECT, "%s", _("Invalid object returned from a server")); } } else if (chosen == GTK_RESPONSE_NO) { /* user wants to create a new event, thus generate a new UID */ gchar *new_uid = e_cal_component_gen_uid (); edit_comp = mc->comp; e_cal_component_set_uid (edit_comp, new_uid); e_cal_component_set_recurid (edit_comp, NULL); g_free (new_uid); } g_free (msg); } } else { edit_comp = mc->comp; } if (edit_comp) { EShell *shell; CompEditor *editor; /* FIXME Pass in the EShell instance. */ shell = e_shell_get_default (); editor = get_component_editor ( shell, mc->client, edit_comp, edit_comp == mc->comp, &error); if (editor && !error) { /* Force editor's title change */ comp_editor_title_changed (GTK_WIDGET (editor), NULL, mc); e_signal_connect_notify ( editor, "notify::title", G_CALLBACK (comp_editor_title_changed), mc); g_signal_connect ( editor, "comp_closed", G_CALLBACK (comp_editor_closed), mc); gtk_window_present (GTK_WINDOW (editor)); if (edit_comp != mc->comp) g_object_unref (edit_comp); } else { g_warning ("Failed to create event editor: %s", error ? error->message : "Unknown error"); g_cond_signal (&mc->cond); } } else { /* User canceled editing already existing event, so * treat it as if he just closed the editor window. */ comp_editor_closed (NULL, FALSE, mc); } if (error != NULL) { e_notice ( NULL, GTK_MESSAGE_ERROR, _("An error occurred during processing: %s"), error->message); g_clear_error (&error); } return FALSE; }
/* Pilot syncing callbacks */ static gint pre_sync (GnomePilotConduit *conduit, GnomePilotDBInfo *dbi, EMemoConduitContext *ctxt) { GnomePilotConduitSyncAbs *abs_conduit; GList *l; int len; unsigned char *buf; char *filename, *change_id; icalcomponent *icalcomp; gint num_records, add_records = 0, mod_records = 0, del_records = 0; #ifdef PILOT_LINK_0_12 pi_buffer_t * buffer; #endif abs_conduit = GNOME_PILOT_CONDUIT_SYNC_ABS (conduit); LOG (g_message ( "---------------------------------------------------------\n" )); LOG (g_message ( "pre_sync: Memo Conduit v.%s", CONDUIT_VERSION )); g_message ("Memo Conduit v.%s", CONDUIT_VERSION); ctxt->dbi = dbi; ctxt->client = NULL; if (start_calendar_server (ctxt) != 0) { WARN(_("Could not start evolution-data-server")); gnome_pilot_conduit_error (conduit, _("Could not start evolution-data-server")); return -1; } /* Get the timezone */ ctxt->timezone = get_default_timezone (); if (ctxt->timezone == NULL) return -1; LOG (g_message ( " Using timezone: %s", icaltimezone_get_tzid (ctxt->timezone) )); /* Set the default timezone on the backend. */ if (ctxt->timezone && !e_cal_set_default_timezone (ctxt->client, ctxt->timezone, NULL)) return -1; /* Get the default component */ if (!e_cal_get_default_object (ctxt->client, &icalcomp, NULL)) return -1; ctxt->default_comp = e_cal_component_new (); if (!e_cal_component_set_icalcomponent (ctxt->default_comp, icalcomp)) { g_object_unref (ctxt->default_comp); icalcomponent_free (icalcomp); return -1; } /* Load the uid <--> pilot id map */ filename = map_name (ctxt); e_pilot_map_read (filename, &ctxt->map); g_free (filename); /* Get the local database */ if (!e_cal_get_object_list_as_comp (ctxt->client, "#t", &ctxt->comps, NULL)) return -1; /* Count and hash the changes */ change_id = g_strdup_printf ("pilot-sync-evolution-memo-%d", ctxt->cfg->pilot_id); if (!e_cal_get_changes (ctxt->client, change_id, &ctxt->changed, NULL)) return -1; ctxt->changed_hash = g_hash_table_new (g_str_hash, g_str_equal); g_free (change_id); for (l = ctxt->changed; l != NULL; l = l->next) { ECalChange *ccc = l->data; const char *uid; e_cal_component_get_uid (ccc->comp, &uid); if (!e_pilot_map_uid_is_archived (ctxt->map, uid)) { g_hash_table_insert (ctxt->changed_hash, g_strdup (uid), ccc); switch (ccc->type) { case E_CAL_CHANGE_ADDED: add_records++; break; case E_CAL_CHANGE_MODIFIED: mod_records++; break; case E_CAL_CHANGE_DELETED: del_records++; break; } } else if (ccc->type == E_CAL_CHANGE_DELETED) { e_pilot_map_remove_by_uid (ctxt->map, uid); } } /* Set the count information */ num_records = g_list_length (ctxt->comps); gnome_pilot_conduit_sync_abs_set_num_local_records(abs_conduit, num_records); gnome_pilot_conduit_sync_abs_set_num_new_local_records (abs_conduit, add_records); gnome_pilot_conduit_sync_abs_set_num_updated_local_records (abs_conduit, mod_records); gnome_pilot_conduit_sync_abs_set_num_deleted_local_records(abs_conduit, del_records); g_message("num_records: %d\nadd_records: %d\nmod_records: %d\ndel_records: %d\n", num_records, add_records, mod_records, del_records); #ifdef PILOT_LINK_0_12 buffer = pi_buffer_new(DLP_BUF_SIZE); if(buffer == NULL){ pi_set_error(dbi->pilot_socket, PI_ERR_GENERIC_MEMORY); return -1; } len = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0, DLP_BUF_SIZE, buffer); #else buf = (unsigned char*)g_malloc (0xffff); len = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0, (unsigned char *)buf, 0xffff); #endif if (len < 0) { WARN (_("Could not read pilot's Memo application block")); WARN ("dlp_ReadAppBlock(...) = %d", len); gnome_pilot_conduit_error (conduit, _("Could not read pilot's Memo application block")); return -1; } #ifdef PILOT_LINK_0_12 buf = g_new0 (unsigned char,buffer->used); memcpy(buf, buffer->data, buffer->used); unpack_MemoAppInfo (&(ctxt->ai), buf, len); pi_buffer_free(buffer); #else unpack_MemoAppInfo (&(ctxt->ai), buf, len); #endif g_free (buf); lastDesktopUniqueID = 128; check_for_slow_setting (conduit, ctxt); if (ctxt->cfg->sync_type == GnomePilotConduitSyncTypeCopyToPilot || ctxt->cfg->sync_type == GnomePilotConduitSyncTypeCopyFromPilot) ctxt->map->write_touched_only = TRUE; return 0; }
/** * build_component_from_details: * @summary: * @initial_date: * @final_date: * * Create a component with the provided details * * Returns: (Transfer full): an {@link ECalComponent} object **/ ECalComponent* build_component_from_details (const gchar *summary, GDateTime *initial_date, GDateTime *final_date) { ECalComponent *event; ECalComponentDateTime dt; ECalComponentText summ; icaltimezone *zone; gboolean all_day; event = e_cal_component_new (); e_cal_component_set_new_vtype (event, E_CAL_COMPONENT_EVENT); /* * Check if the event is all day. Notice that it can be all day even * without the final date. */ all_day = datetime_is_date (initial_date) && (final_date ? datetime_is_date (final_date) : TRUE); /* * When the event is all day, we consider UTC timezone by default. Otherwise, * we always use the system timezone to create new events */ if (all_day) { zone = icaltimezone_get_utc_timezone (); } else { gchar *system_tz = e_cal_system_timezone_get_location (); zone = icaltimezone_get_builtin_timezone (system_tz); g_free (system_tz); } /* Start date */ dt.value = datetime_to_icaltime (initial_date); icaltime_set_timezone (dt.value, zone); dt.value->is_date = all_day; dt.tzid = icaltimezone_get_tzid (zone); e_cal_component_set_dtstart (event, &dt); g_free (dt.value); /* End date */ if (!final_date) final_date = g_date_time_add_days (initial_date, 1); dt.value = datetime_to_icaltime (final_date); icaltime_set_timezone (dt.value, zone); dt.value->is_date = all_day; dt.tzid = icaltimezone_get_tzid (zone); e_cal_component_set_dtend (event, &dt); g_free (dt.value); /* Summary */ summ.altrep = NULL; summ.value = summary; e_cal_component_set_summary (event, &summ); e_cal_component_commit_sequence (event); return event; }
static ECalComponent * comp_from_remote_record (GnomePilotConduitSyncAbs *conduit, GnomePilotRecord *remote, ECalComponent *in_comp, icaltimezone *timezone, struct MemoAppInfo *ai) { ECalComponent *comp; struct Memo memo; struct icaltimetype now; icaltimezone *utc_zone; char *txt, *txt2, *txt3; int i; #ifdef PILOT_LINK_0_12 pi_buffer_t * buffer; #endif g_return_val_if_fail (remote != NULL, NULL); #ifdef PILOT_LINK_0_12 buffer = pi_buffer_new(DLP_BUF_SIZE); if(buffer == NULL){ return NULL; } if(pi_buffer_append(buffer, remote->record, remote->length)==NULL){ return NULL; } unpack_Memo (&memo, buffer, memo_v1); pi_buffer_free(buffer); #else memset (&memo, 0, sizeof (struct Memo)); unpack_Memo (&memo, remote->record, remote->length); #endif utc_zone = icaltimezone_get_utc_timezone (); now = icaltime_from_timet_with_zone (time (NULL), FALSE, utc_zone); if (in_comp == NULL) { comp = e_cal_component_new (); e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL); e_cal_component_set_created (comp, &now); } else { comp = e_cal_component_clone (in_comp); } e_cal_component_set_last_modified (comp, &now); /*Category support*/ e_pilot_remote_category_to_local(remote->category, comp, &(ai->category)); /* The iCal description field */ if (!memo.text) { e_cal_component_set_comment_list (comp, NULL); e_cal_component_set_summary(comp, NULL); } else { int idxToUse = -1, ntext = strlen(memo.text); gboolean foundNL = FALSE; GSList l; ECalComponentText text, sumText; for(i = 0; i<ntext && i<50; i++){ if(memo.text[i] == '\n'){ idxToUse = i; foundNL = TRUE; break; } } if(foundNL == FALSE){ if(ntext > 50){ txt2 = g_strndup(memo.text, 50); } else{ txt2 = g_strdup(memo.text); } } else{ txt2 = g_strndup(memo.text, idxToUse); /* cuts off '\n' */ } sumText.value = txt3 = e_pilot_utf8_from_pchar(txt2); sumText.altrep = NULL; text.value = txt = e_pilot_utf8_from_pchar (memo.text); text.altrep = NULL; l.data = &text; l.next = NULL; e_cal_component_set_summary(comp, &sumText); e_cal_component_set_description_list (comp, &l); free (txt); g_free(txt2); free(txt3); } e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_NONE); if (remote->secret) e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PRIVATE); else e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PUBLIC); e_cal_component_commit_sequence (comp); free_Memo(&memo); return comp; }
/** Sync changes from the server to the cache. * * @param cb 3e calendar backend. * * @return TRUE on success. * * @todo Handle UID/RID. * @todo Better server error handling. * @todo Conflict resolution. */ gboolean e_cal_backend_3e_sync_server_to_cache(ECalBackend3e *cb) { GError *local_err = NULL; gboolean update_sync = TRUE; icalcomponent *ical; icalcomponent *icomp; char filter[128]; struct tm tm; time_t stamp = MAX(e_cal_backend_3e_get_sync_timestamp(cb) - 60 * 60 * 24, 0); /*XXX: always add 1 day padding to prevent timezone problems */ /* prepare query filter string */ gmtime_r(&stamp, &tm); strftime(filter, sizeof(filter), "modified_since('%F %T')", &tm); ical = get_server_objects(cb, filter); if (ical == NULL) { return FALSE; } for (icomp = icalcomponent_get_first_component(ical, ICAL_ANY_COMPONENT); icomp; icomp = icalcomponent_get_next_component(ical, ICAL_ANY_COMPONENT)) { icalcomponent_kind kind = icalcomponent_isa(icomp); icalcomponent_set_cache_state(icomp, E_CAL_COMPONENT_CACHE_STATE_NONE); if (kind == ICAL_VEVENT_COMPONENT) { ECalComponent *comp; const char *uid = icalcomponent_get_uid(icomp); gboolean server_deleted = icalcomponent_3e_status_is_deleted(icomp); ECalComponentCacheState comp_state = E_CAL_COMPONENT_CACHE_STATE_NONE; g_static_rw_lock_reader_lock(&cb->priv->cache_lock); comp = e_cal_backend_store_get_component(cb->priv->store, uid, NULL); g_static_rw_lock_reader_unlock(&cb->priv->cache_lock); if (comp) { comp_state = e_cal_component_get_cache_state(comp); } if (server_deleted) { /* deleted by the server */ if (comp && e_cal_component_get_cache_state(comp) != E_CAL_COMPONENT_CACHE_STATE_CREATED && e_cal_component_get_cache_state(comp) != E_CAL_COMPONENT_CACHE_STATE_MODIFIED) { char *object = e_cal_component_get_as_string(comp); ECalComponentId *id = e_cal_component_get_id(comp); g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_remove_component(cb->priv->store, uid, NULL); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_removed(E_CAL_BACKEND(cb), id, object, NULL); e_cal_component_free_id(id); g_free(object); } } else { char *old_object = NULL; char *object; ECalComponent *new_comp = e_cal_component_new(); e_cal_component_set_icalcomponent(new_comp, icalcomponent_new_clone(icomp)); e_cal_component_set_cache_state(new_comp, E_CAL_COMPONENT_CACHE_STATE_NONE); e_cal_backend_3e_convert_attachment_uris_to_local(cb, new_comp); if (comp) { old_object = e_cal_component_get_as_string(comp); } object = e_cal_component_get_as_string(new_comp); if (old_object == NULL) { if (e_cal_backend_3e_download_attachments(cb, new_comp, &local_err)) { /* not in cache yet */ g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_put_component(cb->priv->store, new_comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_created(E_CAL_BACKEND(cb), object); } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "Can't download attachment.", local_err); g_clear_error(&local_err); update_sync = FALSE; } } else if (g_strcmp0(old_object, object)) { /* what is in cache and what is on server differs */ if (comp_state != E_CAL_COMPONENT_CACHE_STATE_NONE) { /* modified in cache, don't do anything */ } else { if (e_cal_backend_3e_download_attachments(cb, new_comp, &local_err)) { /* sync with server */ g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_put_component(cb->priv->store, new_comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), old_object, object); } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "Can't download attachment.", local_err); g_clear_error(&local_err); update_sync = FALSE; } } } g_free(old_object); g_free(object); g_object_unref(new_comp); } if (comp) { g_object_unref(comp); } } else if (kind == ICAL_VTIMEZONE_COMPONENT) { const char *tzid = icalcomponent_get_tzid(icomp); /* import non-existing timezones from the server */ if (!e_cal_backend_store_get_timezone(cb->priv->store, tzid)) { icaltimezone *zone = icaltimezone_new(); icalcomponent *zone_comp = icalcomponent_new_clone(icomp); if (icaltimezone_set_component(zone, zone_comp)) { g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_put_timezone(cb->priv->store, zone); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); } else { icalcomponent_free(zone_comp); } icaltimezone_free(zone, 1); } } else { g_warning("Unsupported component kind (%d) found on the 3e server.", kind); } } if (update_sync) { e_cal_backend_3e_set_sync_timestamp(cb, time(NULL)); } icalcomponent_free(ical); return TRUE; }
static const gchar * test_object_creation (ECal *client, gchar **uid) { ECalComponent *comp, *comp_retrieved; icalcomponent *icalcomp, *icalcomp_retrieved; struct icaltimetype tt; ECalComponentText text; ECalComponentDateTime dt; ECalComponentTransparency transp; gboolean compare; GError *error = NULL; comp = e_cal_component_new (); /* set fields */ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT); text.value = "Creation of new test event"; text.altrep = NULL; e_cal_component_set_summary (comp, &text); tt = icaltime_from_string ("20040109T090000Z"); dt.value = &tt; dt.tzid ="UTC"; e_cal_component_set_dtstart (comp, &dt); tt = icaltime_from_string ("20040109T103000"); dt.value = &tt; dt.tzid ="UTC"; e_cal_component_set_dtend (comp, &dt); e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_OPAQUE); e_cal_component_commit_sequence (comp); icalcomp = e_cal_component_get_icalcomponent (comp); if (!e_cal_create_object (client, icalcomp, uid, &error)) { cl_printf (client, "Object creation: %s\n", error->message); g_free (comp); g_free (icalcomp); return "Test Object Creation failed"; } e_cal_component_commit_sequence (comp); if (!e_cal_get_object (client, *uid, NULL, &icalcomp_retrieved, &error)) { cl_printf (client, "Object retrieval: %s\n", error->message); g_free (uid); g_free (comp); g_free (icalcomp); return "Test Object Creation failed"; } comp_retrieved = e_cal_component_new (); if (!e_cal_component_set_icalcomponent (comp_retrieved, icalcomp_retrieved)) { cl_printf (client, "Could not set icalcomponent\n"); g_free (uid); g_free (comp); g_free (icalcomp); g_free (icalcomp_retrieved); return "Test Object Creation failed"; } /* Dumping icalcomp into a string is not useful as the retrieved object * has some generated information like timestamps. We compare * member values we set during creation*/ compare = e_cal_component_event_dates_match (comp, comp_retrieved); if (compare) { e_cal_component_get_transparency (comp_retrieved, &transp); compare = (transp == E_CAL_COMPONENT_TRANSP_OPAQUE); } g_free (comp_retrieved); g_free (comp); g_free (icalcomp); g_free (icalcomp_retrieved); mu_assert ("Test Object creation : Created object does not match retrieved data\n", compare); return NULL; }
static gboolean cal_backend_http_load (ECalBackendHttp *backend, const gchar *uri, gchar **out_certificate_pem, GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error) { ECalBackendHttpPrivate *priv = backend->priv; ETimezoneCache *timezone_cache; SoupMessage *soup_message; SoupSession *soup_session; icalcomponent *icalcomp, *subcomp; icalcomponent_kind kind; const gchar *newuri; SoupURI *uri_parsed; GHashTable *old_cache; GSList *comps_in_cache; ESource *source; guint status_code; gulong cancel_id = 0; struct { SoupSession *soup_session; SoupMessage *soup_message; } cancel_data; timezone_cache = E_TIMEZONE_CACHE (backend); soup_session = backend->priv->soup_session; soup_message = cal_backend_http_new_message (backend, uri); if (soup_message == NULL) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Malformed URI: %s"), uri); return FALSE; } if (G_IS_CANCELLABLE (cancellable)) { cancel_data.soup_session = soup_session; cancel_data.soup_message = soup_message; cancel_id = g_cancellable_connect ( cancellable, G_CALLBACK (cal_backend_http_cancelled), &cancel_data, (GDestroyNotify) NULL); } source = e_backend_get_source (E_BACKEND (backend)); e_soup_ssl_trust_connect (soup_message, source); e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING); status_code = soup_session_send_message (soup_session, soup_message); if (G_IS_CANCELLABLE (cancellable)) g_cancellable_disconnect (cancellable, cancel_id); if (status_code == SOUP_STATUS_NOT_MODIFIED) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); /* attempts with ETag can result in 304 status code */ g_object_unref (soup_message); priv->opened = TRUE; return TRUE; } /* Handle redirection ourselves */ if (SOUP_STATUS_IS_REDIRECTION (status_code)) { gboolean success; newuri = soup_message_headers_get_list ( soup_message->response_headers, "Location"); d (g_message ("Redirected from %s to %s\n", async_context->uri, newuri)); if (newuri != NULL) { gchar *redirected_uri; if (newuri[0]=='/') { g_warning ("Hey! Relative URI returned! Working around...\n"); uri_parsed = soup_uri_new (uri); soup_uri_set_path (uri_parsed, newuri); soup_uri_set_query (uri_parsed, NULL); /* g_free (newuri); */ newuri = soup_uri_to_string (uri_parsed, FALSE); g_message ("Translated URI: %s\n", newuri); soup_uri_free (uri_parsed); } redirected_uri = webcal_to_http_method (newuri, FALSE); success = cal_backend_http_load ( backend, redirected_uri, out_certificate_pem, out_certificate_errors, cancellable, error); g_free (redirected_uri); } else { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_BAD_REQUEST, _("Redirected to Invalid URI")); success = FALSE; } if (success) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); } else { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED); } g_object_unref (soup_message); return success; } /* check status code */ if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) { /* because evolution knows only G_IO_ERROR_CANCELLED */ if (status_code == SOUP_STATUS_CANCELLED) g_set_error ( error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "%s", soup_message->reason_phrase); else g_set_error ( error, SOUP_HTTP_ERROR, status_code, "%s", soup_message->reason_phrase); if (status_code == SOUP_STATUS_SSL_FAILED) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_SSL_FAILED); cal_backend_http_extract_ssl_failed_data (soup_message, out_certificate_pem, out_certificate_errors); } else { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED); } g_object_unref (soup_message); empty_cache (backend); return FALSE; } e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); if (priv->store) { const gchar *etag; etag = soup_message_headers_get_one ( soup_message->response_headers, "ETag"); if (etag != NULL && *etag == '\0') etag = NULL; e_cal_backend_store_put_key_value (priv->store, "ETag", etag); } /* get the calendar from the response */ icalcomp = icalparser_parse_string (soup_message->response_body->data); if (!icalcomp) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Bad file format.")); g_object_unref (soup_message); empty_cache (backend); return FALSE; } if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Not a calendar.")); icalcomponent_free (icalcomp); g_object_unref (soup_message); empty_cache (backend); return FALSE; } g_object_unref (soup_message); soup_message = NULL; /* Update cache */ old_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); comps_in_cache = e_cal_backend_store_get_components (priv->store); while (comps_in_cache != NULL) { const gchar *uid; ECalComponent *comp = comps_in_cache->data; e_cal_component_get_uid (comp, &uid); g_hash_table_insert (old_cache, g_strdup (uid), e_cal_component_get_as_string (comp)); comps_in_cache = g_slist_remove (comps_in_cache, comps_in_cache->data); g_object_unref (comp); } kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend)); subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); e_cal_backend_store_freeze_changes (priv->store); while (subcomp) { ECalComponent *comp; icalcomponent_kind subcomp_kind; icalproperty *prop = NULL; subcomp_kind = icalcomponent_isa (subcomp); prop = icalcomponent_get_first_property (subcomp, ICAL_UID_PROPERTY); if (!prop && subcomp_kind == kind) { gchar *new_uid = e_cal_component_gen_uid (); icalcomponent_set_uid (subcomp, new_uid); g_free (new_uid); } if (subcomp_kind == kind) { comp = e_cal_component_new (); if (e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp))) { const gchar *uid; gpointer orig_key, orig_value; e_cal_component_get_uid (comp, &uid); if (!put_component_to_store (backend, comp)) { g_hash_table_remove (old_cache, uid); } else if (g_hash_table_lookup_extended (old_cache, uid, &orig_key, &orig_value)) { ECalComponent *orig_comp = e_cal_component_new_from_string (orig_value); e_cal_backend_notify_component_modified (E_CAL_BACKEND (backend), orig_comp, comp); g_hash_table_remove (old_cache, uid); if (orig_comp) g_object_unref (orig_comp); } else { e_cal_backend_notify_component_created (E_CAL_BACKEND (backend), comp); } } g_object_unref (comp); } else if (subcomp_kind == ICAL_VTIMEZONE_COMPONENT) { icaltimezone *zone; zone = icaltimezone_new (); icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp)); e_timezone_cache_add_timezone (timezone_cache, zone); icaltimezone_free (zone, 1); } subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT); } e_cal_backend_store_thaw_changes (priv->store); /* notify the removals */ g_hash_table_foreach_remove (old_cache, (GHRFunc) notify_and_remove_from_cache, backend); g_hash_table_destroy (old_cache); /* free memory */ icalcomponent_free (icalcomp); priv->opened = TRUE; return TRUE; }
static GtkWidget * ical_get_preview (icalcomponent *icalcomp) { GtkWidget *preview; GtkTreeView *tree_view; GtkTreeSelection *selection; GtkListStore *store; GtkTreeIter iter; GHashTable *timezones; icalcomponent *subcomp; icaltimezone *users_zone; if (!icalcomp || !is_icalcomp_usable (icalcomp)) return NULL; store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, E_TYPE_CAL_COMPONENT); timezones = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_zone_cb); users_zone = get_users_timezone (); /* get timezones first */ for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT); subcomp; subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT)) { icaltimezone *zone = icaltimezone_new (); if (!icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp)) || !icaltimezone_get_tzid (zone)) { icaltimezone_free (zone, 1); } else { g_hash_table_insert (timezones, (gchar *) icaltimezone_get_tzid (zone), zone); } } /* then each component */ for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); subcomp; subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT)) { icalcomponent_kind kind = icalcomponent_isa (subcomp); if (kind == ICAL_VEVENT_COMPONENT || kind == ICAL_VTODO_COMPONENT || kind == ICAL_VJOURNAL_COMPONENT) { ECalComponent *comp = e_cal_component_new (); ECalComponentText summary = { 0 }; ECalComponentDateTime dt = { 0 }; gchar *formatted_dt; if (!e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp))) { g_object_unref (comp); continue; } e_cal_component_get_summary (comp, &summary); e_cal_component_get_dtstart (comp, &dt); formatted_dt = format_dt (&dt, timezones, users_zone); gtk_list_store_append (store, &iter); gtk_list_store_set ( store, &iter, 0, kind == ICAL_VEVENT_COMPONENT ? (e_cal_component_has_attendees (comp) ? C_("iCalImp", "Meeting") : C_("iCalImp", "Event")) : kind == ICAL_VTODO_COMPONENT ? C_("iCalImp", "Task") : kind == ICAL_VJOURNAL_COMPONENT ? C_("iCalImp", "Memo") : "??? Other ???", 1, formatted_dt ? formatted_dt : "", 2, summary.value && *summary.value ? summary.value : summary.altrep && *summary.altrep ? summary.altrep : "", 3, comp, -1); g_free (formatted_dt); e_cal_component_free_datetime (&dt); g_object_unref (comp); } } if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) { g_object_unref (store); g_hash_table_destroy (timezones); return NULL; } preview = e_web_view_preview_new (); gtk_widget_show (preview); g_object_set_data_full (G_OBJECT (preview), "iCalImp-timezones", timezones, (GDestroyNotify) g_hash_table_destroy); g_object_set_data (G_OBJECT (preview), "iCalImp-userszone", users_zone); tree_view = e_web_view_preview_get_tree_view (E_WEB_VIEW_PREVIEW (preview)); g_return_val_if_fail (tree_view != NULL, NULL); gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store)); g_object_unref (store); /* Translators: Column header for a component type; it can be Event, Task or Memo */ gtk_tree_view_insert_column_with_attributes ( tree_view, -1, C_("iCalImp", "Type"), gtk_cell_renderer_text_new (), "text", 0, NULL); /* Translators: Column header for a component start date/time */ gtk_tree_view_insert_column_with_attributes ( tree_view, -1, C_("iCalImp", "Start"), gtk_cell_renderer_text_new (), "text", 1, NULL); /* Translators: Column header for a component summary */ gtk_tree_view_insert_column_with_attributes ( tree_view, -1, C_("iCalImp", "Summary"), gtk_cell_renderer_text_new (), "text", 2, NULL); if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) e_web_view_preview_show_tree_view (E_WEB_VIEW_PREVIEW (preview)); selection = gtk_tree_view_get_selection (tree_view); gtk_tree_selection_select_iter (selection, &iter); g_signal_connect ( selection, "changed", G_CALLBACK (preview_selection_changed_cb), preview); preview_selection_changed_cb (selection, E_WEB_VIEW_PREVIEW (preview)); return preview; }