2 /// \file EvoSources.cc
3 /// A class that creates a list of Evolution data sources.
7 Copyright (C) 2011-2012, Net Direct Inc. (http://www.netdirect.ca/)
8 Based on evolution2_sync.h and list_sources.c from evolution opensync plugin
10 Copyright (C) 2009, Ian Martin, licensed under LGPL 2.1
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU General Public License in the COPYING file at the
22 root directory of this project for more details.
25 #include "../config.h"
30 // Some versions of libical use a ring buffer for the following
31 // functions, for which the library manages memory. Somewhere along
32 // the line, this was fixed so that the application was responsible
33 // for freeing the strings returned by these functions. A warning
34 // was added to the header that would display if HANDLE_LIBICAL_MEMORY
37 // Even newer versions of evolution-data-server, which this plugin
38 // depends on, get rid of some of these functions, while newer
39 // versions of libical add _r variants that implement the
40 // application-free functinality.
42 // Since this plugin does not use these functions, we disable the
43 // warning by defining HANDLE_LIBICAL_MEMORY, then include the
47 #define HANDLE_LIBICAL_MEMORY 1
49 #include <libecal/e-cal.h>
50 #include <libebook/e-book.h>
51 #include <libedataserver/e-data-server-util.h>
53 #include "EvoSources.h"
57 void (*g_type_init
)(void);
59 gboolean (*e_book_get_addressbooks
)(ESourceList
**, GError
**);
61 gboolean (*e_cal_get_sources
)(ESourceList
**, ECalSourceType
, GError
**);
63 GSList
* (*e_source_list_peek_groups
)(ESourceList
*);
64 GSList
* (*e_source_group_peek_sources
)(ESourceGroup
*);
65 const gchar
* (*e_source_group_peek_name
)(ESourceGroup
*);
66 const gchar
* (*e_source_peek_name
)(ESource
*);
67 gchar
* (*e_source_get_uri
)(ESource
*);
72 void FetchSources(EvoFunctions
&funcs
, EvoSources::List
&list
,
76 for( g
= funcs
.e_source_list_peek_groups(sources
); g
; g
= g
->next
) {
77 ESourceGroup
*group
= (ESourceGroup
*) g
->data
;
80 for( s
= funcs
.e_source_group_peek_sources(group
); s
; s
= s
->next
) {
82 ESource
*source
= (ESource
*) s
->data
;
84 sitem
.m_GroupName
= funcs
.e_source_group_peek_name(group
);
85 sitem
.m_SourceName
= funcs
.e_source_peek_name(source
);
86 sitem
.m_SourcePath
= funcs
.e_source_get_uri(source
);
88 list
.push_back(sitem
);
93 void FetchCalendars(EvoFunctions
&funcs
, EvoSources::List
&list
,
94 ECalSourceType source_type
)
96 ESourceList
*sources
= NULL
;
97 if( funcs
.e_cal_get_sources(&sources
, source_type
, NULL
) ) {
98 FetchSources(funcs
, list
, sources
);
102 void EvoSources::LoadBaseSyms()
104 // Ideally, these functions would be loaded dynamically,
105 // but there are two problems with that, which need to be
108 // - the glib major version numbers, according to the .so
109 // files, are not consistent between distros
110 // - when used dynamically, in a program that is not otherwise
111 // linked to glib, it can segfault... and it seems to get
112 // funky somewhere inside glib itself... so I'm guessing that
113 // the library is not being initialized properly :-(
115 // All this means that general compilations of barrydesktop will
116 // need evolution-data-server and friends linked in. It is possible
117 // to compile without, but then you risk getting a weak auto-detection
118 // of data sources in newer versions of evolution. If your data
119 // sources are located in paths like this:
121 // file:///home/cdfrey/.evolution/addressbook/local/system
123 // then it is safe to disable evolution for the barrydesktop compile.
124 // Otherwise, if your version of evolution uses funkier names, or
125 // uses local:system, or puts its files under ~/.config, then
126 // build with evolution and link against it.
129 LoadSym(m_funcs->g_type_init, "g_type_init");
130 LoadSym(m_funcs->e_source_list_peek_groups,
131 "e_source_list_peek_groups");
132 LoadSym(m_funcs->e_source_group_peek_sources,
133 "e_source_group_peek_sources");
134 LoadSym(m_funcs->e_source_group_peek_name,
135 "e_source_group_peek_name");
136 LoadSym(m_funcs->e_source_peek_name, "e_source_peek_name");
137 LoadSym(m_funcs->e_source_get_uri, "e_source_get_uri");
139 m_funcs
->g_type_init
= &g_type_init
;
140 m_funcs
->e_source_list_peek_groups
= &e_source_list_peek_groups
;
141 m_funcs
->e_source_group_peek_sources
= &e_source_group_peek_sources
;
142 m_funcs
->e_source_group_peek_name
= &e_source_group_peek_name
;
143 m_funcs
->e_source_peek_name
= &e_source_peek_name
;
144 m_funcs
->e_source_get_uri
= &e_source_get_uri
;
146 m_funcs
->e_book_get_addressbooks
= &e_book_get_addressbooks
;
147 m_funcs
->e_cal_get_sources
= &e_cal_get_sources
;
150 bool EvoSources::LoadEbookLib()
153 m_funcs
.reset( new EvoFunctions
);
154 // if( !Open("libebook-1.2.so.9") )
157 // LoadSym(m_funcs->e_book_get_addressbooks, "e_book_get_addressbooks");
159 m_funcs
->g_type_init();
161 ESourceList
*sources
= NULL
;
162 if (m_funcs
->e_book_get_addressbooks(&sources
, NULL
)) {
163 FetchSources(*m_funcs
, m_addressbook
, sources
);
168 // catch( DlError & ) {
173 bool EvoSources::LoadEcalLib()
176 m_funcs
.reset( new EvoFunctions
);
177 // if( !Open("libecal-1.2.so.7") )
180 // LoadSym(m_funcs->e_cal_get_sources, "e_cal_get_sources");
182 m_funcs
->g_type_init();
184 FetchCalendars(*m_funcs
, m_events
, E_CAL_SOURCE_TYPE_EVENT
);
185 FetchCalendars(*m_funcs
, m_tasks
, E_CAL_SOURCE_TYPE_TODO
);
186 FetchCalendars(*m_funcs
, m_memos
, E_CAL_SOURCE_TYPE_JOURNAL
);
190 // catch( DlError & ) {
195 void EvoSources::Detect()
199 if( LoadEbookLib() && LoadEcalLib() ) {
209 // shutdown to unload symbols
213 bool EvoSources::IsSupported() const
218 #else // HAVE_EVOLUTION
220 // No Evolution data libraries available
222 #include "EvoSources.h"
227 void EvoSources::Detect()
232 bool EvoSources::IsSupported() const
237 #endif // HAVE_EVOLUTION
240 #include <sys/types.h>
241 #include <sys/stat.h>
247 bool EvoSources::PathExists(const std::string
&path
)
250 if( stat(path
.c_str(), &s
) == 0 ) {
251 if( S_ISDIR(s
.st_mode
) ) {
258 void SetIfExists(EvoSources::List
&list
,
259 const std::string
&group
,
260 const std::string
&name
,
261 const std::string
&dir
)
263 if( EvoSources::PathExists(dir
) ) {
266 sitem
.m_GroupName
= group
;
267 sitem
.m_SourceName
= name
;
268 sitem
.m_SourcePath
= "file://" + dir
;
270 list
.push_back(sitem
);
274 EvoSources::EvoSources()
279 void EvoSources::GuessPaths()
281 struct passwd
*pw
= getpwuid(getuid());
285 string base
= pw
->pw_dir
;
286 base
+= "/.evolution/";
288 string tail
= "/local/system";
290 SetIfExists(m_addressbook
, "Autodetect", "Addressbook", base
+ "addressbook" + tail
);
291 SetIfExists(m_events
, "Autodetect", "Events", base
+ "calendar" + tail
);
292 SetIfExists(m_tasks
, "Autodetect", "Tasks", base
+ "tasks" + tail
);
293 SetIfExists(m_memos
, "Autodetect", "Memos", base
+ "memos" + tail
);
296 void EvoSources::Clear()
298 m_addressbook
.clear();
304 bool EvoSources::IsEmpty() const
306 return m_addressbook
.empty() &&
312 bool EvoSources::IsDefaultable() const
315 // first three are required
316 m_addressbook
.size() && m_addressbook
[0].m_SourcePath
.size() &&
317 m_events
.size() && m_events
[0].m_SourcePath
.size() &&
318 m_tasks
.size() && m_tasks
[0].m_SourcePath
.size() &&
320 // and all lists must not have more than 1 item
321 m_addressbook
.size() <= 1 &&
322 m_events
.size() <= 1 &&
323 m_tasks
.size() <= 1 &&