void ForkExecParent::setupPipe(GIOChannel *&channel, guint &sourceID, int fd) { if (fd == -1) { // nop return; } channel = g_io_channel_unix_new(fd); if (!channel) { // failure SE_LOG_DEBUG(NULL, NULL, "g_io_channel_unix_new() returned NULL"); close(fd); return; } // Close fd when freeing the channel (done by caller). g_io_channel_set_close_on_unref(channel, true); // Don't block in outputReady(). GErrorCXX error; g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, error); // We assume that the helper is writing data in the same encoding // and thus avoid any kind of conversion. Necessary to avoid // buffering. error.clear(); g_io_channel_set_encoding(channel, NULL, error); g_io_channel_set_buffered(channel, true); sourceID = g_io_add_watch(channel, (GIOCondition)(G_IO_IN|G_IO_ERR|G_IO_HUP), outputReady, this); }
void EvolutionContactSource::listAllItems(RevisionMap_t &revisions) { #ifdef USE_EBOOK_CLIENT GErrorCXX gerror; EBookClientView *view; EBookQueryCXX allItemsQuery(e_book_query_any_field_contains(""), false); PlainGStr sexp(e_book_query_to_string (allItemsQuery.get())); if (!e_book_client_get_view_sync(m_addressbook, sexp, &view, NULL, gerror)) { throwError( "getting the view" , gerror); } EBookClientViewCXX viewPtr = EBookClientViewCXX::steal(view); // Optimization: set fields_of_interest (UID / REV) GListCXX<const char, GSList> interesting_field_list; interesting_field_list.push_back(e_contact_field_name (E_CONTACT_UID)); interesting_field_list.push_back(e_contact_field_name (E_CONTACT_REV)); e_book_client_view_set_fields_of_interest (viewPtr, interesting_field_list, gerror); if (gerror) { SE_LOG_ERROR(this, NULL, "e_book_client_view_set_fields_of_interest: %s", (const char*)gerror); gerror.clear(); } EBookClientViewSyncHandler handler(viewPtr, list_revisions, &revisions); if (!handler.process(gerror)) { throwError("watching view", gerror); } #else GErrorCXX gerror; eptr<EBookQuery> allItemsQuery(e_book_query_any_field_contains(""), "query"); GList *nextItem; if (!e_book_get_contacts(m_addressbook, allItemsQuery, &nextItem, gerror)) { throwError( "reading all items", gerror ); } eptr<GList> listptr(nextItem); while (nextItem) { EContact *contact = E_CONTACT(nextItem->data); if (!contact) { throwError("contact entry without data"); } pair<string, string> revmapping; const char *uid = (const char *)e_contact_get_const(contact, E_CONTACT_UID); if (!uid || !uid[0]) { throwError("contact entry without UID"); } revmapping.first = uid; const char *rev = (const char *)e_contact_get_const(contact, E_CONTACT_REV); if (!rev || !rev[0]) { throwError(string("contact entry without REV: ") + revmapping.first); } revmapping.second = rev; revisions.insert(revmapping); nextItem = nextItem->next; } #endif }
EvolutionSyncSource::Databases EvolutionContactSource::getDatabases() { ESourceList *sources = NULL; #ifdef USE_EBOOK_CLIENT if (!e_book_client_get_sources(&sources, NULL)) { #else if (!e_book_get_addressbooks(&sources, NULL)) { #endif SyncContext::throwError("unable to access address books"); } Databases secondary; Databases result; for (GSList *g = e_source_list_peek_groups (sources); g; g = g->next) { ESourceGroup *group = E_SOURCE_GROUP (g->data); for (GSList *s = e_source_group_peek_sources (group); s; s = s->next) { ESource *source = E_SOURCE (s->data); eptr<char> uri(e_source_get_uri(source)); string uristr; if (uri) { uristr = uri.get(); } Database entry(e_source_peek_name(source), uristr, false); if (boost::starts_with(uristr, "couchdb://")) { // Append CouchDB address books at the end of the list, // otherwise preserving the order of address books. // // The reason is Moblin Bugzilla #7877 (aka CouchDB // feature request #479110): the initial release of // evolution-couchdb in Ubuntu 9.10 is unusable because // it does not support the REV property. // // Reordering the entries ensures that the CouchDB // address book is not used as the default database by // SyncEvolution, as it happened in Ubuntu 9.10. // Users can still pick it intentionally via // "evolutionsource". secondary.push_back(entry); } else { result.push_back(entry); } } } result.insert(result.end(), secondary.begin(), secondary.end()); // No results? Try system address book (workaround for embedded Evolution Dataserver). if (!result.size()) { #ifdef USE_EBOOK_CLIENT EBookClientCXX book; const char *name; name = "<<system>>"; book = EBookClientCXX::steal(e_book_client_new_system (NULL)); if (!book) { name = "<<default>>"; book = EBookClientCXX::steal(e_book_client_new_default (NULL)); } if (book) { const char *uri = e_client_get_uri (E_CLIENT ((EBookClient*)book)); result.push_back(Database(name, uri, true)); } #else eptr<EBook, GObject> book; GErrorCXX gerror; const char *name; name = "<<system>>"; book = e_book_new_system_addressbook (gerror); gerror.clear(); if (!book) { name = "<<default>>"; book = e_book_new_default_addressbook (gerror); } if (book) { const char *uri = e_book_get_uri (book); result.push_back(Database(name, uri, true)); } #endif } else { // the first DB found is the default result[0].m_isDefault = true; } return result; } #ifdef USE_EBOOK_CLIENT static void handle_error_cb (EClient */*client*/, const gchar *error_msg, gpointer user_data) { EvolutionContactSource *that = static_cast<EvolutionContactSource *>(user_data); SE_LOG_ERROR(that, NULL, "%s", error_msg); }
void EvolutionContactSource::open() { GErrorCXX gerror; bool created = false; bool onlyIfExists = false; // always try to create address book, because even if there is // a source there's no guarantee that the actual database was // created already; the original logic below for only setting // this when explicitly requesting a new address book // therefore failed in some cases #ifdef USE_EBOOK_CLIENT ESourceList *tmp; if (!e_book_client_get_sources(&tmp, gerror)) { throwError("unable to access address books", gerror); } ESourceListCXX sources(tmp, false); string id = getDatabaseID(); ESource *source = findSource(sources, id); if (!source) { // might have been special "<<system>>" or "<<default>>", try that and // creating address book from file:// URI before giving up if (id.empty() || id == "<<system>>") { m_addressbook = EBookClientCXX::steal(e_book_client_new_system (gerror)); } else if (id.empty() || id == "<<default>>") { m_addressbook = EBookClientCXX::steal(e_book_client_new_default (gerror)); } else if (boost::starts_with(id, "file://")) { m_addressbook = EBookClientCXX::steal(e_book_client_new_from_uri(id.c_str(), gerror)); } else { throwError(string(getName()) + ": no such address book: '" + id + "'"); } created = true; } else { m_addressbook = EBookClientCXX::steal(e_book_client_new( source, gerror )); } if (gerror) { throwError("create addressbook", gerror); } // Listen for errors g_signal_connect (m_addressbook, "backend-error", G_CALLBACK (handle_error_cb), this); // Handle authentication requests from the backend g_signal_connect (m_addressbook, "authenticate", G_CALLBACK (handle_authentication_cb), this); // Open the address book if (!e_client_open_sync( E_CLIENT ((EBookClient*)m_addressbook), onlyIfExists, NULL, gerror) ) { if (created) { // opening newly created address books often fails, try again once more gerror.clear(); sleep(5); if (!e_client_open_sync( E_CLIENT ((EBookClient*)m_addressbook), onlyIfExists, NULL, gerror)) { throwError("opening address book", gerror); } } else { throwError("opening address book", gerror); } } g_signal_connect_after(m_addressbook, "backend-died", G_CALLBACK(SyncContext::fatalError), (void *)"Evolution Data Server has died unexpectedly, contacts no longer available."); #else ESourceList *tmp; if (!e_book_get_addressbooks(&tmp, gerror)) { throwError("unable to access address books", gerror); } ESourceListCXX sources(tmp, false); string id = getDatabaseID(); ESource *source = findSource(sources, id); if (!source) { // might have been special "<<system>>" or "<<default>>", try that and // creating address book from file:// URI before giving up if (id.empty() || id == "<<system>>") { m_addressbook.set( e_book_new_system_addressbook (gerror), "system address book" ); } else if (id.empty() || id == "<<default>>") { m_addressbook.set( e_book_new_default_addressbook (gerror), "default address book" ); } else if (boost::starts_with(id, "file://")) { m_addressbook.set(e_book_new_from_uri(id.c_str(), gerror), "creating address book"); } else { throwError(string(getName()) + ": no such address book: '" + id + "'"); } created = true; } else { m_addressbook.set( e_book_new( source, gerror ), "address book" ); } if (!e_book_open( m_addressbook, onlyIfExists, gerror) ) { if (created) { // opening newly created address books often fails, try again once more sleep(5); if (!e_book_open(m_addressbook, onlyIfExists, gerror)) { throwError("opening address book", gerror); } } else { throwError("opening address book", gerror); } } // users are not expected to configure an authentication method, // so pick one automatically if the user indicated that he wants authentication // by setting user or password std::string user = getUser(), passwd = getPassword(); if (!user.empty() || !passwd.empty()) { GList *authmethod; if (!e_book_get_supported_auth_methods(m_addressbook, &authmethod, gerror)) { throwError("getting authentication methods", gerror); } while (authmethod) { const char *method = (const char *)authmethod->data; SE_LOG_DEBUG(this, NULL, "trying authentication method \"%s\", user %s, password %s", method, !user.empty() ? "configured" : "not configured", !passwd.empty() ? "configured" : "not configured"); if (e_book_authenticate_user(m_addressbook, user.c_str(), passwd.c_str(), method, gerror)) { SE_LOG_DEBUG(this, NULL, "authentication succeeded"); break; } else { SE_LOG_ERROR(this, NULL, "authentication failed: %s", gerror->message); } authmethod = authmethod->next; } } g_signal_connect_after(m_addressbook, "backend-died", G_CALLBACK(SyncContext::fatalError), (void *)"Evolution Data Server has died unexpectedly, contacts no longer available."); #endif }