aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/backend/ebook
diff options
context:
space:
mode:
authorEttore Perazzoli <ettore@src.gnome.org>2003-10-22 02:49:34 +0800
committerEttore Perazzoli <ettore@src.gnome.org>2003-10-22 02:49:34 +0800
commit653cfffc0e00dfb59b36813c1b45c53d3f773c65 (patch)
tree9b486d5e383ec1391d60973d9cc548be0ef6d9d5 /addressbook/backend/ebook
parent0fb08f3ff81575a4749d851404233f34252dd2f2 (diff)
downloadgsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar
gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.gz
gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.bz2
gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.lz
gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.xz
gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.zst
gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.zip
Merge new-ui-branch to the trunk.
svn path=/trunk/; revision=22965
Diffstat (limited to 'addressbook/backend/ebook')
-rw-r--r--addressbook/backend/ebook/.cvsignore1
-rw-r--r--addressbook/backend/ebook/Makefile.am114
-rw-r--r--addressbook/backend/ebook/docs/rfc2739.txt899
-rw-r--r--addressbook/backend/ebook/e-book-async.c1120
-rw-r--r--addressbook/backend/ebook/e-book-async.h107
-rw-r--r--addressbook/backend/ebook/e-book-listener.c779
-rw-r--r--addressbook/backend/ebook/e-book-listener.h42
-rw-r--r--addressbook/backend/ebook/e-book-query.c524
-rw-r--r--addressbook/backend/ebook/e-book-query.h49
-rw-r--r--addressbook/backend/ebook/e-book-types.h59
-rw-r--r--addressbook/backend/ebook/e-book-util.c808
-rw-r--r--addressbook/backend/ebook/e-book-util.h94
-rw-r--r--addressbook/backend/ebook/e-book-view-listener.c263
-rw-r--r--addressbook/backend/ebook/e-book-view-listener.h30
-rw-r--r--addressbook/backend/ebook/e-book-view.c101
-rw-r--r--addressbook/backend/ebook/e-book-view.h15
-rw-r--r--addressbook/backend/ebook/e-book.c2549
-rw-r--r--addressbook/backend/ebook/e-book.h212
-rw-r--r--addressbook/backend/ebook/e-card-compare.c706
-rw-r--r--addressbook/backend/ebook/e-card-compare.h72
-rw-r--r--addressbook/backend/ebook/e-card-cursor.c239
-rw-r--r--addressbook/backend/ebook/e-card-cursor.h53
-rw-r--r--addressbook/backend/ebook/e-card-pairs.h118
-rw-r--r--addressbook/backend/ebook/e-card-simple.c1344
-rw-r--r--addressbook/backend/ebook/e-card-simple.h234
-rw-r--r--addressbook/backend/ebook/e-card-types.h101
-rw-r--r--addressbook/backend/ebook/e-card.c2807
-rw-r--r--addressbook/backend/ebook/e-card.h209
-rw-r--r--addressbook/backend/ebook/e-contact.c1288
-rw-r--r--addressbook/backend/ebook/e-contact.h227
-rw-r--r--addressbook/backend/ebook/e-destination.h140
-rw-r--r--addressbook/backend/ebook/e-vcard.c488
-rw-r--r--addressbook/backend/ebook/e-vcard.h99
-rw-r--r--addressbook/backend/ebook/test-client-list.c65
-rw-r--r--addressbook/backend/ebook/test-client.c191
-rw-r--r--addressbook/backend/ebook/tests/Makefile.am2
-rw-r--r--addressbook/backend/ebook/tests/ebook/.cvsignore7
-rw-r--r--addressbook/backend/ebook/tests/ebook/Makefile.am12
-rw-r--r--addressbook/backend/ebook/tests/ebook/test-changes.c89
-rw-r--r--addressbook/backend/ebook/tests/ebook/test-date.c36
-rw-r--r--addressbook/backend/ebook/tests/ebook/test-ebook.c110
-rw-r--r--addressbook/backend/ebook/tests/ebook/test-photo.c59
-rw-r--r--addressbook/backend/ebook/tests/ebook/test-string.c27
-rw-r--r--addressbook/backend/ebook/tests/vcard/Makefile.am6
-rw-r--r--addressbook/backend/ebook/tests/vcard/dump-vcard.c2
45 files changed, 7065 insertions, 9432 deletions
diff --git a/addressbook/backend/ebook/.cvsignore b/addressbook/backend/ebook/.cvsignore
index e3e9c805bb..17250008f8 100644
--- a/addressbook/backend/ebook/.cvsignore
+++ b/addressbook/backend/ebook/.cvsignore
@@ -12,6 +12,7 @@ addressbook.h
test-card
test-client
test-client-list
+test-ebook
load-pine-addressbook
load-gnomecard-addressbook
evolution-vcard-importer
diff --git a/addressbook/backend/ebook/Makefile.am b/addressbook/backend/ebook/Makefile.am
index 9d2b6d1b05..e83e3e1411 100644
--- a/addressbook/backend/ebook/Makefile.am
+++ b/addressbook/backend/ebook/Makefile.am
@@ -1,16 +1,7 @@
-noinst_PROGRAMS = test-card test-client test-client-list
-
-privlibexec_PROGRAMS = \
- evolution-vcard-importer \
- evolution-ldif-importer
-
-toolsdir = $(privlibexecdir)/
-tools_PROGRAMS = \
- load-pine-addressbook \
- load-gnomecard-addressbook
-
# CORBA stuff
+SUBDIRS = . tests
+
CORBA_ADDRESSBOOK_SOURCE_H = \
addressbook.h
CORBA_ADDRESSBOOK_SOURCE_C = \
@@ -38,13 +29,10 @@ INCLUDES = \
-DLIBDIR=\"$(libdir)\" \
-DG_LOG_DOMAIN=\"EBook\" \
-I$(top_srcdir) \
- -I$(top_srcdir)/camel \
-I$(top_srcdir)/addressbook/backend \
-I$(top_srcdir)/addressbook/ename \
-I$(top_builddir)/addressbook/backend \
-I$(top_builddir)/addressbook/ename \
- -I$(top_builddir)/shell \
- -I$(top_srcdir)/shell \
-DG_DISABLE_DEPRECATED \
-DLIBGNOME_DISABLE_DEPRECATED \
$(EVOLUTION_ADDRESSBOOK_CFLAGS)
@@ -53,113 +41,39 @@ privlib_LTLIBRARIES = libebook.la
libebook_la_SOURCES = \
$(CORBA_SOURCE) \
- e-book-listener.c \
+ addressbook.h \
e-book-marshal.c \
+ e-book-query.c \
e-book-view-listener.c \
e-book-view.c \
+ e-book-listener.c \
e-book.c \
- e-book-util.c \
- e-card-cursor.c \
- e-card-simple.c \
- e-card.c \
- e-card-compare.c \
- e-destination.c
+ e-book-async.c \
+ e-contact.c \
+ e-vcard.c
libebook_la_LIBADD = \
$(top_builddir)/libversit/libversit.la \
- $(top_builddir)/camel/libcamel.la \
$(top_builddir)/e-util/ename/libename.la \
$(top_builddir)/e-util/libeutil.la
libebookincludedir = $(privincludedir)/ebook
libebookinclude_HEADERS = \
- e-book-listener.h \
- e-book-types.h \
+ e-book-query.h \
e-book-view-listener.h \
e-book-view.h \
+ e-book-types.h \
+ e-book-listener.h \
e-book.h \
- e-book-util.h \
- e-card-cursor.h \
- e-card-simple.h \
- e-card-types.h \
- e-card.h \
- e-card-compare.h \
- e-destination.h \
- addressbook.h
-
+ e-contact.h \
+ e-vcard.h
MARSHAL_GENERATED = e-book-marshal.c e-book-marshal.h
@EVO_MARSHAL_RULE@
-test_client_SOURCES = \
- test-client.c
-
-test_client_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
-
-test_client_list_SOURCES = \
- test-client-list.c
-
-test_client_list_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
-
-test_card_SOURCES = \
- test-card.c
-
-test_card_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
-
-evolution_vcard_importer_SOURCES = \
- evolution-vcard-importer.c
-
-evolution_vcard_importer_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS) \
- $(top_builddir)/shell/importer/libevolution-importer.la \
- $(DB3_LDADD)
-
-evolution_ldif_importer_SOURCES = \
- evolution-ldif-importer.c
-
-evolution_ldif_importer_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS) \
- $(top_builddir)/shell/importer/libevolution-importer.la \
- $(DB3_LDADD)
-
-load_pine_addressbook_SOURCES = \
- load-pine-addressbook.c
-
-load_pine_addressbook_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
-
-load_gnomecard_addressbook_SOURCES = \
- load-gnomecard-addressbook.c
-
-load_gnomecard_addressbook_LDADD = \
- libebook.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
-
-
-BUILT_SOURCES = $(CORBA_SOURCE) $(MARSHAL_GENERATED) $(server_DATA)
+BUILT_SOURCES = $(CORBA_SOURCE) $(MARSHAL_GENERATED)
CLEANFILES = $(BUILT_SOURCES)
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
-
-server_in_files = GNOME_Evolution_Addressbook_VCard_Importer.server.in.in \
- GNOME_Evolution_Addressbook_LDIF_Importer.server.in.in
-
-server_DATA = $(server_in_files:.server.in.in=.server)
-%.server.in: %.server.in.in
- sed -e "s|\@LIBEXECDIR\@|$(privlibexecdir)|" $< > $@
-
-
-@INTLTOOL_SERVER_RULE@
-
-EXTRA_DIST = $(server_in_files) $(server_DATA) e-book-marshal.list
diff --git a/addressbook/backend/ebook/docs/rfc2739.txt b/addressbook/backend/ebook/docs/rfc2739.txt
new file mode 100644
index 0000000000..5c1dbbcf77
--- /dev/null
+++ b/addressbook/backend/ebook/docs/rfc2739.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group T. Small
+Request for Comments: 2739 XpertSite.Com
+Category: Standards Track D. Hennessy
+ ISOCOR
+ F. Dawson
+ Lotus
+ January 2000
+
+
+ Calendar Attributes for vCard and LDAP
+
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ When scheduling a calendar entity, such as an event, it is a
+ prerequisite that an organizer has the calendar address of each
+ attendee that will be invited to the event. Additionally, access to
+ an attendee's current "busy time" provides an a priori indication of
+ whether the attendee will be free to participate in the event.
+
+ In order to meet these challenges, a calendar user agent (CUA) needs
+ a mechanism to locate (URI) individual user's calendar and free/busy
+ time.
+
+ This memo defines three mechanisms for obtaining a URI to a user's
+ calendar and free/busy time. These include:
+
+ - Manual transfer of the information;
+
+ - Personal data exchange using the vCard format; and
+
+ - Directory lookup using the LDAP protocol.
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 1]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+Table of Contents
+
+ 1 CALENDARING AND SCHEDULING URIS...................................3
+ 1.1 FREE/BUSY URI (FBURL) .........................................3
+ 1.2 CALENDAR ACCESS URI (CAPURI) ..................................4
+ 1.3 CALENDAR URI (CALURI) .........................................4
+ 1.4 DEFAULT URIS ..................................................4
+ 2 DISTRIBUTION......................................................4
+ 2.1 MANUAL TRANSFER ...............................................5
+ 2.2 PERSONAL DATA EXCHANGE USING A VCARD ..........................5
+ 2.3 VCARD SCHEMA EXTENSIONS .......................................5
+ 2.3.1 FBURL Property IANA Registration ...........................6
+ 2.3.2 CALADRURI Property IANA Registration .......................7
+ 2.3.3 CAPURI Property IANA Registration ......................... 8
+ 2.3.4 CALURI Property IANA Registration ......................... 8
+ 2.4 DIRECTORY LOOKUP USING THE LDAP V3 PROTOCOL .................. 9
+ 2.4.1 LDAP Schema Extensions .................................... 9
+ 2.4.2 Notation ..................................................10
+ 2.4.3 Object Definitions ........................................10
+ 2.4.3.1 calEntry ..............................................10
+ 2.4.4 Attribute Definitions .....................................10
+ 2.4.4.1 calCalURI .............................................10
+ 2.4.4.2 calFBURL ..............................................10
+ 2.4.4.3 calCAPURI .............................................11
+ 2.4.4.4 calCalAdrURI ..........................................11
+ 2.4.4.5 calOtherCalURIs .......................................11
+ 2.4.4.6 calOtherFBURLs ........................................11
+ 2.4.4.7 calOtherCAPURIs .......................................12
+ 2.4.4.8 calOtherCalAdrURIs ....................................12
+ 3 IANA Considerations..............................................12
+ 4 Security Considerations..........................................12
+ 5 Acknowledgments..................................................13
+ 6 Authors' Addresses...............................................13
+ 7 Bibliography.....................................................15
+ 8 Full Copyright Statement.........................................16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 2]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+1 Calendaring and Scheduling URIs
+
+ This memo defines four classes of URIs. URIs are more useful if it is
+ understood what the URIs point to. Here is a brief description:
+
+1.1 Free/Busy URI (FBURL)
+
+ The free/busy URI is defined to be a transport independent location
+ where a client can obtain information about when a user is busy. At
+ the present time, this URI only points to busy time data. Future
+ revisions of this specification may provide for the extended
+ capability of publishing free time data.
+
+ If a calendaring and scheduling client (i.e., CUA) were to retrieve
+ data from this location using FTP or HTTP, it would get back an
+ iCalendar object [4] containing one or more "VFREEBUSY" calendar
+ components. If a MIME transport is being used, the response will be
+ contained within a "text/calendar" MIME body part as specified in the
+ iCalendar specification [4]. For example:
+
+ BEGIN:VCALENDAR
+ VERSION:2.0
+ PRODID:-//hacksw/handcal//NONSGML v1.0//EN
+ METHOD:PUBLISH
+ BEGIN:VFREEBUSY
+ ATTENDEE:MAILTO:jane_doe@host1.com
+ DTSTART:19971013T050000Z
+ DTEND:19971124T050000Z
+ DTSTAMP:19970901T083000Z
+ FREEBUSY:19971015T133000Z/19971015T180000Z
+ FREEBUSY:19971015T190000Z/19971015T220000Z
+ FBURL:http://www.host.com/calendar/busy/jdoe.ifb
+ END:VFREEBUSY
+ END:VCALENDAR
+
+ The amount of busy time data pointed to by the FBURL will generally
+ be pre-determined; for example one month of busy time data. As a
+ guideline, it is recommended that the previous six weeks of busy time
+ data be published at the location associated with the FBURL. If this
+ URI points to a file resource, it is recommended that the file
+ extension be "ifb" to distinguish it from an arbitrary iCalendar
+ object (e.g., with the "ics" file extension).
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 3]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+1.2 Calendar Access URI (CAPURI)
+
+ The Calendar Access URI is defined to be a protocol independent
+ location from which a calendaring and scheduling client (i.e., CUA)
+ can communicate with a user's entire calendar.
+
+ The semantics for using this URI as an access protocol locator are
+ yet to be defined by the IETF CALSCH Working Group. This will be
+ addressed in the "Calendar Access Protocol" specification.
+
+1.3 Calendar URI (CALURI)
+
+ The Calendar URI is defined to be a protocol independent location
+ from which a calendaring and scheduling client (i.e. CUA) can
+ retrieve an entire copy of a user's calendar. Retrieving data from
+ this URI obtains a published "snapshot" of the user's calendar.
+
+ HTTP URI -- If the URI is an HTTP URI, then the content returned with
+ a GET should be a "text/calendar" MIME body part containing one or
+ more iCalendar object.
+
+ FTP URI -- If the URI is an FTP URI, then the resource pointed to
+ should be a file with an "ics" file extension containing one or more
+ iCalendar objects.
+
+1.4 Default URIs
+
+ There are many cases where a user may have more than one calendar. In
+ these cases, a user may have multiple URIs, each URI pointing to a
+ calendar or free/busy data.
+
+ To make the case of multiple calendars simpler for clients, the
+ concept of the "default" calendar is introduced. A "default" calendar
+ is one that the user has designated as the calendar that other users
+ should look at when accessing the user's calendar, or retrieving the
+ user's free/busy time.
+
+ The default calendar may, in fact, include rolled-up information from
+ all the user's other calendars. The other calendars may only exist
+ for organizational purposes.
+
+2 Distribution
+
+ These four URIs provide valuable pointers to calendaring and
+ scheduling data that other users need in order to know when to
+ schedule meetings, etc. There are several possibilities on how users
+ can communicate these URIs to other users. The following section
+ outlines how these URIs can be distributed to other users.
+
+
+
+Small, et al. Standards Track [Page 4]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+2.1 Manual Transfer
+
+ The simplest way to obtain these URIs is for a user to communicate
+ the URIs using some out-of-band mechanism such as verbally, or in an
+ e-mail message, or by printing these URIs on a paper business card.
+
+ When using this mechanism, the user obtains these URIs using an out-
+ of-band mechanism and then enters these URIs into their calendaring
+ software manually.
+
+2.2 Personal Data Exchange Using A vCard
+
+ A more sophisticated way to obtain these URIs is for users to publish
+ vCards containing these URIs. The vCard object can be transferred
+ between one another. Since many e-mail clients allow a user to
+ automatically include a vCard with every message that the user sends,
+ this provides a simple, transparent way for a user to distribute
+ their calendaring and scheduling URIs.
+
+ On the receiving end, an e-mail client that provides an integrated
+ vCard database can provide a way to lookup calendaring URIs for users
+ whose vCards are stored locally.
+
+2.3 vCard Schema Extensions
+
+ Since the vCard [3] specification doesn't specify how to encode
+ calendaring URIs in a vCard, this section is provided as an extension
+ to vCard which specifies how to encode calendaring URIs within a
+ vCard.
+
+ Inside a vCard object, four new properties are defined: "CALURI",
+ "CAPURI", "CALADRURI", and "FBURL", as defined above.
+
+ Any vCard can have one or more of these properties, each representing
+ a calendar or free/busy time that is associated with the user.
+
+ One of these properties can be designated as the "default" by adding
+ the "PREF" parameter.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 5]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ Here is a simple example of a vCard containing a "FBURL" and a
+ "CALURI".
+
+ BEGIN:VCARD
+ VERSION:3.0
+ N:Dun;Alec
+ FN:Alec Dun
+ ORG:Microsoft Corporation
+ ADR;WORK;POSTAL;PARCEL:;;One Microsoft Way;
+ Redmond;WA;98052-6399;USA
+ TEL;WORK;MSG:+1-206-936-4544
+ TEL;WORK;FAX:+1-206-936-7329
+ EMAIL;INTERNET:user@host1.com
+ CALADRURI;PREF:mailto:user@host1.com
+ CALURI;PREF:http://cal.host1.com/user/cal.ics
+ FBURL;PREF:http://cal.host1.com/user/fb.ifb
+ CALURI:http://cal.company.com/projectA/pjtA.ics
+ FBURL:http://cal.company.com/projectA/pjtAfb.ifb
+ END:VCARD
+
+2.3.1 FBURL Property IANA Registration
+
+ To: ietf-mime-directory@imc.org
+
+ Subject: Registration of FBURL type for text/directory MIME type
+ vCard profile.
+
+ Type name: FBURL
+
+ Type purpose: To specify the URI for a user's busy time in a vCard
+ object.
+
+ Type encoding: 8bit
+
+ Type value: A single URI value.
+
+ Type special notes: Where multiple FBURL properties are specified,
+ the default FBURL property is indicated with the PREF parameter. The
+ FTP or HTTP type of URI points to an iCalendar object associated with
+ a snapshot of the last six weeks of the user's busy time data. If the
+ iCalendar object is represented as a file or document, it's file type
+ should be "ifb".
+
+ Intended usage: Refer to section 1.1.
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 6]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ Type examples:
+
+ FBURL;PREF:http://www.host1.com/busy/janedoe
+ FBURL:FTP://ftp.host.com/busy/project-a.ifb
+
+2.3.2 CALADRURI Property IANA Registration
+
+ To: ietf-mime-directory@imc.org
+
+ Subject: Registration of CALADRURI type for application/directory
+ MIME type vCard profile.
+
+ Type name: CALADRURI
+
+ Type purpose: To specify the location to which an event request
+ should be sent for the user.
+
+ Type encoding: 8bit
+
+ Type value: A single URI value.
+
+ Type special notes: Where multiple CALADRURI properties are
+ specified, the default CALADRURI property is indicated with the PREF
+ parameter.
+
+ Intended usage: Refer to section 1.2.
+
+ Type examples:
+
+ CALADRURI;PREF:mailto:janedoe@host.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 7]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+2.3.3 CAPURI Property IANA Registration
+
+ To: ietf-mime-directory@imc.org
+
+ Subject: Registration of CAPURI type for application/directory MIME
+ type vCard profile.
+
+ Type name: CAPURI
+
+ Type purpose: To specify a protocol independent location from which a
+ calendaring and scheduling client (i.e., CUA) can communicate with a
+ user's entire calendar.
+
+ Type encoding: 8bit
+
+ Type value: A single URI value.
+
+ Type special notes: Where multiple CAPURI properties are specified,
+ the default CAPURI property is indicated with the PREF parameter.
+
+ Intended usage: Refer to section 1.3.
+
+2.3.4 CALURI Property IANA Registration
+
+ To: ietf-mime-directory@imc.org
+
+ Subject: Registration of CALURI type for text/directory MIME type
+ vCard profile.
+
+ Type name: CALURI
+
+ Type purpose: To specify the URI for a user's calendar in a vCard
+ object.
+
+ Type encoding: 8bit
+
+ Type value type: A single URI value.
+
+ Type special notes: Where multiple CALURI properties are specified,
+ the default CALURI property is indicated with the PREF parameter. The
+ property should contain a URI pointing to an iCalendar object
+ associated with a snapshot of the user's calendar store. If the
+ iCalendar object is represented as a file or document, it's file type
+ should be "ics".
+
+ Intended usage: Refer to section 1.4.
+
+
+
+
+
+Small, et al. Standards Track [Page 8]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ Type examples:
+
+ CALURI;PREF:http://cal.host1.com/calA
+ CALURI:ftp://ftp.host1.com/calA.ics
+
+2.4 Directory Lookup Using The LDAP v3 Protocol
+
+ Another way to obtain these URIs is to look them up in a directory
+ using the LDAP protocol [1].
+
+ If a user's URIs can be found using directory lookup (i.e., searching
+ for one of the LDAP schema extensions defined below), they should, in
+ general, be considered "more up-to-date" than URIs in any vCards that
+ are stored locally.
+
+2.4.1 LDAP Schema Extensions
+
+ In order to encode the calendaring URIs in the directory, the
+ following are defined:
+
+ - One object class:
+
+ - calEntry
+
+ - Eight attributes:
+
+ - calCalURI
+
+ - calFBURL
+
+ - calCAPURI
+
+ - calCalAdrURI
+
+ - calOtherCalURIs
+
+ - calOtherFBURLs
+
+ - calOtherCAPURIs
+
+ - calOtherCalAdrURIs
+
+ The calCalURI contains the URI to a snapshot of the user's entire
+ default calendar. The calFBURL contains the URI to the user's default
+ busy time data. The calCAPURI represents contains a URI that can be
+ used to communicate with the user's calendar. The calCalAdrURI
+ contains a URI that points to the location to which event requests
+ should be sent for that user.
+
+
+
+Small, et al. Standards Track [Page 9]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ The calOtherCalURIs is a multi-valued property containing URIs to
+ snapshots of other calendars that the user may have. The
+ calOtherFBURLs is a multi-valued property containing URIs to other
+ free/busy data that the user may have. The calOtherCAPURIs attribute
+ is a multi-valued property containing URIs to other calendars that
+ the user may have. The calOtherCalAdrURIs attribute is a multi-valued
+ property containing URIs to other locations that a user may want
+ event requests sent to.
+
+ There is no predetermined order to the values in either multi-valued
+ property.
+
+2.4.2 Notation
+
+ The notation used in this memo is the same as that used in [2].
+
+2.4.3 Object Definitions
+
+2.4.3.1 calEntry
+
+ The Calendar Entry is a class derived from "TOP" [2], which contains
+ the four calendaring attributes.
+
+ (1.2.840.113556.1.5.87
+ NAME 'calEntry'
+ TOP
+ AUXILIARY
+ MAY (calCalURI calFBURL calOtherCalURIs calOtherFBURLs calCAPURI
+ calOtherCAPURLs)
+ )
+
+2.4.4 Attribute Definitions
+
+2.4.4.1 calCalURI
+
+ (1.2.840.113556.1.4.478
+ NAME 'calCalURI'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ USAGE userApplications
+ )
+
+2.4.4.2 calFBURL
+
+ (1.2.840.113556.1.4.479
+ NAME 'calFBURL'
+ EQUALITY caseIgnoreMatch
+
+
+
+Small, et al. Standards Track [Page 10]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ USAGE userApplications
+ )
+
+2.4.4.3 calCAPURI
+
+ (1.2.840.113556.1.4.480
+ NAME 'calCAPURI'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ USAGE userApplications
+ )
+
+2.4.4.4 calCalAdrURI
+
+ (1.2.840.113556.1.4.481
+ NAME 'calCalAdrURI'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ USAGE userApplications
+ )
+
+2.4.4.5 calOtherCalURIs
+
+ (1.2.840.113556.1.4.482
+ NAME 'calOtherCalURIs'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ MULTI-VALUE
+ USAGE userApplications
+ )
+
+2.4.4.6 calOtherFBURLs
+
+ (1.2.840.113556.1.4.483
+ NAME 'calOtherFBURLs'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ MULTI-VALUE
+ USAGE userApplications
+ )
+
+
+
+
+
+Small, et al. Standards Track [Page 11]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+2.4.4.7 calOtherCAPURIs
+
+ (1.2.840.113556.1.4.484
+ NAME 'calOtherCAPURIs'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ MULTI-VALUE
+ USAGE userApplications
+ )
+
+2.4.4.8 calOtherCalAdrURIs
+
+ (1.2.840.113556.1.4.485
+ NAME 'calOtherCalAdrURIs'
+ EQUALITY caseIgnoreMatch
+ SUBSTRING caseIgnoreMatch
+ SYNTAX 'IA5String'
+ MULTI-VALUE
+ USAGE userApplications
+ )
+
+3 IANA Considerations
+
+ This memo defines IANA registered extensions to the attributes
+ defined by LDAP [1] and vCard [3].
+
+ IANA registration proposals for vCard are to be emailed to the
+ registration agent for the "text/directory" MIME content-type,
+ <MAILTO: ietf-mime-directory@imc.org> using the format defined in
+ [3].
+
+4 Security Considerations
+
+ Standard vCard and LDAP security rules and support apply for the
+ extensions described in this document, and there are no special
+ security issues for these extensions.
+
+ Please note, though, that LDAP servers may permit anonymous clients
+ to refresh entries which they did not create. Servers are also
+ permitted to control a refresh access to an entry by requiring
+ clients to bind before issuing a RefreshRequest. This will have
+ implications on the server performance and scalability.
+
+ Please also note, though, that vCard objects may have been created by
+ an entity other than that represented by the vCard. Recipients should
+ be certain of the source that generated the vCard.
+
+
+
+
+Small, et al. Standards Track [Page 12]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ Also, care should be taken in making use of information obtained from
+ directory servers that has been supplied by client, as it may now be
+ out of date. In many networks, for example, IP addresses are
+ automatically assigned when a host connects to the network, and may
+ be reassigned if that host later disconnects. An IP address obtained
+ from the directory may no longer be assigned to the host that placed
+ the address in the directory. This issue is not specific to LDAP or
+ dynamic directories.
+
+5 Acknowledgments
+
+ The authors wish to acknowledge the work of Alec Dun, who acted as an
+ author for the early drafts of this memo. In addition, this document
+ received input from the various participants in the IETF CALSCH
+ Working Group discussions.
+
+6 Authors' Addresses
+
+ The following address information is provided in a vCard v3.0 [3],
+ Electronic Business Card, format.
+
+ BEGIN:VCARD
+ VERSION:3.0
+ N:Small;Tony
+ FN:Tony Small
+ ORG:XpertSite.Com
+ ADR;TYPE=WORK,POSTAL,PARCEL:;;4700 42nd Ave. SW, Suite 440;
+ Seattle;WA;98116;USA
+ TEL;TYPE=WORK,MSG:+1-206-937-9972
+ TEL;TYPE=WORK,FAX:+1-206-936-7329
+ EMAIL;TYPE=INTERNET:tony@xpertsite.com
+ CALADRURI:MAILTO:tony@xpertsite.com
+ END:VCARD
+
+ BEGIN:VCARD
+ VERSION:3.0
+ N:Hennessy;Denis
+ FN:Denis Hennessy
+ ORG:ISOCOR
+ ADR;TYPE=WORK,POSTAL,PARCEL:;;42-47 Lower Mount St;
+ Dublin 2;Ireland
+ TEL;TYPE=WORK,MSG:+353-1-676-0366
+ TEL;TYPE=WORK,FAX:+353-1-676-0856
+ EMAIL;TYPE=INTERNET:denis.hennessy@isocor.com
+ CALADRURI:MAILTO:denis.hennessy@isocor.com
+ END:VCARD
+
+
+
+
+
+Small, et al. Standards Track [Page 13]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+ BEGIN:VCARD
+ VERSION:3.0
+ N:Dawson;Frank
+ FN:Frank Dawson
+ ORG:Lotus Development Corporation
+ ADR;TYPE=WORK,POSTAL,PARCEL:;;6544 Battleford Drive;
+ Raleigh;NC;27613-3502;USA
+ TEL;TYPE=WORK,PREF:+1-617-693-8728
+ TEL;TYPE=WORK,MSG:+1-919-676-9515
+ TEL;TYPE=FAX:+1-617-693-8728
+ EMAIL;TYPE=INTERNET,PREF:Frank_Dawson@Lotus.com
+ EMAIL;TYPE=INTERNET:fdawson@earthlink.net
+ CALADRURI;TYPE=PREF:MAILTO:Frank_Dawson@Lotus.com
+ CALADRURI:MAILTO:fdawson@earthlink.net
+ URL:http://home.earthlink.net/~fdawson
+ END:VCARD
+
+ This memo is a result of the work of the Internet Engineering Task
+ Force Calendaring and scheduling Working Group. The chairman of that
+ working group is:
+
+ BEGIN:VCARD
+ VERSION:3.0
+ N:Egen;Pat
+ FN:Pat Egen
+ ORG:Engan Consulting
+ ADR;TYPE=WORK:;;803 Creek Overlook;Chattanooga;TN;37415;USA
+ TEL;TYPE=WORK,VOICE:423.875.2652
+ TEL;TYPE=WORK,FAX:423.875.2017
+ EMAIL:pregen@egenconsulting.com
+ URL:http://www.egenconsulting.com
+ CALADRURI:MAILTO:pregen@egenconsulting.com
+ END:VCARD
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 14]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+7 Bibliography
+
+ [1] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory Access
+ Protocol (v3)", RFC 2251, December 1997.
+
+ [2] Wahl, M., Coulbeck, A., Howes, T. and S. Kille, "Lightweight
+ Directory Access Protocol (v3): Attribute Syntax Definitions",
+ RFC 2252, December 1997.
+
+ [3] Dawson, F. and T. Howes, "vCard MIME Directory Profile", RFC
+ 2426, September 1998.
+
+ [4] Dawson, F. and D. Stenerson, "Internet Calendaring and Scheduling
+ Core Object Specification (iCalendar)", RFC 2445, November 1997.
+
+ [5] Dawson, F. and S. Mansour, "iCalendar Message-Based
+ Interopability Protocal (iMIP)", RFC 2447, November 1997.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 15]
+
+RFC 2739 Locating a Calendar User January 2000
+
+
+8 Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Small, et al. Standards Track [Page 16]
+
diff --git a/addressbook/backend/ebook/e-book-async.c b/addressbook/backend/ebook/e-book-async.c
new file mode 100644
index 0000000000..2ccc565eb9
--- /dev/null
+++ b/addressbook/backend/ebook/e-book-async.c
@@ -0,0 +1,1120 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include "ebook/e-book-async.h"
+
+static GThread *worker_thread;
+static GAsyncQueue *to_worker_queue;
+static GAsyncQueue *from_worker_queue;
+
+typedef struct _EBookMsg EBookMsg;
+
+typedef void (*EBookMsgHandler)(EBookMsg* msg);
+typedef void (*EBookMsgDtor)(EBookMsg* msg);
+
+struct _EBookMsg {
+ EBookMsgHandler handler;
+ EBookMsgDtor dtor;
+};
+
+static gpointer
+worker (gpointer data)
+{
+ while (TRUE) {
+ EBookMsg *msg = g_async_queue_pop (to_worker_queue);
+ msg->handler (msg);
+ msg->dtor (msg);
+ }
+
+ return NULL;
+}
+
+static gboolean
+main_thread_check_for_response (gpointer data)
+{
+ EBookMsg *msg;
+
+ while ((msg = g_async_queue_try_pop (from_worker_queue)) != NULL) {
+ msg->handler (msg);
+ msg->dtor (msg);
+ }
+
+ return TRUE;
+}
+
+static void
+e_book_msg_init (EBookMsg *msg, EBookMsgHandler handler, EBookMsgDtor dtor)
+{
+ msg->handler = handler;
+ msg->dtor = dtor;
+}
+
+static void
+init_async()
+{
+ static gboolean init_done = FALSE;
+ if (!init_done) {
+ init_done = TRUE;
+ to_worker_queue = g_async_queue_new ();
+ from_worker_queue = g_async_queue_new ();
+ worker_thread = g_thread_create (worker, NULL, FALSE, NULL);
+ g_timeout_add (300, main_thread_check_for_response, NULL);
+ }
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ char *uri;
+ EBookCallback open_response;
+ gpointer closure;
+} LoadUriMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ EBookCallback open_response;
+ gpointer closure;
+} LoadUriResponse;
+
+static void
+_load_uri_response_handler (EBookMsg *msg)
+{
+ LoadUriResponse *resp = (LoadUriResponse*)msg;
+
+ resp->open_response (resp->book, resp->status, resp->closure);
+}
+
+static void
+_load_uri_response_dtor (EBookMsg *msg)
+{
+ LoadUriResponse *resp = (LoadUriResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_load_uri_handler (EBookMsg *msg)
+{
+ LoadUriMsg *uri_msg = (LoadUriMsg *)msg;
+ LoadUriResponse *response;
+ GError *error = NULL;
+
+ response = g_new (LoadUriResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _load_uri_response_handler, _load_uri_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_load_uri (uri_msg->book, uri_msg->uri, FALSE, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+
+ response->book = uri_msg->book;
+ response->open_response = uri_msg->open_response;
+ response->closure = uri_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_load_uri_dtor (EBookMsg *msg)
+{
+ LoadUriMsg *uri_msg = (LoadUriMsg *)msg;
+
+ g_free (uri_msg->uri);
+ g_free (uri_msg);
+}
+
+void
+e_book_async_load_uri (EBook *book,
+ const char *uri,
+ EBookCallback open_response,
+ gpointer closure)
+{
+ LoadUriMsg *msg;
+
+ init_async ();
+
+ msg = g_new (LoadUriMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _load_uri_handler, _load_uri_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->uri = g_strdup (uri);
+ msg->open_response = open_response;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+}
+
+
+void
+e_book_async_unload_uri (EBook *book)
+{
+ e_book_unload_uri (book, NULL);
+}
+
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBookCallback open_response;
+ gpointer closure;
+} DefaultBookMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ EBookCallback open_response;
+ gpointer closure;
+} DefaultBookResponse;
+
+static void
+_default_book_response_handler (EBookMsg *msg)
+{
+ LoadUriResponse *resp = (LoadUriResponse*)msg;
+
+ resp->open_response (resp->book, resp->status, resp->closure);
+}
+
+static void
+_default_book_response_dtor (EBookMsg *msg)
+{
+ LoadUriResponse *resp = (LoadUriResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_default_book_handler (EBookMsg *msg)
+{
+ DefaultBookMsg *dfb_msg = (DefaultBookMsg *)msg;
+ DefaultBookResponse *response;
+ GError *error = NULL;
+
+ response = g_new (DefaultBookResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _default_book_response_handler, _default_book_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_get_default_addressbook (&response->book, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+
+ response->open_response = dfb_msg->open_response;
+ response->closure = dfb_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_default_book_dtor (EBookMsg *msg)
+{
+ DefaultBookMsg *dfb_msg = (DefaultBookMsg *)msg;
+
+ g_free (dfb_msg);
+}
+
+void
+e_book_async_get_default_addressbook (EBookCallback open_response,
+ gpointer closure)
+{
+ DefaultBookMsg *msg;
+
+ init_async ();
+
+ msg = g_new (DefaultBookMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _default_book_handler, _default_book_dtor);
+
+ msg->open_response = open_response;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookFieldsCallback cb;
+ gpointer closure;
+} GetFieldsMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ GList *fields;
+ EBookFieldsCallback cb;
+ gpointer closure;
+} GetFieldsResponse;
+
+static void
+_get_fields_response_handler (EBookMsg *msg)
+{
+ GetFieldsResponse *resp = (GetFieldsResponse*)msg;
+ GList *l;
+ EList *fields = e_list_new ((EListCopyFunc) g_strdup,
+ (EListFreeFunc) g_free,
+ NULL);
+
+ for (l = resp->fields; l; l = l->next)
+ e_list_append (fields, l->data);
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, fields, resp->closure);
+
+ g_object_unref (fields);
+}
+
+static void
+_get_fields_response_dtor (EBookMsg *msg)
+{
+ GetFieldsResponse *resp = (GetFieldsResponse*)msg;
+
+ g_list_foreach (resp->fields, (GFunc)g_free, NULL);
+ g_list_free (resp->fields);
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_get_fields_handler (EBookMsg *msg)
+{
+ GetFieldsMsg *fields_msg = (GetFieldsMsg *)msg;
+ GetFieldsResponse *response;
+ GError *error = NULL;
+
+ response = g_new (GetFieldsResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _get_fields_response_handler, _get_fields_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_get_supported_fields (fields_msg->book, &response->fields, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = fields_msg->book;
+ response->cb = fields_msg->cb;
+ response->closure = fields_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+guint
+e_book_async_get_supported_fields (EBook *book,
+ EBookFieldsCallback cb,
+ gpointer closure)
+{
+ GetFieldsMsg *msg;
+
+ init_async ();
+
+ msg = g_new (GetFieldsMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _get_fields_handler, (EBookMsgDtor)g_free);
+
+ msg->book = g_object_ref (book);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return 0;
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookAuthMethodsCallback cb;
+ gpointer closure;
+} GetMethodsMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ GList *methods;
+ EBookAuthMethodsCallback cb;
+ gpointer closure;
+} GetMethodsResponse;
+
+static void
+_get_methods_response_handler (EBookMsg *msg)
+{
+ GetMethodsResponse *resp = (GetMethodsResponse*)msg;
+ GList *l;
+ EList *methods = e_list_new ((EListCopyFunc) g_strdup,
+ (EListFreeFunc) g_free,
+ NULL);
+
+ for (l = resp->methods; l; l = l->next)
+ e_list_append (methods, l->data);
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, methods, resp->closure);
+
+ g_object_unref (methods);
+}
+
+static void
+_get_methods_response_dtor (EBookMsg *msg)
+{
+ GetMethodsResponse *resp = (GetMethodsResponse*)msg;
+
+ g_list_foreach (resp->methods, (GFunc)g_free, NULL);
+ g_list_free (resp->methods);
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_get_methods_handler (EBookMsg *msg)
+{
+ GetMethodsMsg *methods_msg = (GetMethodsMsg *)msg;
+ GetMethodsResponse *response;
+ GError *error = NULL;
+
+ response = g_new (GetMethodsResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _get_methods_response_handler, _get_methods_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_get_supported_auth_methods (methods_msg->book, &response->methods, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+
+ response->book = methods_msg->book;
+ response->cb = methods_msg->cb;
+ response->closure = methods_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+guint
+e_book_async_get_supported_auth_methods (EBook *book,
+ EBookAuthMethodsCallback cb,
+ gpointer closure)
+{
+ GetMethodsMsg *msg;
+
+ init_async ();
+
+ msg = g_new (GetMethodsMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _get_methods_handler, (EBookMsgDtor)g_free);
+
+ msg->book = g_object_ref (book);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return 0;
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ char *user;
+ char *passwd;
+ char *auth_method;
+ EBookCallback cb;
+ gpointer closure;
+} AuthUserMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ EBookCallback cb;
+ gpointer closure;
+} AuthUserResponse;
+
+static void
+_auth_user_response_handler (EBookMsg *msg)
+{
+ AuthUserResponse *resp = (AuthUserResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->closure);
+}
+
+static void
+_auth_user_response_dtor (EBookMsg *msg)
+{
+ AuthUserResponse *resp = (AuthUserResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_auth_user_handler (EBookMsg *msg)
+{
+ AuthUserMsg *auth_msg = (AuthUserMsg *)msg;
+ AuthUserResponse *response;
+ GError *error = NULL;
+
+ response = g_new (AuthUserResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _auth_user_response_handler, _auth_user_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_authenticate_user (auth_msg->book, auth_msg->user, auth_msg->passwd, auth_msg->auth_method, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = auth_msg->book;
+ response->cb = auth_msg->cb;
+ response->closure = auth_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_auth_user_dtor (EBookMsg *msg)
+{
+ AuthUserMsg *auth_msg = (AuthUserMsg *)msg;
+
+ g_free (auth_msg->user);
+ g_free (auth_msg->passwd);
+ g_free (auth_msg->auth_method);
+
+ g_free (auth_msg);
+}
+
+/* User authentication. */
+void
+e_book_async_authenticate_user (EBook *book,
+ const char *user,
+ const char *passwd,
+ const char *auth_method,
+ EBookCallback cb,
+ gpointer closure)
+{
+ AuthUserMsg *msg;
+
+ init_async ();
+
+ msg = g_new (AuthUserMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _auth_user_handler, _auth_user_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->user = g_strdup (user);
+ msg->passwd = g_strdup (passwd);
+ msg->auth_method = g_strdup (auth_method);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ char *id;
+ EBookContactCallback cb;
+ gpointer closure;
+} GetContactMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EContact *contact;
+ EBookStatus status;
+ EBookContactCallback cb;
+ gpointer closure;
+} GetContactResponse;
+
+static void
+_get_contact_response_handler (EBookMsg *msg)
+{
+ GetContactResponse *resp = (GetContactResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->contact, resp->closure);
+}
+
+static void
+_get_contact_response_dtor (EBookMsg *msg)
+{
+ GetContactResponse *resp = (GetContactResponse*)msg;
+
+ g_object_unref (resp->contact);
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_get_contact_handler (EBookMsg *msg)
+{
+ GetContactMsg *get_contact_msg = (GetContactMsg *)msg;
+ GetContactResponse *response;
+ GError *error = NULL;
+
+ response = g_new (GetContactResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _get_contact_response_handler, _get_contact_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_get_contact (get_contact_msg->book, get_contact_msg->id, &response->contact, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = get_contact_msg->book;
+ response->cb = get_contact_msg->cb;
+ response->closure = get_contact_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_get_contact_dtor (EBookMsg *msg)
+{
+ GetContactMsg *get_contact_msg = (GetContactMsg *)msg;
+
+ g_free (get_contact_msg->id);
+ g_free (get_contact_msg);
+}
+
+/* Fetching contacts. */
+guint
+e_book_async_get_contact (EBook *book,
+ const char *id,
+ EBookContactCallback cb,
+ gpointer closure)
+{
+ GetContactMsg *msg;
+
+ init_async ();
+
+ msg = g_new (GetContactMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _get_contact_handler, _get_contact_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->id = g_strdup (id);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return 0;
+}
+
+
+
+/* Deleting cards. */
+gboolean
+e_book_async_remove_contact (EBook *book,
+ EContact *contact,
+ EBookCallback cb,
+ gpointer closure)
+{
+ const char *id = e_contact_get_const (contact, E_CONTACT_UID);
+
+ return e_book_async_remove_contact_by_id (book, id, cb, closure);
+}
+
+gboolean
+e_book_async_remove_contact_by_id (EBook *book,
+ const char *id,
+ EBookCallback cb,
+ gpointer closure)
+{
+ GList *list = g_list_append (NULL, g_strdup (id));
+
+ return e_book_async_remove_contacts (book, list, cb, closure);
+}
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ GList *id_list;
+ EBookCallback cb;
+ gpointer closure;
+} RemoveContactsMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ EBookCallback cb;
+ gpointer closure;
+} RemoveContactsResponse;
+
+static void
+_remove_contacts_response_handler (EBookMsg *msg)
+{
+ RemoveContactsResponse *resp = (RemoveContactsResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->closure);
+}
+
+static void
+_remove_contacts_response_dtor (EBookMsg *msg)
+{
+ RemoveContactsResponse *resp = (RemoveContactsResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_remove_contacts_handler (EBookMsg *msg)
+{
+ RemoveContactsMsg *remove_contacts_msg = (RemoveContactsMsg *)msg;
+ RemoveContactsResponse *response;
+ GError *error = NULL;
+
+ response = g_new (RemoveContactsResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _remove_contacts_response_handler, _remove_contacts_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_remove_contacts (remove_contacts_msg->book, remove_contacts_msg->id_list, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = remove_contacts_msg->book;
+ response->cb = remove_contacts_msg->cb;
+ response->closure = remove_contacts_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_remove_contacts_dtor (EBookMsg *msg)
+{
+ RemoveContactsMsg *remove_contacts_msg = (RemoveContactsMsg *)msg;
+
+ g_list_foreach (remove_contacts_msg->id_list, (GFunc)g_free, NULL);
+ g_list_free (remove_contacts_msg->id_list);
+ g_free (remove_contacts_msg);
+}
+
+gboolean
+e_book_async_remove_contacts (EBook *book,
+ GList *id_list,
+ EBookCallback cb,
+ gpointer closure)
+{
+ RemoveContactsMsg *msg;
+ GList *l;
+ init_async ();
+
+ msg = g_new (RemoveContactsMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _remove_contacts_handler, _remove_contacts_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->id_list = g_list_copy (id_list);
+ for (l = msg->id_list; l; l = l->next)
+ l->data = g_strdup (l->data);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return 0;
+}
+
+
+
+/* Adding contacts. */
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EContact *contact;
+ EBookIdCallback cb;
+ gpointer closure;
+} AddContactMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ char *id;
+ EBookStatus status;
+ EBookIdCallback cb;
+ gpointer closure;
+} AddContactResponse;
+
+static void
+_add_contact_response_handler (EBookMsg *msg)
+{
+ AddContactResponse *resp = (AddContactResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->id, resp->closure);
+}
+
+static void
+_add_contact_response_dtor (EBookMsg *msg)
+{
+ AddContactResponse *resp = (AddContactResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp->id);
+ g_free (resp);
+}
+
+static void
+_add_contact_handler (EBookMsg *msg)
+{
+ AddContactMsg *add_contact_msg = (AddContactMsg *)msg;
+ AddContactResponse *response;
+ GError *error = NULL;
+
+ response = g_new (AddContactResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _add_contact_response_handler, _add_contact_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_add_contact (add_contact_msg->book, add_contact_msg->contact, &error)) {
+ response->status = error->code;
+ response->id = NULL;
+ g_error_free (error);
+ }
+ else {
+ response->id = e_contact_get (add_contact_msg->contact, E_CONTACT_UID);
+ }
+ response->book = add_contact_msg->book;
+ response->cb = add_contact_msg->cb;
+ response->closure = add_contact_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_add_contact_dtor (EBookMsg *msg)
+{
+ AddContactMsg *add_contact_msg = (AddContactMsg *)msg;
+
+ g_object_unref (add_contact_msg->contact);
+ g_free (add_contact_msg);
+}
+
+gboolean
+e_book_async_add_contact (EBook *book,
+ EContact *contact,
+ EBookIdCallback cb,
+ gpointer closure)
+{
+ AddContactMsg *msg;
+
+ init_async ();
+
+ msg = g_new (AddContactMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _add_contact_handler, _add_contact_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->contact = g_object_ref (contact); /* XXX maybe we should _duplicate it here instead */
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return TRUE;
+}
+
+
+
+/* Modifying cards. */
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EContact *contact;
+ EBookCallback cb;
+ gpointer closure;
+} CommitContactMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ EBookCallback cb;
+ gpointer closure;
+} CommitContactResponse;
+
+static void
+_commit_contact_response_handler (EBookMsg *msg)
+{
+ CommitContactResponse *resp = (CommitContactResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->closure);
+}
+
+static void
+_commit_contact_response_dtor (EBookMsg *msg)
+{
+ CommitContactResponse *resp = (CommitContactResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_commit_contact_handler (EBookMsg *msg)
+{
+ CommitContactMsg *commit_contact_msg = (CommitContactMsg *)msg;
+ CommitContactResponse *response;
+ GError *error = NULL;
+
+ response = g_new (CommitContactResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _commit_contact_response_handler, _commit_contact_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_commit_contact (commit_contact_msg->book, commit_contact_msg->contact, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = commit_contact_msg->book;
+ response->cb = commit_contact_msg->cb;
+ response->closure = commit_contact_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_commit_contact_dtor (EBookMsg *msg)
+{
+ CommitContactMsg *commit_contact_msg = (CommitContactMsg *)msg;
+
+ g_object_unref (commit_contact_msg->contact);
+ g_free (commit_contact_msg);
+}
+
+
+gboolean
+e_book_async_commit_contact (EBook *book,
+ EContact *contact,
+ EBookCallback cb,
+ gpointer closure)
+{
+ CommitContactMsg *msg;
+
+ init_async ();
+
+ msg = g_new (CommitContactMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _commit_contact_handler, _commit_contact_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->contact = g_object_ref (contact); /* XXX maybe we should _duplicate it here instead */
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return TRUE;
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookQuery *query;
+ EBookBookViewCallback cb;
+ gpointer closure;
+} GetBookViewMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ EBookView *book_view;
+ EBookBookViewCallback cb;
+ gpointer closure;
+} GetBookViewResponse;
+
+static void
+_get_book_view_response_handler (EBookMsg *msg)
+{
+ GetBookViewResponse *resp = (GetBookViewResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->book_view, resp->closure);
+}
+
+static void
+_get_book_view_response_dtor (EBookMsg *msg)
+{
+ GetBookViewResponse *resp = (GetBookViewResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_get_book_view_handler (EBookMsg *msg)
+{
+ GetBookViewMsg *view_msg = (GetBookViewMsg *)msg;
+ GetBookViewResponse *response;
+ GError *error = NULL;
+
+ response = g_new (GetBookViewResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _get_book_view_response_handler, _get_book_view_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_get_book_view (view_msg->book, view_msg->query, NULL, -1, &response->book_view, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = view_msg->book;
+ response->cb = view_msg->cb;
+ response->closure = view_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_get_book_view_dtor (EBookMsg *msg)
+{
+ GetBookViewMsg *view_msg = (GetBookViewMsg *)msg;
+
+ e_book_query_unref (view_msg->query);
+ g_free (view_msg);
+}
+
+guint
+e_book_async_get_book_view (EBook *book,
+ const gchar *query,
+ EBookBookViewCallback cb,
+ gpointer closure)
+{
+ GetBookViewMsg *msg;
+
+ init_async ();
+
+ msg = g_new (GetBookViewMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _get_book_view_handler, _get_book_view_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->query = e_book_query_from_string (query);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return 0;
+}
+
+
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookQuery *query;
+ EBookContactsCallback cb;
+ gpointer closure;
+} GetContactsMsg;
+
+typedef struct {
+ EBookMsg msg;
+
+ EBook *book;
+ EBookStatus status;
+ GList *contacts;
+ EBookContactsCallback cb;
+ gpointer closure;
+} GetContactsResponse;
+
+static void
+_get_contacts_response_handler (EBookMsg *msg)
+{
+ GetContactsResponse *resp = (GetContactsResponse*)msg;
+
+ if (resp->cb)
+ resp->cb (resp->book, resp->status, resp->contacts, resp->closure);
+}
+
+static void
+_get_contacts_response_dtor (EBookMsg *msg)
+{
+ GetContactsResponse *resp = (GetContactsResponse*)msg;
+
+ g_object_unref (resp->book);
+ g_free (resp);
+}
+
+static void
+_get_contacts_handler (EBookMsg *msg)
+{
+ GetContactsMsg *view_msg = (GetContactsMsg *)msg;
+ GetContactsResponse *response;
+ GError *error = NULL;
+
+ response = g_new (GetContactsResponse, 1);
+ e_book_msg_init ((EBookMsg*)response, _get_contacts_response_handler, _get_contacts_response_dtor);
+
+ response->status = E_BOOK_ERROR_OK;
+ if (!e_book_get_contacts (view_msg->book, view_msg->query, &response->contacts, &error)) {
+ response->status = error->code;
+ g_error_free (error);
+ }
+ response->book = view_msg->book;
+ response->cb = view_msg->cb;
+ response->closure = view_msg->closure;
+
+ g_async_queue_push (from_worker_queue, response);
+}
+
+static void
+_get_contacts_dtor (EBookMsg *msg)
+{
+ GetContactsMsg *view_msg = (GetContactsMsg *)msg;
+
+ e_book_query_unref (view_msg->query);
+ g_free (view_msg);
+}
+
+guint
+e_book_async_get_contacts (EBook *book,
+ const gchar *query,
+ EBookContactsCallback cb,
+ gpointer closure)
+{
+ GetContactsMsg *msg;
+
+ init_async ();
+
+ msg = g_new (GetContactsMsg, 1);
+ e_book_msg_init ((EBookMsg*)msg, _get_contacts_handler, _get_contacts_dtor);
+
+ msg->book = g_object_ref (book);
+ msg->query = e_book_query_from_string (query);
+ msg->cb = cb;
+ msg->closure = closure;
+
+ g_async_queue_push (to_worker_queue, msg);
+
+ return 0;
+}
diff --git a/addressbook/backend/ebook/e-book-async.h b/addressbook/backend/ebook/e-book-async.h
new file mode 100644
index 0000000000..097f3cff61
--- /dev/null
+++ b/addressbook/backend/ebook/e-book-async.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * The Evolution addressbook client object.
+ *
+ * Author:
+ * Chris Toshok (toshok@ximian.com)
+ *
+ * Copyright (C) 2003, Ximian, Inc.
+ */
+
+#ifndef __E_BOOK_ASYNC_H__
+#define __E_BOOK_ASYNC_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <e-util/e-list.h>
+#include <ebook/e-contact.h>
+#include <ebook/e-book.h>
+
+G_BEGIN_DECLS
+
+/* Callbacks for asynchronous functions. */
+typedef void (*EBookCallback) (EBook *book, EBookStatus status, gpointer closure);
+typedef void (*EBookOpenProgressCallback) (EBook *book,
+ const char *status_message,
+ short percent,
+ gpointer closure);
+typedef void (*EBookIdCallback) (EBook *book, EBookStatus status, const char *id, gpointer closure);
+typedef void (*EBookContactCallback) (EBook *book, EBookStatus status, EContact *contact, gpointer closure);
+typedef void (*EBookContactsCallback) (EBook *book, EBookStatus status, GList *contacts, gpointer closure);
+typedef void (*EBookBookViewCallback) (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure);
+typedef void (*EBookFieldsCallback) (EBook *book, EBookStatus status, EList *fields, gpointer closure);
+typedef void (*EBookAuthMethodsCallback) (EBook *book, EBookStatus status, EList *auth_methods, gpointer closure);
+
+void e_book_async_load_uri (EBook *book,
+ const char *uri,
+ EBookCallback open_response,
+ gpointer closure);
+
+void e_book_async_get_default_addressbook (EBookCallback open_response,
+ gpointer closure);
+
+void e_book_async_unload_uri (EBook *book);
+
+guint e_book_async_get_supported_fields (EBook *book,
+ EBookFieldsCallback cb,
+ gpointer closure);
+
+guint e_book_async_get_supported_auth_methods (EBook *book,
+ EBookAuthMethodsCallback cb,
+ gpointer closure);
+
+/* User authentication. */
+void e_book_async_authenticate_user (EBook *book,
+ const char *user,
+ const char *passwd,
+ const char *auth_method,
+ EBookCallback cb,
+ gpointer closure);
+
+/* Fetching cards. */
+guint e_book_async_get_contact (EBook *book,
+ const char *id,
+ EBookContactCallback cb,
+ gpointer closure);
+
+guint e_book_async_get_contacts (EBook *book,
+ const char *query,
+ EBookContactsCallback cb,
+ gpointer closure);
+
+/* Deleting cards. */
+gboolean e_book_async_remove_contact (EBook *book,
+ EContact *contact,
+ EBookCallback cb,
+ gpointer closure);
+gboolean e_book_async_remove_contact_by_id (EBook *book,
+ const char *id,
+ EBookCallback cb,
+ gpointer closure);
+
+gboolean e_book_async_remove_contacts (EBook *book,
+ GList *id_list,
+ EBookCallback cb,
+ gpointer closure);
+
+/* Adding cards. */
+gboolean e_book_async_add_contact (EBook *book,
+ EContact *contact,
+ EBookIdCallback cb,
+ gpointer closure);
+
+/* Modifying cards. */
+gboolean e_book_async_commit_contact (EBook *book,
+ EContact *contact,
+ EBookCallback cb,
+ gpointer closure);
+
+guint e_book_async_get_book_view (EBook *book,
+ const gchar *query, /* XXX this needs to change to an EBookQuery */
+ EBookBookViewCallback cb,
+ gpointer closure);
+
+G_END_DECLS
+
+#endif /* ! __E_BOOK_H__ */
diff --git a/addressbook/backend/ebook/e-book-listener.c b/addressbook/backend/ebook/e-book-listener.c
index 9d6d876045..0bb5193376 100644
--- a/addressbook/backend/ebook/e-book-listener.c
+++ b/addressbook/backend/ebook/e-book-listener.c
@@ -11,13 +11,14 @@
#include <config.h>
#include <bonobo/bonobo-main.h>
+#include "e-contact.h"
#include "e-book-listener.h"
#include "e-book-marshal.h"
-static EBookStatus e_book_listener_convert_status (GNOME_Evolution_Addressbook_BookListener_CallStatus status);
+static EBookStatus e_book_listener_convert_status (GNOME_Evolution_Addressbook_CallStatus status);
enum {
- RESPONSES_QUEUED,
+ RESPONSE,
LAST_SIGNAL
};
@@ -26,569 +27,267 @@ static guint e_book_listener_signals [LAST_SIGNAL];
static BonoboObjectClass *parent_class;
struct _EBookListenerPrivate {
- GList *response_queue;
- gint timeout_id;
-
- guint timeout_lock : 1;
guint stopped : 1;
};
-static void
-response_free (EBookListenerResponse *resp)
-{
- if (resp == NULL)
- return;
-
- g_free (resp->msg);
- g_free (resp->id);
-
- if (resp->book != CORBA_OBJECT_NIL) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- bonobo_object_release_unref (resp->book, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_listener_destroy: "
- "Exception destroying book "
- "in response queue!\n");
- }
-
- CORBA_exception_free (&ev);
- }
-
- if (resp->cursor != CORBA_OBJECT_NIL) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- bonobo_object_release_unref (resp->cursor, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_listener_destroy: "
- "Exception destroying cursor "
- "in response queue!\n");
- }
-
- CORBA_exception_free (&ev);
- }
-
- if (resp->book_view != CORBA_OBJECT_NIL) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- bonobo_object_release_unref (resp->book_view, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_listener_destroy: "
- "Exception destroying book_view "
- "in response queue!\n");
- }
-
- CORBA_exception_free (&ev);
- }
-
- g_free (resp);
-}
-
-static gboolean
-e_book_listener_check_queue (EBookListener *listener)
-{
- if (listener->priv->timeout_lock)
- return TRUE;
-
- listener->priv->timeout_lock = TRUE;
-
- if (listener->priv->response_queue != NULL && !listener->priv->stopped) {
- g_signal_emit (listener, e_book_listener_signals [RESPONSES_QUEUED], 0);
- }
-
- if (listener->priv->response_queue == NULL || listener->priv->stopped) {
- listener->priv->timeout_id = 0;
- listener->priv->timeout_lock = FALSE;
- bonobo_object_unref (BONOBO_OBJECT (listener)); /* release the timeout's reference */
- return FALSE;
- }
-
- listener->priv->timeout_lock = FALSE;
- return TRUE;
-}
-
-static void
-e_book_listener_queue_response (EBookListener *listener,
- EBookListenerResponse *response)
+static EBookStatus
+e_book_listener_convert_status (const GNOME_Evolution_Addressbook_CallStatus status)
{
- if (response == NULL)
- return;
-
- if (listener->priv->stopped) {
- response_free (response);
- return;
- }
-
- listener->priv->response_queue = g_list_append (listener->priv->response_queue, response);
-
- if (listener->priv->timeout_id == 0) {
-
- /* 20 == an arbitrary small integer */
- listener->priv->timeout_id = g_timeout_add (20, (GSourceFunc) e_book_listener_check_queue, listener);
-
- /* Hold a reference on behalf of the timeout */
- bonobo_object_ref (BONOBO_OBJECT (listener));
-
+ switch (status) {
+ case GNOME_Evolution_Addressbook_Success:
+ return E_BOOK_ERROR_OK;
+ case GNOME_Evolution_Addressbook_RepositoryOffline:
+ return E_BOOK_ERROR_REPOSITORY_OFFLINE;
+ case GNOME_Evolution_Addressbook_PermissionDenied:
+ return E_BOOK_ERROR_PERMISSION_DENIED;
+ case GNOME_Evolution_Addressbook_ContactNotFound:
+ return E_BOOK_ERROR_CONTACT_NOT_FOUND;
+ case GNOME_Evolution_Addressbook_ContactIdAlreadyExists:
+ return E_BOOK_ERROR_CONTACT_ID_ALREADY_EXISTS;
+ case GNOME_Evolution_Addressbook_AuthenticationFailed:
+ return E_BOOK_ERROR_AUTHENTICATION_FAILED;
+ case GNOME_Evolution_Addressbook_AuthenticationRequired:
+ return E_BOOK_ERROR_AUTHENTICATION_REQUIRED;
+ case GNOME_Evolution_Addressbook_TLSNotAvailable:
+ return E_BOOK_ERROR_TLS_NOT_AVAILABLE;
+ case GNOME_Evolution_Addressbook_NoSuchBook:
+ return E_BOOK_ERROR_NO_SUCH_BOOK;
+ case GNOME_Evolution_Addressbook_OtherError:
+ default:
+ return E_BOOK_ERROR_OTHER_ERROR;
}
}
-/* Add, Remove, Modify */
-static void
-e_book_listener_queue_generic_response (EBookListener *listener,
- EBookListenerOperation op,
- EBookStatus status)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = op;
- resp->status = status;
-
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-e_book_listener_queue_open_response (EBookListener *listener,
- EBookStatus status,
- GNOME_Evolution_Addressbook_Book book)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = OpenBookResponse;
- resp->status = status;
- resp->book = book;
-
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-e_book_listener_queue_open_progress (EBookListener *listener,
- const char *msg,
- short percent)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = OpenProgressEvent;
- resp->msg = g_strdup (msg);
- resp->percent = percent;
-
- e_book_listener_queue_response (listener, resp);
-}
-
-
-static void
-e_book_listener_queue_create_card_response (EBookListener *listener,
- EBookStatus status,
- const char *id)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = CreateCardResponse;
- resp->status = status;
- resp->id = g_strdup (id);
-
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-e_book_listener_queue_get_vcard_response (EBookListener *listener,
- EBookStatus status,
- const char *vcard)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = GetCardResponse;
- resp->status = status;
- resp->vcard = g_strdup (vcard);
-
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-e_book_listener_queue_get_cursor_response (EBookListener *listener,
- EBookStatus status,
- GNOME_Evolution_Addressbook_CardCursor cursor)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = GetCursorResponse;
- resp->status = status;
- resp->cursor = cursor;
-
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-e_book_listener_queue_get_view_response (EBookListener *listener,
- EBookStatus status,
- GNOME_Evolution_Addressbook_BookView book_view)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = GetBookViewResponse;
- resp->status = status;
- resp->book_view = book_view;
-
- e_book_listener_queue_response (listener, resp);
-}
-
static void
-e_book_listener_queue_get_changes_response (EBookListener *listener,
- EBookStatus status,
- GNOME_Evolution_Addressbook_BookView book_view)
+impl_BookListener_respond_create_contact (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ const CORBA_char* id,
+ CORBA_Environment *ev)
{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
-
- resp->op = GetChangesResponse;
- resp->status = status;
- resp->book_view = book_view;
-
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-e_book_listener_queue_link_status (EBookListener *listener,
- gboolean connected)
-{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- resp = g_new0 (EBookListenerResponse, 1);
+ response.op = CreateContactResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.id = g_strdup (id);
- resp->op = LinkStatusEvent;
- resp->connected = connected;
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
- e_book_listener_queue_response (listener, resp);
+ g_free (response.id);
}
static void
-e_book_listener_queue_writable_status (EBookListener *listener,
- gboolean writable)
+impl_BookListener_respond_remove_contacts (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ CORBA_Environment *ev)
{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- resp->op = WritableStatusEvent;
- resp->writable = writable;
+ response.op = RemoveContactResponse;
+ response.status = e_book_listener_convert_status (status);
- e_book_listener_queue_response (listener, resp);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
-e_book_listener_queue_authentication_response (EBookListener *listener,
- EBookStatus status)
+impl_BookListener_respond_modify_contact (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ CORBA_Environment *ev)
{
- EBookListenerResponse *resp;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- resp->op = AuthenticationResponse;
- resp->status = status;
+ response.op = ModifyContactResponse;
+ response.status = e_book_listener_convert_status (status);
- e_book_listener_queue_response (listener, resp);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
-e_book_listener_queue_get_supported_fields_response (EBookListener *listener,
- EBookStatus status,
- const GNOME_Evolution_Addressbook_stringlist *fields)
+impl_BookListener_respond_get_contact (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ const CORBA_char* card,
+ CORBA_Environment *ev)
{
- EBookListenerResponse *resp;
- int i;
-
- if (listener->priv->stopped)
- return;
-
- resp = g_new0 (EBookListenerResponse, 1);
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- resp->op = GetSupportedFieldsResponse;
- resp->status = status;
- resp->list = e_list_new ((EListCopyFunc)g_strdup, (EListFreeFunc)g_free, NULL);
+ response.op = GetContactResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.vcard = g_strdup (card);
- for (i = 0; i < fields->_length; i ++) {
- e_list_append (resp->list, fields->_buffer[i]);
- }
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
- e_book_listener_queue_response (listener, resp);
+ g_free (response.vcard);
}
static void
-e_book_listener_queue_get_supported_auth_methods_response (EBookListener *listener,
- EBookStatus status,
- const GNOME_Evolution_Addressbook_stringlist *auth_methods)
+impl_BookListener_respond_get_contact_list (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ const GNOME_Evolution_Addressbook_stringlist *cards,
+ CORBA_Environment *ev)
{
- EBookListenerResponse *resp;
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
int i;
if (listener->priv->stopped)
return;
- resp = g_new0 (EBookListenerResponse, 1);
+ response.op = GetContactListResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.list = NULL;
- resp->op = GetSupportedAuthMethodsResponse;
- resp->status = status;
- resp->list = e_list_new ((EListCopyFunc)g_strdup, (EListFreeFunc)g_free, NULL);
-
- for (i = 0; i < auth_methods->_length; i ++) {
- e_list_append (resp->list, auth_methods->_buffer[i]);
+ for (i = 0; i < cards->_length; i ++) {
+ response.list = g_list_prepend (response.list, e_contact_new_from_vcard (cards->_buffer[i]));
}
- e_book_listener_queue_response (listener, resp);
-}
-
-static void
-impl_BookListener_respond_create_card (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const CORBA_char* id,
- CORBA_Environment *ev)
-{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
-
- e_book_listener_queue_create_card_response (
- listener,
- e_book_listener_convert_status (status),
- id);
-}
-
-static void
-impl_BookListener_respond_remove_cards (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- CORBA_Environment *ev)
-{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
-
- e_book_listener_queue_generic_response (
- listener, RemoveCardResponse,
- e_book_listener_convert_status (status));
-}
-
-static void
-impl_BookListener_respond_modify_card (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- CORBA_Environment *ev)
-{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
-
- e_book_listener_queue_generic_response (
- listener, ModifyCardResponse,
- e_book_listener_convert_status (status));
-}
-
-static void
-impl_BookListener_respond_get_vcard (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const CORBA_char* card,
- CORBA_Environment *ev)
-{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
-
- e_book_listener_queue_get_vcard_response (
- listener,
- e_book_listener_convert_status (status),
- g_strdup (card));
-}
-
-static void
-impl_BookListener_respond_get_cursor (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const GNOME_Evolution_Addressbook_CardCursor cursor,
- CORBA_Environment *ev)
-{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
- GNOME_Evolution_Addressbook_CardCursor cursor_copy;
-
- cursor_copy = bonobo_object_dup_ref (cursor, ev);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
- if (ev->_major != CORBA_NO_EXCEPTION) {
- g_warning ("EBookListener: Exception while duplicating CardCursor!\n");
- return;
- }
-
- e_book_listener_queue_get_cursor_response (
- listener,
- e_book_listener_convert_status (status),
- cursor_copy);
+ /* XXX free response.list? */
}
static void
impl_BookListener_respond_get_view (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
+ const GNOME_Evolution_Addressbook_CallStatus status,
const GNOME_Evolution_Addressbook_BookView book_view,
CORBA_Environment *ev)
{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
- GNOME_Evolution_Addressbook_BookView book_view_copy;
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- book_view_copy = bonobo_object_dup_ref (book_view, ev);
+ printf ("impl_BookListener_respond_get_view\n");
- if (ev->_major != CORBA_NO_EXCEPTION) {
- g_warning ("EBookListener: Exception while duplicating BookView.\n");
+ if (listener->priv->stopped)
return;
- }
- e_book_listener_queue_get_view_response (
- listener,
- e_book_listener_convert_status (status),
- book_view_copy);
+ response.op = GetBookViewResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.book_view = bonobo_object_dup_ref (book_view, ev);
+
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
impl_BookListener_respond_get_changes (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const GNOME_Evolution_Addressbook_BookView book_view,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ const GNOME_Evolution_Addressbook_BookChangeList *changes,
CORBA_Environment *ev)
{
EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
- GNOME_Evolution_Addressbook_BookView book_view_copy;
+ EBookListenerResponse response;
+ int i;
- book_view_copy = bonobo_object_dup_ref (book_view, ev);
+ response.op = GetChangesResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.list = NULL;
+
+ for (i = 0; i < changes->_length; i ++) {
+ EBookChange *change = g_new (EBookChange, 1);
+ GNOME_Evolution_Addressbook_BookChangeItem corba_change = changes->_buffer[i];
+
+ switch (corba_change._d) {
+ case GNOME_Evolution_Addressbook_ContactAdded:
+ change->change_type = E_BOOK_CHANGE_CARD_ADDED;
+ change->vcard = g_strdup (corba_change._u.add_vcard);
+ break;
+ case GNOME_Evolution_Addressbook_ContactDeleted:
+ change->change_type = E_BOOK_CHANGE_CARD_DELETED;
+ change->id = g_strdup (corba_change._u.del_id);
+ break;
+ case GNOME_Evolution_Addressbook_ContactModified:
+ change->change_type = E_BOOK_CHANGE_CARD_MODIFIED;
+ change->vcard = g_strdup (corba_change._u.mod_vcard);
+ break;
+ }
- if (ev->_major != CORBA_NO_EXCEPTION) {
- g_warning ("EBookListener: Exception while duplicating BookView.\n");
- return;
+ response.list = g_list_prepend (response.list, change);
}
- e_book_listener_queue_get_changes_response (
- listener,
- e_book_listener_convert_status (status),
- book_view_copy);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
impl_BookListener_respond_open_book (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const GNOME_Evolution_Addressbook_Book book,
+ const GNOME_Evolution_Addressbook_CallStatus status,
CORBA_Environment *ev)
{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
- GNOME_Evolution_Addressbook_Book book_copy;
-
- book_copy = bonobo_object_dup_ref (book, ev);
+ EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- if (ev->_major != CORBA_NO_EXCEPTION) {
- g_warning ("EBookListener: Exception while duplicating Book!\n");
- return;
- }
+ response.op = OpenBookResponse;
+ response.status = e_book_listener_convert_status (status);
- e_book_listener_queue_open_response (
- listener,
- e_book_listener_convert_status (status),
- book_copy);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
-impl_BookListener_report_open_book_progress (PortableServer_Servant servant,
- const CORBA_char *status_message,
- const CORBA_short percent,
- CORBA_Environment *ev)
+impl_BookListener_respond_remove_book (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ CORBA_Environment *ev)
{
EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- e_book_listener_queue_open_progress (
- listener, status_message, percent);
+ response.op = RemoveBookResponse;
+ response.status = e_book_listener_convert_status (status);
+
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
impl_BookListener_respond_authentication_result (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
+ const GNOME_Evolution_Addressbook_CallStatus status,
CORBA_Environment *ev)
{
EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
+
+ response.op = AuthenticationResponse;
+ response.status = e_book_listener_convert_status (status);
- e_book_listener_queue_authentication_response (
- listener, status);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
-impl_BookListener_response_get_supported_fields (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const GNOME_Evolution_Addressbook_stringlist *fields,
- CORBA_Environment *ev)
+impl_BookListener_respond_get_supported_fields (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ const GNOME_Evolution_Addressbook_stringlist *fields,
+ CORBA_Environment *ev)
{
EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
+ int i;
- e_book_listener_queue_get_supported_fields_response (
- listener, status, fields);
-}
+ response.op = GetSupportedFieldsResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.list = NULL;
-static void
-impl_BookListener_response_get_supported_auth_methods (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookListener_CallStatus status,
- const GNOME_Evolution_Addressbook_stringlist *auth_methods,
- CORBA_Environment *ev)
-{
- EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ for (i = 0; i < fields->_length; i ++)
+ response.list = g_list_prepend (response.list, g_strdup (fields->_buffer[i]));
- e_book_listener_queue_get_supported_auth_methods_response (
- listener, status, auth_methods);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
-impl_BookListener_report_connection_status (PortableServer_Servant servant,
- const CORBA_boolean connected,
- CORBA_Environment *ev)
+impl_BookListener_respond_get_supported_auth_methods (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_CallStatus status,
+ const GNOME_Evolution_Addressbook_stringlist *auth_methods,
+ CORBA_Environment *ev)
{
EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
+ int i;
+
+ response.op = GetSupportedAuthMethodsResponse;
+ response.status = e_book_listener_convert_status (status);
+ response.list = NULL;
- e_book_listener_queue_link_status (
- listener, connected);
+ for (i = 0; i < auth_methods->_length; i ++)
+ response.list = g_list_prepend (response.list, g_strdup (auth_methods->_buffer[i]));
+
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
static void
@@ -597,89 +296,20 @@ impl_BookListener_report_writable (PortableServer_Servant servant,
CORBA_Environment *ev)
{
EBookListener *listener = E_BOOK_LISTENER (bonobo_object (servant));
+ EBookListenerResponse response;
- e_book_listener_queue_writable_status (listener, writable);
-}
+ response.op = WritableStatusEvent;
+ response.writable = writable;
-/**
- * e_book_listener_check_pending:
- * @listener: the #EBookListener
- *
- * Returns: the number of items on the response queue,
- * or -1 if the @listener is isn't an #EBookListener.
- */
-int
-e_book_listener_check_pending (EBookListener *listener)
-{
- g_return_val_if_fail (listener != NULL, -1);
- g_return_val_if_fail (E_IS_BOOK_LISTENER (listener), -1);
-
- return g_list_length (listener->priv->response_queue);
+ g_signal_emit (listener, e_book_listener_signals [RESPONSE], 0, &response);
}
-/**
- * e_book_listener_pop_response:
- * @listener: the #EBookListener for which a request is to be popped
- *
- * Returns: an #EBookListenerResponse if there are responses on the
- * queue to be returned; %NULL if there aren't, or if the @listener
- * isn't an EBookListener.
- */
-EBookListenerResponse *
-e_book_listener_pop_response (EBookListener *listener)
-{
- EBookListenerResponse *resp;
- GList *popped;
-
- g_return_val_if_fail (listener != NULL, NULL);
- g_return_val_if_fail (E_IS_BOOK_LISTENER (listener), NULL);
-
- if (listener->priv->response_queue == NULL)
- return NULL;
-
- resp = listener->priv->response_queue->data;
-
- popped = listener->priv->response_queue;
- listener->priv->response_queue =
- g_list_remove_link (listener->priv->response_queue,
- listener->priv->response_queue);
- g_list_free_1 (popped);
-
- return resp;
-}
-
-static EBookStatus
-e_book_listener_convert_status (const GNOME_Evolution_Addressbook_BookListener_CallStatus status)
+static void
+impl_BookListener_respond_progress (PortableServer_Servant servant,
+ const CORBA_char * message,
+ const CORBA_short percent,
+ CORBA_Environment *ev)
{
- switch (status) {
- case GNOME_Evolution_Addressbook_BookListener_Success:
- return E_BOOK_STATUS_SUCCESS;
- case GNOME_Evolution_Addressbook_BookListener_RepositoryOffline:
- return E_BOOK_STATUS_REPOSITORY_OFFLINE;
- case GNOME_Evolution_Addressbook_BookListener_PermissionDenied:
- return E_BOOK_STATUS_PERMISSION_DENIED;
- case GNOME_Evolution_Addressbook_BookListener_CardNotFound:
- return E_BOOK_STATUS_CARD_NOT_FOUND;
- case GNOME_Evolution_Addressbook_BookListener_CardIdAlreadyExists:
- return E_BOOK_STATUS_CARD_ID_ALREADY_EXISTS;
- case GNOME_Evolution_Addressbook_BookListener_ProtocolNotSupported:
- return E_BOOK_STATUS_PROTOCOL_NOT_SUPPORTED;
- case GNOME_Evolution_Addressbook_BookListener_AuthenticationFailed:
- return E_BOOK_STATUS_AUTHENTICATION_FAILED;
- case GNOME_Evolution_Addressbook_BookListener_AuthenticationRequired:
- return E_BOOK_STATUS_AUTHENTICATION_REQUIRED;
- case GNOME_Evolution_Addressbook_BookListener_TLSNotAvailable:
- return E_BOOK_STATUS_TLS_NOT_AVAILABLE;
- case GNOME_Evolution_Addressbook_BookListener_NoSuchBook:
- return E_BOOK_STATUS_NO_SUCH_BOOK;
- case GNOME_Evolution_Addressbook_BookListener_OtherError:
- return E_BOOK_STATUS_OTHER_ERROR;
- default:
- g_warning ("e_book_listener_convert_status: Unknown status "
- "from card server: %d\n", (int) status);
- return E_BOOK_STATUS_UNKNOWN;
-
- }
}
static void
@@ -701,7 +331,9 @@ e_book_listener_new ()
{
EBookListener *listener;
- listener = g_object_new (E_TYPE_BOOK_LISTENER, NULL);
+ listener = g_object_new (E_TYPE_BOOK_LISTENER,
+ "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_ALL_AT_IDLE, NULL),
+ NULL);
e_book_listener_construct (listener);
@@ -723,38 +355,6 @@ e_book_listener_stop (EBookListener *listener)
}
static void
-e_book_listener_dispose (GObject *object)
-{
- EBookListener *listener = E_BOOK_LISTENER (object);
-
- if (listener->priv) {
- GList *l;
-
- /* Remove our response queue handler: In theory, this
- can never happen since we always hold a reference
- to the listener while the timeout is running. */
- if (listener->priv->timeout_id) {
- g_source_remove (listener->priv->timeout_id);
- }
-
- /* Clean up anything still sitting in response_queue */
- for (l = listener->priv->response_queue; l != NULL; l = l->next) {
- EBookListenerResponse *resp = l->data;
-
- response_free (resp);
- }
- g_list_free (listener->priv->response_queue);
-
- g_free (listener->priv);
-
- listener->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
e_book_listener_class_init (EBookListenerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -762,31 +362,30 @@ e_book_listener_class_init (EBookListenerClass *klass)
parent_class = g_type_class_ref (BONOBO_TYPE_OBJECT);
- e_book_listener_signals [RESPONSES_QUEUED] =
- g_signal_new ("responses_queued",
+ e_book_listener_signals [RESPONSE] =
+ g_signal_new ("response",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookListenerClass, responses_queued),
+ G_STRUCT_OFFSET (EBookListenerClass, response),
NULL, NULL,
- e_book_marshal_NONE__NONE,
- G_TYPE_NONE, 0);
-
- object_class->dispose = e_book_listener_dispose;
+ e_book_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
epv = &klass->epv;
- epv->notifyOpenBookProgress = impl_BookListener_report_open_book_progress;
+ epv->notifyProgress = impl_BookListener_respond_progress;
epv->notifyBookOpened = impl_BookListener_respond_open_book;
- epv->notifyCardCreated = impl_BookListener_respond_create_card;
- epv->notifyCardsRemoved = impl_BookListener_respond_remove_cards;
- epv->notifyCardModified = impl_BookListener_respond_modify_card;
+ epv->notifyBookRemoved = impl_BookListener_respond_remove_book;
+ epv->notifyContactCreated = impl_BookListener_respond_create_contact;
+ epv->notifyContactsRemoved = impl_BookListener_respond_remove_contacts;
+ epv->notifyContactModified = impl_BookListener_respond_modify_contact;
epv->notifyAuthenticationResult = impl_BookListener_respond_authentication_result;
- epv->notifySupportedFields = impl_BookListener_response_get_supported_fields;
- epv->notifySupportedAuthMethods = impl_BookListener_response_get_supported_auth_methods;
- epv->notifyCardRequested = impl_BookListener_respond_get_vcard;
- epv->notifyCursorRequested = impl_BookListener_respond_get_cursor;
+ epv->notifySupportedFields = impl_BookListener_respond_get_supported_fields;
+ epv->notifySupportedAuthMethods = impl_BookListener_respond_get_supported_auth_methods;
+ epv->notifyContactRequested = impl_BookListener_respond_get_contact;
+ epv->notifyContactListRequested = impl_BookListener_respond_get_contact_list;
epv->notifyViewRequested = impl_BookListener_respond_get_view;
epv->notifyChangesRequested = impl_BookListener_respond_get_changes;
- epv->notifyConnectionStatus = impl_BookListener_report_connection_status;
epv->notifyWritable = impl_BookListener_report_writable;
}
diff --git a/addressbook/backend/ebook/e-book-listener.h b/addressbook/backend/ebook/e-book-listener.h
index 1b02dd4bb6..4d1f0c0231 100644
--- a/addressbook/backend/ebook/e-book-listener.h
+++ b/addressbook/backend/ebook/e-book-listener.h
@@ -15,7 +15,6 @@
#include <bonobo/bonobo-object.h>
#include <ebook/addressbook.h>
#include <ebook/e-book-types.h>
-#include <e-util/e-list.h>
#define E_TYPE_BOOK_LISTENER (e_book_listener_get_type ())
#define E_BOOK_LISTENER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_LISTENER, EBookListener))
@@ -29,6 +28,7 @@ G_BEGIN_DECLS
typedef struct _EBookListener EBookListener;
typedef struct _EBookListenerClass EBookListenerClass;
typedef struct _EBookListenerPrivate EBookListenerPrivate;
+typedef struct _EBookListenerResponse EBookListenerResponse;
struct _EBookListener {
BonoboObject parent;
@@ -39,20 +39,30 @@ struct _EBookListenerClass {
BonoboObjectClass parent;
POA_GNOME_Evolution_Addressbook_BookListener__epv epv;
+
/*
* Signals
*/
- void (*responses_queued) (void);
+
+ void (*response) (EBookListener *listener, EBookListenerResponse *response);
+
+ /* Padding for future expansion */
+ void (*_ebook_reserved0) (void);
+ void (*_ebook_reserved1) (void);
+ void (*_ebook_reserved2) (void);
+ void (*_ebook_reserved3) (void);
+ void (*_ebook_reserved4) (void);
};
typedef enum {
/* Async responses */
OpenBookResponse,
- CreateCardResponse,
- RemoveCardResponse,
- ModifyCardResponse,
- GetCardResponse,
- GetCursorResponse,
+ RemoveBookResponse,
+ CreateContactResponse,
+ RemoveContactResponse,
+ ModifyContactResponse,
+ GetContactResponse,
+ GetContactListResponse,
GetBookViewResponse,
GetChangesResponse,
AuthenticationResponse,
@@ -62,28 +72,22 @@ typedef enum {
/* Async events */
LinkStatusEvent,
WritableStatusEvent,
- OpenProgressEvent,
+ ProgressEvent,
} EBookListenerOperation;
-typedef struct {
+struct _EBookListenerResponse {
EBookListenerOperation op;
/* For most Response notifications */
EBookStatus status;
- /* For OpenBookResponse */
- GNOME_Evolution_Addressbook_Book book;
-
- /* For GetCursorResponse */
- GNOME_Evolution_Addressbook_CardCursor cursor;
-
/* For GetBookViewReponse */
GNOME_Evolution_Addressbook_BookView book_view;
/* For GetSupportedFields/GetSupportedAuthMethods */
- EList *list;
+ GList *list;
- /* For OpenProgressEvent */
+ /* For ProgressEvent */
char *msg;
short percent;
@@ -96,12 +100,10 @@ typedef struct {
/* For Card[Added|Removed|Modified]Event */
char *id;
char *vcard;
-} EBookListenerResponse;
+};
EBookListener *e_book_listener_new (void);
-int e_book_listener_check_pending (EBookListener *listener);
-EBookListenerResponse *e_book_listener_pop_response (EBookListener *listener);
GType e_book_listener_get_type (void);
void e_book_listener_stop (EBookListener *listener);
diff --git a/addressbook/backend/ebook/e-book-query.c b/addressbook/backend/ebook/e-book-query.c
new file mode 100644
index 0000000000..16e325303c
--- /dev/null
+++ b/addressbook/backend/ebook/e-book-query.c
@@ -0,0 +1,524 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <config.h>
+
+#include "e-book-query.h"
+#include <e-util/e-sexp.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+typedef enum {
+ E_BOOK_QUERY_TYPE_AND,
+ E_BOOK_QUERY_TYPE_OR,
+ E_BOOK_QUERY_TYPE_NOT,
+ E_BOOK_QUERY_TYPE_FIELD_EXISTS,
+ E_BOOK_QUERY_TYPE_FIELD_TEST,
+ E_BOOK_QUERY_TYPE_ANY_FIELD_CONTAINS
+} EBookQueryType;
+
+struct EBookQuery {
+ EBookQueryType type;
+ int ref_count;
+
+ union {
+ struct {
+ guint nqs;
+ EBookQuery **qs;
+ } andor;
+
+ struct {
+ EBookQuery *q;
+ } not;
+
+ struct {
+ EBookQueryTest test;
+ EContactField field;
+ char *value;
+ } field_test;
+
+ struct {
+ EContactField field;
+ } exist;
+
+ struct {
+ char *value;
+ } any_field_contains;
+ } query;
+};
+
+static EBookQuery *
+conjoin (EBookQueryType type, int nqs, EBookQuery **qs, gboolean unref)
+{
+ EBookQuery *ret = g_new0 (EBookQuery, 1);
+ int i;
+
+ ret->type = type;
+ ret->query.andor.nqs = nqs;
+ ret->query.andor.qs = g_new (EBookQuery *, nqs);
+ for (i = 0; i < nqs; i++) {
+ ret->query.andor.qs[i] = qs[i];
+ if (!unref)
+ e_book_query_ref (qs[i]);
+ }
+
+ return ret;
+}
+
+EBookQuery *
+e_book_query_and (int nqs, EBookQuery **qs, gboolean unref)
+{
+ return conjoin (E_BOOK_QUERY_TYPE_AND, nqs, qs, unref);
+}
+
+EBookQuery *
+e_book_query_or (int nqs, EBookQuery **qs, gboolean unref)
+{
+ return conjoin (E_BOOK_QUERY_TYPE_OR, nqs, qs, unref);
+}
+
+static EBookQuery *
+conjoinv (EBookQueryType type, EBookQuery *q, va_list ap)
+{
+ EBookQuery *ret = g_new0 (EBookQuery, 1);
+ GPtrArray *qs;
+
+ qs = g_ptr_array_new ();
+ while (q) {
+ g_ptr_array_add (qs, q);
+ q = va_arg (ap, EBookQuery *);
+ }
+ va_end (ap);
+
+ ret->type = type;
+ ret->query.andor.nqs = qs->len;
+ ret->query.andor.qs = (EBookQuery **)qs->pdata;
+ g_ptr_array_free (qs, FALSE);
+
+ return ret;
+}
+
+EBookQuery *
+e_book_query_andv (EBookQuery *q, ...)
+{
+ va_list ap;
+
+ va_start (ap, q);
+ return conjoinv (E_BOOK_QUERY_TYPE_AND, q, ap);
+}
+
+EBookQuery *
+e_book_query_orv (EBookQuery *q, ...)
+{
+ va_list ap;
+
+ va_start (ap, q);
+ return conjoinv (E_BOOK_QUERY_TYPE_OR, q, ap);
+}
+
+EBookQuery *
+e_book_query_not (EBookQuery *q, gboolean unref)
+{
+ EBookQuery *ret = g_new0 (EBookQuery, 1);
+
+ ret->type = E_BOOK_QUERY_TYPE_NOT;
+ ret->query.not.q = q;
+ if (!unref)
+ e_book_query_ref (q);
+
+ return ret;
+}
+
+EBookQuery *
+e_book_query_field_test (EContactField field,
+ EBookQueryTest test,
+ const char *value)
+{
+ EBookQuery *ret = g_new0 (EBookQuery, 1);
+
+ ret->type = E_BOOK_QUERY_TYPE_FIELD_TEST;
+ ret->query.field_test.field = field;
+ ret->query.field_test.test = test;
+ ret->query.field_test.value = g_strdup (value);
+
+ return ret;
+}
+
+EBookQuery *
+e_book_query_field_exists (EContactField field)
+{
+ EBookQuery *ret = g_new0 (EBookQuery, 1);
+
+ ret->type = E_BOOK_QUERY_TYPE_FIELD_EXISTS;
+ ret->query.exist.field = field;
+
+ return ret;
+}
+
+EBookQuery *
+e_book_query_any_field_contains (const char *value)
+{
+ EBookQuery *ret = g_new0 (EBookQuery, 1);
+
+ ret->type = E_BOOK_QUERY_TYPE_ANY_FIELD_CONTAINS;
+ ret->query.any_field_contains.value = g_strdup (value);
+
+ return ret;
+}
+
+void
+e_book_query_unref (EBookQuery *q)
+{
+ int i;
+
+ if (q->ref_count--)
+ return;
+
+ switch (q->type) {
+ case E_BOOK_QUERY_TYPE_AND:
+ case E_BOOK_QUERY_TYPE_OR:
+ for (i = 0; i < q->query.andor.nqs; i++)
+ e_book_query_unref (q->query.andor.qs[i]);
+ g_free (q->query.andor.qs);
+ break;
+
+ case E_BOOK_QUERY_TYPE_NOT:
+ e_book_query_unref (q->query.not.q);
+ break;
+
+ case E_BOOK_QUERY_TYPE_FIELD_TEST:
+ g_free (q->query.field_test.value);
+ break;
+
+ case E_BOOK_QUERY_TYPE_ANY_FIELD_CONTAINS:
+ g_free (q->query.any_field_contains.value);
+ break;
+
+ default:
+ break;
+ }
+
+ g_free (q);
+}
+
+void
+e_book_query_ref (EBookQuery *q)
+{
+ q->ref_count++;
+}
+
+static ESExpResult *
+func_and(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+ EBookQuery **qs;
+
+ if (argc > 0) {
+ int i;
+
+ qs = g_new0(EBookQuery*, argc);
+
+ for (i = 0; i < argc; i ++) {
+ GList *list_head = *list;
+ if (!list_head)
+ break;
+ qs[i] = list_head->data;
+ *list = g_list_remove_link(*list, list_head);
+ g_list_free_1(list_head);
+ }
+
+ *list = g_list_prepend(*list,
+ e_book_query_and (argc, qs, TRUE));
+
+ g_free (qs);
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_or(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+ EBookQuery **qs;
+
+ if (argc > 0) {
+ int i;
+
+ qs = g_new0(EBookQuery*, argc);
+
+ for (i = 0; i < argc; i ++) {
+ GList *list_head = *list;
+ if (!list_head)
+ break;
+ qs[i] = list_head->data;
+ *list = g_list_remove_link(*list, list_head);
+ g_list_free_1(list_head);
+ }
+
+ *list = g_list_prepend(*list,
+ e_book_query_or (argc, qs, TRUE));
+
+ g_free (qs);
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_not(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ /* just replace the head of the list with the NOT of it. */
+ if (argc > 0) {
+ EBookQuery *term = (*list)->data;
+ (*list)->data = e_book_query_not (term, TRUE);
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+
+ if (!strcmp (propname, "x-evolution-any-field")) {
+ *list = g_list_prepend (*list, e_book_query_any_field_contains (str));
+ }
+ else {
+ EContactField field = e_contact_field_id (propname);
+
+ if (field)
+ *list = g_list_prepend (*list, e_book_query_field_test (field,
+ E_BOOK_QUERY_CONTAINS,
+ str));
+ }
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_is(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ EContactField field = e_contact_field_id (propname);
+
+ if (field)
+ *list = g_list_prepend (*list, e_book_query_field_test (field,
+ E_BOOK_QUERY_IS,
+ str));
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_beginswith(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ EContactField field = e_contact_field_id (propname);
+
+ if (field)
+ *list = g_list_prepend (*list, e_book_query_field_test (field,
+ E_BOOK_QUERY_BEGINS_WITH,
+ str));
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_endswith(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ EContactField field = e_contact_field_id (propname);
+
+ if (field)
+ *list = g_list_prepend (*list, e_book_query_field_test (field,
+ E_BOOK_QUERY_ENDS_WITH,
+ str));
+ }
+
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+/* 'builtin' functions */
+static struct {
+ char *name;
+ ESExpFunc *func;
+ int type; /* set to 1 if a function can perform shortcut evaluation, or
+ doesn't execute everything, 0 otherwise */
+} symbols[] = {
+ { "and", func_and, 0 },
+ { "or", func_or, 0 },
+ { "not", func_not, 0 },
+ { "contains", func_contains, 0 },
+ { "is", func_is, 0 },
+ { "beginswith", func_beginswith, 0 },
+ { "endswith", func_endswith, 0 },
+};
+
+EBookQuery*
+e_book_query_from_string (const char *query_string)
+{
+ ESExp *sexp;
+ ESExpResult *r;
+ EBookQuery *retval;
+ GList *list = NULL;
+ int i;
+
+ sexp = e_sexp_new();
+
+ for(i=0;i<sizeof(symbols)/sizeof(symbols[0]);i++) {
+ if (symbols[i].type == 1) {
+ e_sexp_add_ifunction(sexp, 0, symbols[i].name,
+ (ESExpIFunc *)symbols[i].func, &list);
+ } else {
+ e_sexp_add_function(sexp, 0, symbols[i].name,
+ symbols[i].func, &list);
+ }
+ }
+
+ e_sexp_input_text(sexp, query_string, strlen(query_string));
+ e_sexp_parse(sexp);
+
+ r = e_sexp_eval(sexp);
+
+ e_sexp_result_free(sexp, r);
+ e_sexp_unref (sexp);
+
+ if (list) {
+ if (list->next) {
+ g_warning ("conversion to EBookQuery");
+ retval = NULL;
+ g_list_foreach (list, (GFunc)e_book_query_unref, NULL);
+ }
+ else {
+ retval = list->data;
+ }
+ }
+ else {
+ g_warning ("conversion to EBookQuery failed");
+ retval = NULL;
+ }
+
+ g_list_free (list);
+ return retval;
+}
+
+char*
+e_book_query_to_string (EBookQuery *q)
+{
+ GString *str = g_string_new ("(");
+ int i;
+ char *s = NULL;
+
+ switch (q->type) {
+ case E_BOOK_QUERY_TYPE_AND:
+ g_string_append (str, "and ");
+ for (i = 0; i < q->query.andor.nqs; i ++) {
+ s = e_book_query_to_string (q->query.andor.qs[i]);
+ g_string_append (str, s);
+ g_free (s);
+ g_string_append_c (str, ' ');
+ }
+ break;
+ case E_BOOK_QUERY_TYPE_OR:
+ g_string_append (str, "or ");
+ for (i = 0; i < q->query.andor.nqs; i ++) {
+ s = e_book_query_to_string (q->query.andor.qs[i]);
+ g_string_append (str, s);
+ g_free (s);
+ g_string_append_c (str, ' ');
+ }
+ break;
+ case E_BOOK_QUERY_TYPE_NOT:
+ s = e_book_query_to_string (q->query.not.q);
+ g_string_append_printf (str, "not %s", s);
+ g_free (s);
+ break;
+ case E_BOOK_QUERY_TYPE_FIELD_EXISTS:
+ g_string_append_printf (str, "exists \"%s\"", e_contact_field_name (q->query.exist.field));
+ break;
+ case E_BOOK_QUERY_TYPE_FIELD_TEST:
+ switch (q->query.field_test.test) {
+ case E_BOOK_QUERY_IS: s = "is"; break;
+ case E_BOOK_QUERY_CONTAINS: s = "contains"; break;
+ case E_BOOK_QUERY_BEGINS_WITH: s = "beginswith"; break;
+ case E_BOOK_QUERY_ENDS_WITH: s = "endswith"; break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ /* XXX need to escape q->query.field_test.value */
+ g_string_append_printf (str, "%s \"%s\" \"%s\"",
+ s,
+ e_contact_field_name (q->query.field_test.field),
+ q->query.field_test.value);
+ break;
+ case E_BOOK_QUERY_TYPE_ANY_FIELD_CONTAINS:
+ g_string_append_printf (str, "contains \"x-evolution-any-field\" \"%s\"", q->query.any_field_contains.value);
+ break;
+ }
+
+
+ g_string_append (str, ")");
+
+ return g_string_free (str, FALSE);
+}
diff --git a/addressbook/backend/ebook/e-book-query.h b/addressbook/backend/ebook/e-book-query.h
new file mode 100644
index 0000000000..e36887f6f2
--- /dev/null
+++ b/addressbook/backend/ebook/e-book-query.h
@@ -0,0 +1,49 @@
+
+#ifndef __E_BOOK_QUERY_H__
+#define __E_BOOK_QUERY_H__
+
+#include <ebook/e-contact.h>
+
+G_BEGIN_DECLS
+
+typedef struct EBookQuery EBookQuery;
+
+typedef enum {
+ E_BOOK_QUERY_IS,
+ E_BOOK_QUERY_CONTAINS,
+ E_BOOK_QUERY_BEGINS_WITH,
+ E_BOOK_QUERY_ENDS_WITH,
+
+#if notyet
+ E_BOOK_QUERY_LT,
+ E_BOOK_QUERY_LE,
+ E_BOOK_QUERY_GT,
+ E_BOOK_QUERY_GE,
+ E_BOOK_QUERY_EQ,
+#endif
+} EBookQueryTest;
+
+EBookQuery* e_book_query_from_string (const char *sexp);
+char* e_book_query_to_string (EBookQuery *q);
+
+void e_book_query_ref (EBookQuery *q);
+void e_book_query_unref (EBookQuery *q);
+
+EBookQuery* e_book_query_and (int nqs, EBookQuery **qs, gboolean unref);
+EBookQuery* e_book_query_andv (EBookQuery *q, ...);
+EBookQuery* e_book_query_or (int nqs, EBookQuery **qs, gboolean unref);
+EBookQuery* e_book_query_orv (EBookQuery *q, ...);
+
+EBookQuery* e_book_query_not (EBookQuery *qs, gboolean unref);
+
+EBookQuery* e_book_query_field_exists (EContactField field);
+EBookQuery* e_book_query_field_test (EContactField field,
+ EBookQueryTest test,
+ const char *value);
+
+/* a special any field contains query */
+EBookQuery* e_book_query_any_field_contains (const char *value);
+
+G_END_DECLS
+
+#endif /* __E_BOOK_QUERY_H__ */
diff --git a/addressbook/backend/ebook/e-book-types.h b/addressbook/backend/ebook/e-book-types.h
index b1900e77ed..4ca69bd516 100644
--- a/addressbook/backend/ebook/e-book-types.h
+++ b/addressbook/backend/ebook/e-book-types.h
@@ -16,37 +16,52 @@
G_BEGIN_DECLS
+#define E_BOOK_ERROR e_book_error_quark()
+
+GQuark e_book_error_quark (void) G_GNUC_CONST;
+
typedef enum {
- E_BOOK_STATUS_SUCCESS,
- E_BOOK_STATUS_UNKNOWN,
- E_BOOK_STATUS_REPOSITORY_OFFLINE,
- E_BOOK_STATUS_PERMISSION_DENIED,
- E_BOOK_STATUS_CARD_NOT_FOUND,
- E_BOOK_STATUS_CARD_ID_ALREADY_EXISTS,
- E_BOOK_STATUS_PROTOCOL_NOT_SUPPORTED,
- E_BOOK_STATUS_CANCELLED,
- E_BOOK_STATUS_AUTHENTICATION_FAILED,
- E_BOOK_STATUS_AUTHENTICATION_REQUIRED,
- E_BOOK_STATUS_TLS_NOT_AVAILABLE,
- E_BOOK_STATUS_NO_SUCH_BOOK,
- E_BOOK_STATUS_OTHER_ERROR
+ E_BOOK_ERROR_OK,
+ E_BOOK_ERROR_INVALID_ARG,
+ E_BOOK_ERROR_BUSY,
+ E_BOOK_ERROR_REPOSITORY_OFFLINE,
+ E_BOOK_ERROR_NO_SUCH_BOOK,
+ E_BOOK_ERROR_URI_NOT_LOADED,
+ E_BOOK_ERROR_URI_ALREADY_LOADED,
+ E_BOOK_ERROR_PERMISSION_DENIED,
+ E_BOOK_ERROR_CONTACT_NOT_FOUND,
+ E_BOOK_ERROR_CONTACT_ID_ALREADY_EXISTS,
+ E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
+ E_BOOK_ERROR_CANCELLED,
+ E_BOOK_ERROR_COULD_NOT_CANCEL,
+ E_BOOK_ERROR_AUTHENTICATION_FAILED,
+ E_BOOK_ERROR_AUTHENTICATION_REQUIRED,
+ E_BOOK_ERROR_TLS_NOT_AVAILABLE,
+ E_BOOK_ERROR_CORBA_EXCEPTION,
+ E_BOOK_ERROR_OTHER_ERROR
} EBookStatus;
+
typedef enum {
- E_BOOK_VIEW_STATUS_SUCCESS,
+ E_BOOK_VIEW_STATUS_OK,
E_BOOK_VIEW_STATUS_TIME_LIMIT_EXCEEDED,
E_BOOK_VIEW_STATUS_SIZE_LIMIT_EXCEEDED,
- E_BOOK_VIEW_STATUS_INVALID_QUERY,
- E_BOOK_VIEW_STATUS_QUERY_REFUSED,
- E_BOOK_VIEW_STATUS_OTHER_ERROR,
- E_BOOK_VIEW_STATUS_UNKNOWN
+ E_BOOK_VIEW_ERROR_INVALID_QUERY,
+ E_BOOK_VIEW_ERROR_QUERY_REFUSED,
+ E_BOOK_VIEW_ERROR_OTHER_ERROR
} EBookViewStatus;
typedef enum {
- E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS,
- E_BOOK_SIMPLE_QUERY_STATUS_CANCELLED,
- E_BOOK_SIMPLE_QUERY_STATUS_OTHER_ERROR
-} EBookSimpleQueryStatus;
+ E_BOOK_CHANGE_CARD_ADDED,
+ E_BOOK_CHANGE_CARD_DELETED,
+ E_BOOK_CHANGE_CARD_MODIFIED
+} EBookChangeType;
+
+typedef struct {
+ EBookChangeType change_type;
+ char *vcard; /* used in the ADDED/MODIFIED case */
+ char *id; /* used in the DELETED case */
+} EBookChange;
G_END_DECLS
diff --git a/addressbook/backend/ebook/e-book-util.c b/addressbook/backend/ebook/e-book-util.c
deleted file mode 100644
index cc00d045f4..0000000000
--- a/addressbook/backend/ebook/e-book-util.c
+++ /dev/null
@@ -1,808 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-book-util.c
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Developed by Jon Trowbridge <trow@ximian.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA.
- */
-
-#include <config.h>
-#include "e-book-util.h"
-
-#include <string.h>
-#include <glib.h>
-#include <glib-object.h>
-#include <e-util/e-config-listener.h>
-#include "e-card-compare.h"
-
-typedef struct _CommonBookInfo CommonBookInfo;
-struct _CommonBookInfo {
- EBookCommonCallback cb;
- gpointer closure;
-};
-
-char *
-e_book_expand_uri (const char *uri)
-{
- if (!strncmp (uri, "file:", 5)) {
- int length = strlen (uri);
- int offset = 5;
-
- if (!strncmp (uri, "file://", 7))
- offset = 7;
-
- if (length < 3 || strcmp (uri + length - 3, ".db")) {
- /* we assume it's a dir and glom addressbook.db onto the end. */
-
- char *ret_val;
- char *file_name;
-
- file_name = g_build_filename(uri + offset, "addressbook.db", NULL);
- ret_val = g_strdup_printf("file://%s", file_name);
- g_free(file_name);
- return ret_val;
- }
- }
-
- return g_strdup (uri);
-}
-
-static void
-got_uri_book_cb (EBook *book, EBookStatus status, gpointer closure)
-{
- CommonBookInfo *info = (CommonBookInfo *) closure;
-
- if (status == E_BOOK_STATUS_SUCCESS) {
- info->cb (book, info->closure);
- } else {
- if (book)
- g_object_unref (book);
- info->cb (NULL, info->closure);
- }
- g_free (info);
-}
-
-void
-e_book_load_address_book_by_uri (EBook *book, const char *uri, EBookCallback open_response, gpointer closure)
-{
- char *real_uri;
-
- g_return_if_fail (book != NULL);
- g_return_if_fail (E_IS_BOOK (book));
- g_return_if_fail (open_response != NULL);
-
- real_uri = e_book_expand_uri (uri);
-
- e_book_load_uri (book, real_uri, open_response, closure);
-
- g_free (real_uri);
-}
-
-void
-e_book_use_address_book_by_uri (const char *uri, EBookCommonCallback cb, gpointer closure)
-{
- EBook *book;
- CommonBookInfo *info;
-
- g_return_if_fail (cb != NULL);
-
- info = g_new0 (CommonBookInfo, 1);
- info->cb = cb;
- info->closure = closure;
-
- book = e_book_new ();
- e_book_load_address_book_by_uri (book, uri, got_uri_book_cb, info);
-}
-
-EConfigListener *
-e_book_get_config_database ()
-{
- static EConfigListener *config_db;
-
- if (config_db == NULL)
- config_db = e_config_listener_new ();
-
- return config_db;
-}
-
-static EBook *common_default_book = NULL;
-
-static void
-got_default_book_cb (EBook *book, EBookStatus status, gpointer closure)
-{
- CommonBookInfo *info = (CommonBookInfo *) closure;
-
- if (status == E_BOOK_STATUS_SUCCESS) {
-
- /* We try not to leak in a race condition where the
- default book got loaded twice. */
-
- if (common_default_book) {
- g_object_unref (book);
- book = common_default_book;
- }
-
- info->cb (book, info->closure);
-
- if (common_default_book == NULL) {
- common_default_book = book;
- }
-
- } else {
- if (book)
- g_object_unref (book);
- info->cb (NULL, info->closure);
-
- }
- g_free (info);
-}
-
-void
-e_book_use_default_book (EBookCommonCallback cb, gpointer closure)
-{
- EBook *book;
- CommonBookInfo *info;
-
- g_return_if_fail (cb != NULL);
-
- if (common_default_book != NULL) {
- cb (common_default_book, closure);
- return;
- }
-
- info = g_new0 (CommonBookInfo, 1);
- info->cb = cb;
- info->closure = closure;
-
- book = e_book_new ();
- e_book_load_default_book (book, got_default_book_cb, info);
-}
-
-static char *default_book_uri;
-
-static char*
-get_local_book_uri (void)
-{
- char *filename;
- char *uri;
-
- filename = g_build_filename (g_get_home_dir(),
- "evolution/local/Contacts/addressbook.db",
- NULL);
- uri = g_strdup_printf ("file://%s", filename);
-
- g_free (filename);
-
- return uri;
-}
-
-static void
-set_default_book_uri_local (void)
-{
- g_free (default_book_uri);
-
- default_book_uri = get_local_book_uri ();
-}
-
-static void
-set_default_book_uri (char *val)
-{
- if (default_book_uri)
- g_free (default_book_uri);
-
- if (val) {
- default_book_uri = e_book_expand_uri (val);
- g_free (val);
- }
- else {
- set_default_book_uri_local ();
- }
-}
-
-#define DEFAULT_CONTACTS_URI_PATH "/apps/evolution/shell/default_folders/contacts_uri"
-static void
-default_folder_listener (EConfigListener *cl, const char *key, gpointer data)
-{
- char *val;
-
- if (strcmp (key, DEFAULT_CONTACTS_URI_PATH))
- return;
-
- val = e_config_listener_get_string (cl, DEFAULT_CONTACTS_URI_PATH);
-
- set_default_book_uri (val);
-}
-
-static void
-set_default_book_uri_from_config_db (void)
-{
- char *val;
- EConfigListener* config_db;
-
- config_db = e_book_get_config_database ();
- val = e_config_listener_get_string_with_default (config_db, DEFAULT_CONTACTS_URI_PATH, NULL, NULL);
-
- g_signal_connect (config_db,
- "key_changed",
- G_CALLBACK (default_folder_listener), NULL);
-
- set_default_book_uri (val);
-}
-
-typedef struct {
- gpointer closure;
- EBookCallback open_response;
-} DefaultBookClosure;
-
-static void
-e_book_default_book_open (EBook *book, EBookStatus status, gpointer closure)
-{
- DefaultBookClosure *default_book_closure = closure;
- gpointer user_closure = default_book_closure->closure;
- EBookCallback user_response = default_book_closure->open_response;
-
- g_free (default_book_closure);
-
- /* If there's a transient error, report it to the caller, but
- * if the old default folder has disappeared, fall back to the
- * local contacts folder instead, except when the default
- * folder is also the local folder.
- */
- if (status == E_BOOK_STATUS_PROTOCOL_NOT_SUPPORTED ||
- status == E_BOOK_STATUS_NO_SUCH_BOOK) {
- char *local_uri = get_local_book_uri();
- if (strcmp (local_uri, default_book_uri)) {
- set_default_book_uri_local ();
- e_book_load_default_book (book, user_response, user_closure);
- }
- else
- user_response (book, status, user_closure);
- g_free (local_uri);
- } else {
- user_response (book, status, user_closure);
- }
-}
-
-void
-e_book_load_default_book (EBook *book, EBookCallback open_response, gpointer closure)
-{
- const char *uri;
- DefaultBookClosure *default_book_closure;
-
- g_return_if_fail (book != NULL);
- g_return_if_fail (E_IS_BOOK (book));
- g_return_if_fail (open_response != NULL);
-
- uri = e_book_get_default_book_uri ();
-
- default_book_closure = g_new (DefaultBookClosure, 1);
-
- default_book_closure->closure = closure;
- default_book_closure->open_response = open_response;
-
- e_book_load_uri (book, uri,
- e_book_default_book_open, default_book_closure);
-
-}
-
-const char *
-e_book_get_default_book_uri ()
-{
- if (!default_book_uri)
- set_default_book_uri_from_config_db ();
-
- return default_book_uri;
-}
-
-/*
- *
- * Simple Query Stuff
- *
- */
-
-typedef struct _SimpleQueryInfo SimpleQueryInfo;
-struct _SimpleQueryInfo {
- guint tag;
- EBook *book;
- gchar *query;
- EBookSimpleQueryCallback cb;
- gpointer closure;
- EBookView *view;
- guint add_tag;
- guint seq_complete_tag;
- GList *cards;
- gboolean cancelled;
-};
-
-static void
-book_add_simple_query (EBook *book, SimpleQueryInfo *info)
-{
- GList *pending = g_object_get_data (G_OBJECT(book), "sq_pending");
- pending = g_list_prepend (pending, info);
- g_object_set_data (G_OBJECT (book), "sq_pending", pending);
-}
-
-static SimpleQueryInfo *
-book_lookup_simple_query (EBook *book, guint tag)
-{
- GList *pending = g_object_get_data (G_OBJECT (book), "sq_pending");
- while (pending) {
- SimpleQueryInfo *sq = pending->data;
- if (sq->tag == tag)
- return sq;
- pending = g_list_next (pending);
- }
- return NULL;
-}
-
-static void
-book_remove_simple_query (EBook *book, SimpleQueryInfo *info)
-{
- GList *pending = g_object_get_data (G_OBJECT (book), "sq_pending");
- GList *i;
-
- for (i=pending; i != NULL; i = g_list_next (i)) {
- if (i->data == info) {
- pending = g_list_remove_link (pending, i);
- g_list_free_1 (i);
- break;
- }
- }
- g_object_set_data (G_OBJECT (book), "sq_pending", pending);
-}
-
-static guint
-book_issue_tag (EBook *book)
-{
- gpointer ptr = g_object_get_data (G_OBJECT (book), "sq_tag");
- guint tag = GPOINTER_TO_UINT (ptr);
- if (tag == 0)
- tag = 1;
- g_object_set_data (G_OBJECT (book), "sq_tag", GUINT_TO_POINTER (tag+1));
- return tag;
-}
-
-static SimpleQueryInfo *
-simple_query_new (EBook *book, const char *query, EBookSimpleQueryCallback cb, gpointer closure)
-{
- SimpleQueryInfo *sq = g_new0 (SimpleQueryInfo, 1);
-
- sq->tag = book_issue_tag (book);
- sq->book = book;
- g_object_ref (book);
- sq->query = g_strdup (query);
- sq->cb = cb;
- sq->closure = closure;
- sq->cancelled = FALSE;
-
- /* Automatically add ourselves to the EBook's pending list. */
- book_add_simple_query (book, sq);
-
- return sq;
-}
-
-static void
-simple_query_disconnect (SimpleQueryInfo *sq)
-{
- if (sq->add_tag) {
- g_signal_handler_disconnect (sq->view, sq->add_tag);
- sq->add_tag = 0;
- }
-
- if (sq->seq_complete_tag) {
- g_signal_handler_disconnect (sq->view, sq->seq_complete_tag);
- sq->seq_complete_tag = 0;
- }
-
- if (sq->view) {
- g_object_unref (sq->view);
- sq->view = NULL;
- }
-}
-
-static void
-simple_query_free (SimpleQueryInfo *sq)
-{
- simple_query_disconnect (sq);
-
- /* Remove ourselves from the EBook's pending list. */
- book_remove_simple_query (sq->book, sq);
-
- g_free (sq->query);
-
- if (sq->book)
- g_object_unref (sq->book);
-
- g_list_foreach (sq->cards, (GFunc) g_object_unref, NULL);
- g_list_free (sq->cards);
-
- g_free (sq);
-}
-
-static void
-simple_query_card_added_cb (EBookView *view, const GList *cards, gpointer closure)
-{
- SimpleQueryInfo *sq = closure;
-
- if (sq->cancelled)
- return;
-
- sq->cards = g_list_concat (sq->cards, g_list_copy ((GList *) cards));
- g_list_foreach ((GList *) cards, (GFunc) g_object_ref, NULL);
-}
-
-static void
-simple_query_sequence_complete_cb (EBookView *view, EBookViewStatus status, gpointer closure)
-{
- SimpleQueryInfo *sq = closure;
-
- /* Disconnect signals, so that we don't pick up any changes to the book that occur
- in our callback */
- simple_query_disconnect (sq);
- if (! sq->cancelled)
- sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS, sq->cards, sq->closure);
- simple_query_free (sq);
-}
-
-static void
-simple_query_book_view_cb (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure)
-{
- SimpleQueryInfo *sq = closure;
-
- if (sq->cancelled) {
- simple_query_free (sq);
- return;
- }
-
- if (status != E_BOOK_STATUS_SUCCESS) {
- simple_query_disconnect (sq);
- sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_OTHER_ERROR, NULL, sq->closure);
- simple_query_free (sq);
- return;
- }
-
- sq->view = book_view;
- g_object_ref (book_view);
-
- sq->add_tag = g_signal_connect (sq->view, "card_added",
- G_CALLBACK (simple_query_card_added_cb), sq);
- sq->seq_complete_tag = g_signal_connect (sq->view, "sequence_complete",
- G_CALLBACK (simple_query_sequence_complete_cb), sq);
-}
-
-guint
-e_book_simple_query (EBook *book, const char *query, EBookSimpleQueryCallback cb, gpointer closure)
-{
- SimpleQueryInfo *sq;
-
- g_return_val_if_fail (book && E_IS_BOOK (book), 0);
- g_return_val_if_fail (query, 0);
- g_return_val_if_fail (cb, 0);
-
- sq = simple_query_new (book, query, cb, closure);
- e_book_get_book_view (book, (gchar *) query, simple_query_book_view_cb, sq);
-
- return sq->tag;
-}
-
-void
-e_book_simple_query_cancel (EBook *book, guint tag)
-{
- SimpleQueryInfo *sq;
-
- g_return_if_fail (book && E_IS_BOOK (book));
-
- sq = book_lookup_simple_query (book, tag);
-
- if (sq) {
- sq->cancelled = TRUE;
- sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_CANCELLED, NULL, sq->closure);
- } else {
- g_warning ("Simple query tag %d is unknown", tag);
- }
-}
-
-/*
- *
- * Specialized Queries
- *
- */
-
-typedef struct _NameEmailQueryInfo NameEmailQueryInfo;
-struct _NameEmailQueryInfo {
- gchar *name;
- gchar *email;
- EBookSimpleQueryCallback cb;
- gpointer closure;
-};
-
-static void
-name_email_query_info_free (NameEmailQueryInfo *info)
-{
- if (info) {
- g_free (info->name);
- g_free (info->email);
- g_free (info);
- }
-}
-
-static void
-name_and_email_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
-{
- NameEmailQueryInfo *info = closure;
- GList *filtered_cards = NULL;
-
- while (cards) {
- ECard *card = E_CARD (cards->data);
- if ((info->name == NULL || e_card_compare_name_to_string (card, info->name) >= E_CARD_MATCH_VAGUE)
- && (info->email == NULL || e_card_email_match_string (card, info->email))) {
- filtered_cards = g_list_append (filtered_cards, card);
- }
- cards = g_list_next (cards);
- }
-
- info->cb (book, status, filtered_cards, info->closure);
-
- g_list_free (filtered_cards);
-
- name_email_query_info_free (info);
-}
-
-guint
-e_book_name_and_email_query (EBook *book,
- const gchar *name,
- const gchar *email,
- EBookSimpleQueryCallback cb,
- gpointer closure)
-{
- NameEmailQueryInfo *info;
- gchar *email_query=NULL, *name_query=NULL, *query;
- guint tag;
-
- g_return_val_if_fail (book && E_IS_BOOK (book), 0);
- g_return_val_if_fail (cb != NULL, 0);
-
- if (name && !*name)
- name = NULL;
- if (email && !*email)
- email = NULL;
-
- if (name == NULL && email == NULL)
- return 0;
-
- /* Build our e-mail query.
- * We only query against the username part of the address, to avoid not matching
- * fred@foo.com and fred@mail.foo.com. While their may be namespace collisions
- * in the usernames of everyone out there, it shouldn't be that bad. (Famous last words.)
- */
- if (email) {
- const gchar *t = email;
- while (*t && *t != '@')
- ++t;
- if (*t == '@') {
- email_query = g_strdup_printf ("(beginswith \"email\" \"%.*s@\")", t-email, email);
-
- } else {
- email_query = g_strdup_printf ("(beginswith \"email\" \"%s\")", email);
- }
- }
-
- /* Build our name query.
- * We only do name-query stuff if we don't have an e-mail address. Our basic assumption
- * is that the username part of the email is good enough to keep the amount of stuff returned
- * in the query relatively small.
- */
- if (name && !email) {
- gchar *name_cpy = g_strdup (name), *qjoined;
- gchar **namev;
- gint i, count=0;
-
- g_strstrip (name_cpy);
- namev = g_strsplit (name_cpy, " ", 0);
- for (i=0; namev[i]; ++i) {
- if (*namev[i]) {
- char *str = namev[i];
-
- namev[i] = g_strdup_printf ("(contains \"file_as\" \"%s\")", namev[i]);
- ++count;
-
- g_free (str);
- }
- }
-
- qjoined = g_strjoinv (" ", namev);
- if (count > 1) {
- name_query = g_strdup_printf ("(or %s)", qjoined);
- } else {
- name_query = qjoined;
- qjoined = NULL;
- }
-
- g_free (name_cpy);
- g_strfreev (namev);
- g_free (qjoined);
- }
-
- /* Assemble our e-mail & name queries */
- if (email_query && name_query) {
- query = g_strdup_printf ("(and %s %s)", email_query, name_query);
- } else if (email_query) {
- query = email_query;
- email_query = NULL;
- } else if (name_query) {
- query = name_query;
- name_query = NULL;
- } else
- return 0;
-
- info = g_new0 (NameEmailQueryInfo, 1);
- info->name = g_strdup (name);
- info->email = g_strdup (email);
- info->cb = cb;
- info->closure = closure;
-
- tag = e_book_simple_query (book, query, name_and_email_cb, info);
-
- g_free (email_query);
- g_free (name_query);
- g_free (query);
-
- return tag;
-}
-
-/*
- * Simple nickname query
- */
-
-typedef struct _NicknameQueryInfo NicknameQueryInfo;
-struct _NicknameQueryInfo {
- gchar *nickname;
- EBookSimpleQueryCallback cb;
- gpointer closure;
-};
-
-static void
-nickname_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
-{
- NicknameQueryInfo *info = closure;
-
- if (info->cb)
- info->cb (book, status, cards, info->closure);
-
- g_free (info->nickname);
- g_free (info);
-}
-
-guint
-e_book_nickname_query (EBook *book,
- const char *nickname,
- EBookSimpleQueryCallback cb,
- gpointer closure)
-{
- NicknameQueryInfo *info;
- gchar *query;
- guint retval;
-
- g_return_val_if_fail (E_IS_BOOK (book), 0);
- g_return_val_if_fail (nickname != NULL, 0);
-
- /* The empty-string case shouldn't generate a warning. */
- if (! *nickname)
- return 0;
-
- info = g_new0 (NicknameQueryInfo, 1);
- info->nickname = g_strdup (nickname);
- info->cb = cb;
- info->closure = closure;
-
- query = g_strdup_printf ("(is \"nickname\" \"%s\")", info->nickname);
-
- retval = e_book_simple_query (book, query, nickname_cb, info);
-
- g_free (query);
-
- return retval;
-}
-
-/*
- * Convenience routine to check for addresses in the local address book.
- */
-
-typedef struct _HaveAddressInfo HaveAddressInfo;
-struct _HaveAddressInfo {
- gchar *email;
- EBookHaveAddressCallback cb;
- gpointer closure;
-};
-
-static void
-have_address_query_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
-{
- HaveAddressInfo *info = (HaveAddressInfo *) closure;
-
- info->cb (book,
- info->email,
- cards && (status == E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS) ? E_CARD (cards->data) : NULL,
- info->closure);
-
- g_free (info->email);
- g_free (info);
-}
-
-static void
-have_address_book_open_cb (EBook *book, gpointer closure)
-{
- HaveAddressInfo *info = (HaveAddressInfo *) closure;
-
- if (book) {
-
- e_book_name_and_email_query (book, NULL, info->email, have_address_query_cb, info);
-
- } else {
-
- info->cb (NULL, info->email, NULL, info->closure);
-
- g_free (info->email);
- g_free (info);
-
- }
-}
-
-void
-e_book_query_address_default (const gchar *email,
- EBookHaveAddressCallback cb,
- gpointer closure)
-{
- HaveAddressInfo *info;
-
- g_return_if_fail (email != NULL);
- g_return_if_fail (cb != NULL);
-
- info = g_new0 (HaveAddressInfo, 1);
- info->email = g_strdup (email);
- info->cb = cb;
- info->closure = closure;
-
- e_book_use_default_book (have_address_book_open_cb, info);
-}
-
-/* bad place for this i know. */
-int
-e_utf8_casefold_collate_len (const gchar *str1, const gchar *str2, int len)
-{
- gchar *s1 = g_utf8_casefold(str1, len);
- gchar *s2 = g_utf8_casefold(str2, len);
- int rv;
-
- rv = g_utf8_collate (s1, s2);
-
- g_free (s1);
- g_free (s2);
-
- return rv;
-}
-
-int
-e_utf8_casefold_collate (const gchar *str1, const gchar *str2)
-{
- return e_utf8_casefold_collate_len (str1, str2, -1);
-}
-
diff --git a/addressbook/backend/ebook/e-book-util.h b/addressbook/backend/ebook/e-book-util.h
deleted file mode 100644
index 39eb135332..0000000000
--- a/addressbook/backend/ebook/e-book-util.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-book-util.h
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Developed by Jon Trowbridge <trow@ximian.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA.
- */
-
-#ifndef __E_BOOK_UTIL_H__
-#define __E_BOOK_UTIL_H__
-
-#include "e-book.h"
-#include "e-util/e-config-listener.h"
-#include <bonobo/bonobo-object.h>
-#include <bonobo/bonobo-moniker-util.h>
-
-G_BEGIN_DECLS
-
-/* Callbacks for asynchronous functions. */
-typedef void (*EBookCommonCallback) (EBook *book, gpointer closure);
-typedef void (*EBookSimpleQueryCallback) (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure);
-typedef void (*EBookHaveAddressCallback) (EBook *book, const gchar *addr, ECard *card, gpointer closure);
-
-/* expand file:///foo/foo/ to file:///foo/foo/addressbook.db */
-char *e_book_expand_uri (const char *uri);
-
-void e_book_load_address_book_by_uri (EBook *book,
- const char *uri,
- EBookCallback open_response,
- gpointer closure);
-void e_book_use_address_book_by_uri (const char *uri,
- EBookCommonCallback cb,
- gpointer closure);
-
-void e_book_use_default_book (EBookCommonCallback cb,
- gpointer closure);
-void e_book_load_default_book (EBook *book,
- EBookCallback open_response,
- gpointer closure);
-const char *e_book_get_default_book_uri (void);
-
-/* config database interface. */
-EConfigListener *e_book_get_config_database (void);
-
-/* Simple Query Interface. */
-guint e_book_simple_query (EBook *book,
- const char *query,
- EBookSimpleQueryCallback cb,
- gpointer closure);
-void e_book_simple_query_cancel (EBook *book,
- guint tag);
-
-/* Specialized Name/Email Queries */
-guint e_book_name_and_email_query (EBook *book,
- const char *name,
- const char *email,
- EBookSimpleQueryCallback cb,
- gpointer closure);
-guint e_book_nickname_query (EBook *book,
- const char *nickname,
- EBookSimpleQueryCallback cb,
- gpointer closure);
-
-/* Returns the ECard associated to email in the callback,
- or NULL if no match is found in the default address book. */
-void e_book_query_address_default (const gchar *email,
- EBookHaveAddressCallback cb,
- gpointer closure);
-
-int e_utf8_casefold_collate_len (const gchar *str1, const gchar *str2, int len);
-int e_utf8_casefold_collate (const gchar *str1, const gchar *str2);
-
-G_END_DECLS
-
-#endif /* __E_BOOK_UTIL_H__ */
-
diff --git a/addressbook/backend/ebook/e-book-view-listener.c b/addressbook/backend/ebook/e-book-view-listener.c
index 668c442a9a..3ab2ff2708 100644
--- a/addressbook/backend/ebook/e-book-view-listener.c
+++ b/addressbook/backend/ebook/e-book-view-listener.c
@@ -13,13 +13,13 @@
#include <bonobo/bonobo-main.h>
#include "e-book-view-listener.h"
#include "e-book-view.h"
-#include "e-card.h"
+#include "e-contact.h"
#include "e-book-marshal.h"
-static EBookViewStatus e_book_view_listener_convert_status (GNOME_Evolution_Addressbook_BookViewListener_CallStatus status);
+static EBookViewStatus e_book_view_listener_convert_status (GNOME_Evolution_Addressbook_CallStatus status);
enum {
- RESPONSES_QUEUED,
+ RESPONSE,
LAST_SIGNAL
};
@@ -28,36 +28,9 @@ static guint e_book_view_listener_signals [LAST_SIGNAL];
static BonoboObjectClass *parent_class;
struct _EBookViewListenerPrivate {
- GList *response_queue;
- gint timeout_id;
-
- guint timeout_lock : 1;
guint stopped : 1;
};
-static gboolean
-e_book_view_listener_check_queue (EBookViewListener *listener)
-{
- if (listener->priv->timeout_lock)
- return TRUE;
-
- listener->priv->timeout_lock = TRUE;
-
- if (listener->priv->response_queue != NULL && !listener->priv->stopped) {
- g_signal_emit (listener, e_book_view_listener_signals [RESPONSES_QUEUED], 0);
- }
-
- if (listener->priv->response_queue == NULL || listener->priv->stopped) {
- listener->priv->timeout_id = 0;
- listener->priv->timeout_lock = FALSE;
- bonobo_object_unref (BONOBO_OBJECT (listener));
- return FALSE;
- }
-
- listener->priv->timeout_lock = FALSE;
- return TRUE;
-}
-
static void
e_book_view_listener_queue_response (EBookViewListener *listener,
EBookViewListenerResponse *response)
@@ -69,45 +42,14 @@ e_book_view_listener_queue_response (EBookViewListener *listener,
/* Free response and return */
g_list_foreach (response->ids, (GFunc)g_free, NULL);
g_list_free (response->ids);
- g_list_foreach (response->cards, (GFunc) g_object_unref, NULL);
- g_list_free (response->cards);
+ g_list_foreach (response->contacts, (GFunc) g_object_unref, NULL);
+ g_list_free (response->contacts);
g_free (response->message);
g_free (response);
return;
}
- /* a slight optimization for huge ldap queries. if there's an
- existing Add response on the end of the queue, and we're an
- Add response, we just glom the two lists of cards
- together */
- if (response->op == CardAddedEvent) {
- GList *last = g_list_last (listener->priv->response_queue);
- EBookViewListenerResponse *last_resp = NULL;
-
- if (last) last_resp = last->data;
-
- if (last_resp && last_resp->op == CardAddedEvent ) {
- response->cards = g_list_concat (last_resp->cards, response->cards);
- g_free (response);
- /* there should already be a timeout since the
- queue isn't empty, so we'll just return
- here */
- return;
- }
- else
- listener->priv->response_queue = g_list_append (last, response);
- }
- else
- listener->priv->response_queue = g_list_append (listener->priv->response_queue, response);
-
- if (listener->priv->timeout_id == 0) {
-
- /* Here, 20 == an arbitrary small number */
- listener->priv->timeout_id = g_timeout_add (20, (GSourceFunc) e_book_view_listener_check_queue, listener);
-
- /* Hold a reference to the listener on behalf of the timeout */
- bonobo_object_ref (BONOBO_OBJECT (listener));
- }
+ g_signal_emit (listener, e_book_view_listener_signals [RESPONSE], 0, response);
}
/* Add, Remove, Modify */
@@ -125,9 +67,6 @@ e_book_view_listener_queue_status_event (EBookViewListener *listener,
resp->op = op;
resp->status = status;
- resp->ids = NULL;
- resp->cards = NULL;
- resp->message = NULL;
e_book_view_listener_queue_response (listener, resp);
}
@@ -136,7 +75,7 @@ e_book_view_listener_queue_status_event (EBookViewListener *listener,
static void
e_book_view_listener_queue_idlist_event (EBookViewListener *listener,
EBookViewListenerOperation op,
- const GNOME_Evolution_Addressbook_CardIdList *ids)
+ const GNOME_Evolution_Addressbook_ContactIdList *ids)
{
EBookViewListenerResponse *resp;
int i;
@@ -147,10 +86,7 @@ e_book_view_listener_queue_idlist_event (EBookViewListener *listener,
resp = g_new0 (EBookViewListenerResponse, 1);
resp->op = op;
- resp->status = E_BOOK_VIEW_STATUS_SUCCESS;
- resp->ids = NULL;
- resp->cards = NULL;
- resp->message = NULL;
+ resp->status = E_BOOK_VIEW_STATUS_OK;
for (i = 0; i < ids->_length; i ++) {
resp->ids = g_list_prepend (resp->ids, g_strdup (ids->_buffer[i]));
@@ -163,7 +99,7 @@ e_book_view_listener_queue_idlist_event (EBookViewListener *listener,
static void
e_book_view_listener_queue_sequence_event (EBookViewListener *listener,
EBookViewListenerOperation op,
- const GNOME_Evolution_Addressbook_VCardList *cards)
+ const GNOME_Evolution_Addressbook_VCardList *vcards)
{
EBookViewListenerResponse *resp;
int i;
@@ -174,13 +110,10 @@ e_book_view_listener_queue_sequence_event (EBookViewListener *listener,
resp = g_new0 (EBookViewListenerResponse, 1);
resp->op = op;
- resp->status = E_BOOK_VIEW_STATUS_SUCCESS;
- resp->ids = NULL;
- resp->cards = NULL;
- resp->message = NULL;
+ resp->status = E_BOOK_VIEW_STATUS_OK;
- for ( i = 0; i < cards->_length; i++ ) {
- resp->cards = g_list_append(resp->cards, e_card_new(cards->_buffer[i]));
+ for ( i = 0; i < vcards->_length; i++ ) {
+ resp->contacts = g_list_append(resp->contacts, e_contact_new_from_vcard (vcards->_buffer[i]));
}
e_book_view_listener_queue_response (listener, resp);
@@ -200,135 +133,93 @@ e_book_view_listener_queue_message_event (EBookViewListener *listener,
resp = g_new0 (EBookViewListenerResponse, 1);
resp->op = op;
- resp->status = E_BOOK_VIEW_STATUS_SUCCESS;
- resp->ids = NULL;
- resp->cards = NULL;
+ resp->status = E_BOOK_VIEW_STATUS_OK;
resp->message = g_strdup(message);
e_book_view_listener_queue_response (listener, resp);
}
static void
-impl_BookViewListener_notify_card_added (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_VCardList *cards,
- CORBA_Environment *ev)
+impl_BookViewListener_notify_contacts_added (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_VCardList *vcards,
+ CORBA_Environment *ev)
{
EBookViewListener *listener = E_BOOK_VIEW_LISTENER (bonobo_object (servant));
+ printf ("impl_BookViewListener_notify_contacts_added\n");
+
e_book_view_listener_queue_sequence_event (
- listener, CardAddedEvent, cards);
+ listener, ContactsAddedEvent, vcards);
}
static void
-impl_BookViewListener_notify_cards_removed (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_CardIdList *ids,
- CORBA_Environment *ev)
+impl_BookViewListener_notify_contacts_removed (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_ContactIdList *ids,
+ CORBA_Environment *ev)
{
EBookViewListener *listener = E_BOOK_VIEW_LISTENER (bonobo_object (servant));
- e_book_view_listener_queue_idlist_event (listener, CardsRemovedEvent, ids);
+ printf ("impl_BookViewListener_notify_contacts_removed\n");
+
+ e_book_view_listener_queue_idlist_event (listener, ContactsRemovedEvent, ids);
}
static void
-impl_BookViewListener_notify_card_changed (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_VCardList *cards,
- CORBA_Environment *ev)
+impl_BookViewListener_notify_contacts_changed (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_VCardList *vcards,
+ CORBA_Environment *ev)
{
EBookViewListener *listener = E_BOOK_VIEW_LISTENER (bonobo_object (servant));
+ printf ("impl_BookViewListener_notify_contacts_changed\n");
+
e_book_view_listener_queue_sequence_event (
- listener, CardModifiedEvent, cards);
+ listener, ContactsModifiedEvent, vcards);
}
static void
impl_BookViewListener_notify_sequence_complete (PortableServer_Servant servant,
- const GNOME_Evolution_Addressbook_BookViewListener_CallStatus status,
+ const GNOME_Evolution_Addressbook_CallStatus status,
CORBA_Environment *ev)
{
EBookViewListener *listener = E_BOOK_VIEW_LISTENER (bonobo_object (servant));
+ printf ("impl_BookViewListener_notify_sequence_complete\n");
+
e_book_view_listener_queue_status_event (listener, SequenceCompleteEvent,
e_book_view_listener_convert_status (status));
}
static void
-impl_BookViewListener_notify_status_message (PortableServer_Servant servant,
- const char *message,
- CORBA_Environment *ev)
+impl_BookViewListener_notify_progress (PortableServer_Servant servant,
+ const char *message,
+ const CORBA_short percent,
+ CORBA_Environment *ev)
{
EBookViewListener *listener = E_BOOK_VIEW_LISTENER (bonobo_object (servant));
- e_book_view_listener_queue_message_event (listener, StatusMessageEvent, message);
-}
+ printf ("impl_BookViewListener_notify_progress\n");
-/**
- * e_book_view_listener_check_pending:
- * @listener: the #EBookViewListener
- *
- * Returns: the number of items on the response queue,
- * or -1 if the @listener is isn't an #EBookViewListener.
- */
-int
-e_book_view_listener_check_pending (EBookViewListener *listener)
-{
- g_return_val_if_fail (listener != NULL, -1);
- g_return_val_if_fail (E_IS_BOOK_VIEW_LISTENER (listener), -1);
-
- return g_list_length (listener->priv->response_queue);
-}
-
-/**
- * e_book_view_listener_pop_response:
- * @listener: the #EBookViewListener for which a request is to be popped
- *
- * Returns: an #EBookViewListenerResponse if there are responses on the
- * queue to be returned; %NULL if there aren't, or if the @listener
- * isn't an EBookViewListener.
- */
-EBookViewListenerResponse *
-e_book_view_listener_pop_response (EBookViewListener *listener)
-{
- EBookViewListenerResponse *resp;
- GList *popped;
-
- g_return_val_if_fail (listener != NULL, NULL);
- g_return_val_if_fail (E_IS_BOOK_VIEW_LISTENER (listener), NULL);
-
- if (listener->priv->response_queue == NULL)
- return NULL;
-
- resp = listener->priv->response_queue->data;
-
- popped = listener->priv->response_queue;
- listener->priv->response_queue =
- g_list_remove_link (listener->priv->response_queue,
- listener->priv->response_queue);
- g_list_free_1 (popped);
-
- return resp;
+ e_book_view_listener_queue_message_event (listener, StatusMessageEvent, message);
}
static EBookViewStatus
-e_book_view_listener_convert_status (const GNOME_Evolution_Addressbook_BookViewListener_CallStatus status)
+e_book_view_listener_convert_status (const GNOME_Evolution_Addressbook_CallStatus status)
{
switch (status) {
- case GNOME_Evolution_Addressbook_BookViewListener_Success:
- return E_BOOK_VIEW_STATUS_SUCCESS;
- case GNOME_Evolution_Addressbook_BookViewListener_SearchTimeLimitExceeded:
+ case GNOME_Evolution_Addressbook_Success:
+ return E_BOOK_VIEW_STATUS_OK;
+ case GNOME_Evolution_Addressbook_SearchTimeLimitExceeded:
return E_BOOK_VIEW_STATUS_TIME_LIMIT_EXCEEDED;
- case GNOME_Evolution_Addressbook_BookViewListener_SearchSizeLimitExceeded:
+ case GNOME_Evolution_Addressbook_SearchSizeLimitExceeded:
return E_BOOK_VIEW_STATUS_SIZE_LIMIT_EXCEEDED;
- case GNOME_Evolution_Addressbook_BookViewListener_InvalidQuery:
- return E_BOOK_VIEW_STATUS_INVALID_QUERY;
- case GNOME_Evolution_Addressbook_BookViewListener_QueryRefused:
- return E_BOOK_VIEW_STATUS_QUERY_REFUSED;
- case GNOME_Evolution_Addressbook_BookViewListener_OtherError:
- return E_BOOK_VIEW_STATUS_OTHER_ERROR;
+ case GNOME_Evolution_Addressbook_InvalidQuery:
+ return E_BOOK_VIEW_ERROR_INVALID_QUERY;
+ case GNOME_Evolution_Addressbook_QueryRefused:
+ return E_BOOK_VIEW_ERROR_QUERY_REFUSED;
+ case GNOME_Evolution_Addressbook_OtherError:
default:
- g_warning ("e_book_view_listener_convert_status: Unknown status "
- "from card server: %d\n", (int) status);
- return E_BOOK_VIEW_STATUS_UNKNOWN;
-
+ return E_BOOK_VIEW_ERROR_OTHER_ERROR;
}
}
@@ -351,7 +242,9 @@ e_book_view_listener_new ()
{
EBookViewListener *listener;
- listener = g_object_new (E_TYPE_BOOK_VIEW_LISTENER, NULL);
+ listener = g_object_new (E_TYPE_BOOK_VIEW_LISTENER,
+ "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_ALL_AT_IDLE, NULL),
+ NULL);
e_book_view_listener_construct (listener);
@@ -362,9 +255,6 @@ static void
e_book_view_listener_init (EBookViewListener *listener)
{
listener->priv = g_new0 (EBookViewListenerPrivate, 1);
- listener->priv->response_queue = NULL;
- listener->priv->timeout_id = 0;
- listener->priv->timeout_lock = FALSE;
listener->priv->stopped = FALSE;
}
@@ -381,32 +271,6 @@ e_book_view_listener_dispose (GObject *object)
EBookViewListener *listener = E_BOOK_VIEW_LISTENER (object);
if (listener->priv) {
- GList *l;
- /* Remove our response queue handler: In theory, this
- can never happen since we always hold a reference
- to the listener while the timeout is running. */
- if (listener->priv->timeout_id) {
- g_source_remove (listener->priv->timeout_id);
- }
-
- /* Clear out the queue */
- for (l = listener->priv->response_queue; l != NULL; l = l->next) {
- EBookViewListenerResponse *resp = l->data;
-
- g_list_foreach (resp->ids, (GFunc)g_free, NULL);
- g_list_free (resp->ids);
-
- g_list_foreach(resp->cards, (GFunc) g_object_unref, NULL);
- g_list_free(resp->cards);
- resp->cards = NULL;
-
- g_free (resp->message);
- resp->message = NULL;
-
- g_free (resp);
- }
- g_list_free (listener->priv->response_queue);
-
g_free (listener->priv);
listener->priv = NULL;
}
@@ -423,23 +287,24 @@ e_book_view_listener_class_init (EBookViewListenerClass *klass)
parent_class = g_type_class_ref (BONOBO_TYPE_OBJECT);
- e_book_view_listener_signals [RESPONSES_QUEUED] =
- g_signal_new ("responses_queued",
+ e_book_view_listener_signals [RESPONSE] =
+ g_signal_new ("response",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewListenerClass, responses_queued),
+ G_STRUCT_OFFSET (EBookViewListenerClass, response),
NULL, NULL,
- e_book_marshal_NONE__NONE,
- G_TYPE_NONE, 0);
+ e_book_marshal_NONE__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
object_class->dispose = e_book_view_listener_dispose;
epv = &klass->epv;
- epv->notifyCardChanged = impl_BookViewListener_notify_card_changed;
- epv->notifyCardsRemoved = impl_BookViewListener_notify_cards_removed;
- epv->notifyCardAdded = impl_BookViewListener_notify_card_added;
+ epv->notifyContactsChanged = impl_BookViewListener_notify_contacts_changed;
+ epv->notifyContactsRemoved = impl_BookViewListener_notify_contacts_removed;
+ epv->notifyContactsAdded = impl_BookViewListener_notify_contacts_added;
epv->notifySequenceComplete = impl_BookViewListener_notify_sequence_complete;
- epv->notifyStatusMessage = impl_BookViewListener_notify_status_message;
+ epv->notifyProgress = impl_BookViewListener_notify_progress;
}
BONOBO_TYPE_FUNC_FULL (
diff --git a/addressbook/backend/ebook/e-book-view-listener.h b/addressbook/backend/ebook/e-book-view-listener.h
index fd1c1395a7..a68f25c337 100644
--- a/addressbook/backend/ebook/e-book-view-listener.h
+++ b/addressbook/backend/ebook/e-book-view-listener.h
@@ -29,6 +29,8 @@ typedef struct _EBookViewListener EBookViewListener;
typedef struct _EBookViewListenerClass EBookViewListenerClass;
typedef struct _EBookViewListenerPrivate EBookViewListenerPrivate;
+typedef struct _EBookViewListenerResponse EBookViewListenerResponse;
+
struct _EBookViewListener {
BonoboObject parent;
EBookViewListenerPrivate *priv;
@@ -42,38 +44,44 @@ struct _EBookViewListenerClass {
/*
* Signals
*/
- void (*responses_queued) (void);
+ void (*response) (EBookViewListener *listener, EBookViewListenerResponse *response);
+
+
+ /* Padding for future expansion */
+ void (*_ebook_reserved0) (void);
+ void (*_ebook_reserved1) (void);
+ void (*_ebook_reserved2) (void);
+ void (*_ebook_reserved3) (void);
+ void (*_ebook_reserved4) (void);
};
typedef enum {
/* Async events */
- CardAddedEvent,
- CardsRemovedEvent,
- CardModifiedEvent,
+ ContactsAddedEvent,
+ ContactsRemovedEvent,
+ ContactsModifiedEvent,
SequenceCompleteEvent,
StatusMessageEvent,
} EBookViewListenerOperation;
-typedef struct {
+struct _EBookViewListenerResponse {
EBookViewListenerOperation op;
/* For SequenceComplete */
EBookViewStatus status;
- /* For CardsRemovedEvent */
+ /* For ContactsRemovedEvent */
GList *ids;
- /* For Card[Added|Modified]Event */
- GList *cards; /* Of type ECard. */
+ /* For Contact[sAdded|Modified]Event */
+ GList *contacts; /* Of type EContact. */
/* For StatusMessageEvent */
char *message;
-} EBookViewListenerResponse;
+};
EBookViewListener *e_book_view_listener_new (void);
-int e_book_view_listener_check_pending (EBookViewListener *listener);
-EBookViewListenerResponse *e_book_view_listener_pop_response (EBookViewListener *listener);
GType e_book_view_listener_get_type (void);
void e_book_view_listener_stop (EBookViewListener *listener);
diff --git a/addressbook/backend/ebook/e-book-view.c b/addressbook/backend/ebook/e-book-view.c
index e1f4b1623c..e8468e35de 100644
--- a/addressbook/backend/ebook/e-book-view.c
+++ b/addressbook/backend/ebook/e-book-view.c
@@ -11,7 +11,6 @@
#include <config.h>
#include "addressbook.h"
-#include "e-card-cursor.h"
#include "e-book-view-listener.h"
#include "e-book-view.h"
#include "e-book.h"
@@ -26,13 +25,13 @@ struct _EBookViewPrivate {
EBookViewListener *listener;
- int responses_queued_id;
+ int response_id;
};
enum {
- CARD_CHANGED,
- CARD_REMOVED,
- CARD_ADDED,
+ CONTACTS_CHANGED,
+ CONTACTS_REMOVED,
+ CONTACTS_ADDED,
SEQUENCE_COMPLETE,
STATUS_MESSAGE,
LAST_SIGNAL
@@ -41,47 +40,32 @@ enum {
static guint e_book_view_signals [LAST_SIGNAL];
static void
-add_book_iterator (gpointer data, gpointer closure)
-{
- ECard *card = E_CARD (data);
- EBook *book = E_BOOK (closure);
-
- e_card_set_book (card, book);
-}
-
-static void
e_book_view_do_added_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
- if (book_view->priv->book)
- g_list_foreach (resp->cards, add_book_iterator, book_view->priv->book);
-
- g_signal_emit (book_view, e_book_view_signals [CARD_ADDED], 0,
- resp->cards);
+ g_signal_emit (book_view, e_book_view_signals [CONTACTS_ADDED], 0,
+ resp->contacts);
- g_list_foreach (resp->cards, (GFunc) g_object_unref, NULL);
- g_list_free (resp->cards);
+ g_list_foreach (resp->contacts, (GFunc) g_object_unref, NULL);
+ g_list_free (resp->contacts);
}
static void
e_book_view_do_modified_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
- if (book_view->priv->book)
- g_list_foreach (resp->cards, add_book_iterator, book_view->priv->book);
+ g_signal_emit (book_view, e_book_view_signals [CONTACTS_CHANGED], 0,
+ resp->contacts);
- g_signal_emit (book_view, e_book_view_signals [CARD_CHANGED], 0,
- resp->cards);
-
- g_list_foreach (resp->cards, (GFunc) g_object_unref, NULL);
- g_list_free (resp->cards);
+ g_list_foreach (resp->contacts, (GFunc) g_object_unref, NULL);
+ g_list_free (resp->contacts);
}
static void
e_book_view_do_removed_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
- g_signal_emit (book_view, e_book_view_signals [CARD_REMOVED], 0,
+ g_signal_emit (book_view, e_book_view_signals [CONTACTS_REMOVED], 0,
resp->ids);
g_list_foreach (resp->ids, (GFunc) g_free, NULL);
@@ -106,27 +90,20 @@ e_book_view_do_status_message_event (EBookView *book_view,
}
-/*
- * Reading notices out of the EBookViewListener's queue.
- */
static void
-e_book_view_check_listener_queue (EBookViewListener *listener, EBookView *book_view)
+e_book_view_handle_response (EBookViewListener *listener, EBookViewListenerResponse *resp, EBookView *book_view)
{
- EBookViewListenerResponse *resp;
-
- resp = e_book_view_listener_pop_response (listener);
-
if (resp == NULL)
return;
switch (resp->op) {
- case CardAddedEvent:
+ case ContactsAddedEvent:
e_book_view_do_added_event (book_view, resp);
break;
- case CardModifiedEvent:
+ case ContactsModifiedEvent:
e_book_view_do_modified_event (book_view, resp);
break;
- case CardsRemovedEvent:
+ case ContactsRemovedEvent:
e_book_view_do_removed_event (book_view, resp);
break;
case SequenceCompleteEvent:
@@ -171,8 +148,8 @@ e_book_view_construct (EBookView *book_view, GNOME_Evolution_Addressbook_BookVie
* Create our local BookListener interface.
*/
book_view->priv->listener = listener;
- book_view->priv->responses_queued_id = g_signal_connect (book_view->priv->listener, "responses_queued",
- G_CALLBACK (e_book_view_check_listener_queue), book_view);
+ book_view->priv->response_id = g_signal_connect (book_view->priv->listener, "response",
+ G_CALLBACK (e_book_view_handle_response), book_view);
bonobo_object_ref(BONOBO_OBJECT(book_view->priv->listener));
@@ -209,6 +186,22 @@ e_book_view_set_book (EBookView *book_view, EBook *book)
}
void
+e_book_view_start (EBookView *book_view)
+{
+ CORBA_Environment ev;
+
+ g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Addressbook_BookView_start (book_view->priv->corba_book_view, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("corba exception._major = %d\n", ev._major);
+ }
+}
+
+void
e_book_view_stop (EBookView *book_view)
{
g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
@@ -223,7 +216,7 @@ e_book_view_init (EBookView *book_view)
book_view->priv->book = NULL;
book_view->priv->corba_book_view = CORBA_OBJECT_NIL;
book_view->priv->listener = NULL;
- book_view->priv->responses_queued_id = 0;
+ book_view->priv->response_id = 0;
}
static void
@@ -250,9 +243,9 @@ e_book_view_dispose (GObject *object)
}
if (book_view->priv->listener) {
- if (book_view->priv->responses_queued_id)
+ if (book_view->priv->response_id)
g_signal_handler_disconnect(book_view->priv->listener,
- book_view->priv->responses_queued_id);
+ book_view->priv->response_id);
e_book_view_listener_stop (book_view->priv->listener);
bonobo_object_unref (BONOBO_OBJECT(book_view->priv->listener));
}
@@ -271,31 +264,31 @@ e_book_view_class_init (EBookViewClass *klass)
parent_class = g_type_class_ref (G_TYPE_OBJECT);
- e_book_view_signals [CARD_CHANGED] =
- g_signal_new ("card_changed",
+ e_book_view_signals [CONTACTS_CHANGED] =
+ g_signal_new ("contacts_changed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, card_changed),
+ G_STRUCT_OFFSET (EBookViewClass, contacts_changed),
NULL, NULL,
e_book_marshal_NONE__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
- e_book_view_signals [CARD_ADDED] =
- g_signal_new ("card_added",
+ e_book_view_signals [CONTACTS_ADDED] =
+ g_signal_new ("contacts_added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, card_added),
+ G_STRUCT_OFFSET (EBookViewClass, contacts_added),
NULL, NULL,
e_book_marshal_NONE__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
- e_book_view_signals [CARD_REMOVED] =
- g_signal_new ("card_removed",
+ e_book_view_signals [CONTACTS_REMOVED] =
+ g_signal_new ("contacts_removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, card_removed),
+ G_STRUCT_OFFSET (EBookViewClass, contacts_removed),
NULL, NULL,
e_book_marshal_NONE__POINTER,
G_TYPE_NONE, 1,
diff --git a/addressbook/backend/ebook/e-book-view.h b/addressbook/backend/ebook/e-book-view.h
index bd7a97d1d5..5b9768315b 100644
--- a/addressbook/backend/ebook/e-book-view.h
+++ b/addressbook/backend/ebook/e-book-view.h
@@ -13,7 +13,6 @@
#include <glib.h>
#include <glib-object.h>
-#include <ebook/e-card.h>
#include <ebook/e-book-view-listener.h>
#define E_TYPE_BOOK_VIEW (e_book_view_get_type ())
@@ -42,11 +41,18 @@ struct _EBookViewClass {
/*
* Signals.
*/
- void (* card_changed) (EBookView *book_view, const GList *cards);
- void (* card_removed) (EBookView *book_view, const GList *ids);
- void (* card_added) (EBookView *book_view, const GList *cards);
+ void (* contacts_changed) (EBookView *book_view, const GList *contacts);
+ void (* contacts_removed) (EBookView *book_view, const GList *ids);
+ void (* contacts_added) (EBookView *book_view, const GList *contacts);
void (* sequence_complete) (EBookView *book_view, EBookViewStatus status);
void (* status_message) (EBookView *book_view, const char *message);
+
+ /* Padding for future expansion */
+ void (*_ebook_reserved0) (void);
+ void (*_ebook_reserved1) (void);
+ void (*_ebook_reserved2) (void);
+ void (*_ebook_reserved3) (void);
+ void (*_ebook_reserved4) (void);
};
/* Creating a new addressbook. */
@@ -56,6 +62,7 @@ GType e_book_view_get_type (void);
void e_book_view_set_book (EBookView *book_view, struct _EBook *book);
+void e_book_view_start (EBookView *book_view);
void e_book_view_stop (EBookView *book_view);
G_END_DECLS
diff --git a/addressbook/backend/ebook/e-book.c b/addressbook/backend/ebook/e-book.c
index 08a0aac995..3883cd4b15 100644
--- a/addressbook/backend/ebook/e-book.c
+++ b/addressbook/backend/ebook/e-book.c
@@ -1,34 +1,86 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * The Evolution addressbook client object.
- *
- * Author:
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright 1999, 2000, Ximian, Inc.
- */
#include <config.h>
-#include <glib.h>
-#include <glib-object.h>
+
+#include <pthread.h>
+
#include <string.h>
-#include <bonobo-activation/bonobo-activation.h>
-#include "addressbook.h"
-#include "e-card-cursor.h"
-#include "e-book-listener.h"
#include "e-book.h"
+#include "e-vcard.h"
+
+#include <bonobo-activation/bonobo-activation.h>
+
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-main.h>
+
+#include <libgnome/gnome-i18n.h>
+
#include "e-book-marshal.h"
+#include "e-book-listener.h"
+#include "addressbook.h"
#include "e-util/e-component-listener.h"
+#include "e-util/e-msgport.h"
static GObjectClass *parent_class;
#define CARDSERVER_OAF_ID "OAFIID:GNOME_Evolution_Wombat_ServerFactory"
+#define e_return_error_if_fail(expr,error_code) G_STMT_START{ \
+ if G_LIKELY(expr) { } else \
+ { \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #expr); \
+ g_set_error (error, E_BOOK_ERROR, (error_code), \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #expr); \
+ return FALSE; \
+ }; }G_STMT_END
+
+/* XXX we need a better error message here */
+#define E_BOOK_CHECK_STATUS(status,error) G_STMT_START{ \
+ if ((status) == E_BOOK_ERROR_OK) { \
+ return TRUE; \
+ } \
+ else { \
+ g_set_error ((error), E_BOOK_ERROR, (status), "EBookStatus returned %d", (status)); \
+ return FALSE; \
+ } }G_STMT_END
+
+enum {
+ OPEN_PROGRESS,
+ WRITABLE_STATUS,
+ BACKEND_DIED,
+ LAST_SIGNAL
+};
+
+static guint e_book_signals [LAST_SIGNAL];
+
+typedef struct {
+ EMutex *mutex;
+ pthread_cond_t cond;
+ EBookStatus status;
+
+ char *id;
+ GList *list;
+ EContact *contact;
+
+ EBookView *view;
+ EBookViewListener *listener;
+} EBookOp;
+
typedef enum {
- URINotLoaded,
- URILoading,
- URILoaded
+ E_BOOK_URI_NOT_LOADED,
+ E_BOOK_URI_LOADING,
+ E_BOOK_URI_LOADED
} EBookLoadState;
struct _EBookPrivate {
@@ -39,21 +91,20 @@ struct _EBookPrivate {
char *cap;
gboolean cap_queried;
- EBookListener *listener;
+ /* cached writable status */
+ gboolean writable;
+
+ EBookListener *listener;
EComponentListener *comp_listener;
GNOME_Evolution_Addressbook_Book corba_book;
EBookLoadState load_state;
- /*
- * The operation queue. New operations are appended to the
- * end of the queue. When responses come back from the PAS,
- * the op structures are popped off the front of the queue.
- */
- GList *pending_ops;
- guint op_tag;
+ EBookOp *current_op;
+
+ EMutex *mutex;
gchar *uri;
@@ -61,1526 +112,1844 @@ struct _EBookPrivate {
gulong died_signal;
};
-enum {
- OPEN_PROGRESS,
- WRITABLE_STATUS,
- LINK_STATUS,
- BACKEND_DIED,
- LAST_SIGNAL
-};
-
-static guint e_book_signals [LAST_SIGNAL];
+
+/* Error quark */
+GQuark
+e_book_error_quark (void)
+{
+ static GQuark q = 0;
+ if (q == 0)
+ q = g_quark_from_static_string ("e-book-error-quark");
-typedef struct {
- guint tag;
- gboolean active;
- gpointer cb;
- gpointer closure;
- EBookViewListener *listener;
-} EBookOp;
+ return q;
+}
-/*
- * Local response queue management.
- */
+
-static void
-e_book_op_free (EBookOp *op)
-{
- if (op->listener) {
- bonobo_object_unref (BONOBO_OBJECT (op->listener));
- op->listener = NULL;
- }
- g_free (op);
-}
+/* EBookOp calls */
-static guint
-e_book_queue_op (EBook *book,
- gpointer cb,
- gpointer closure,
- EBookViewListener *listener)
+static EBookOp*
+e_book_new_op (EBook *book)
{
- EBookOp *op;
+ EBookOp *op = g_new0 (EBookOp, 1);
- op = g_new0 (EBookOp, 1);
- op->tag = book->priv->op_tag++;
- op->active = TRUE;
- op->cb = cb;
- op->closure = closure;
- op->listener = listener;
+ op->mutex = e_mutex_new (E_MUTEX_SIMPLE);
+ pthread_cond_init (&op->cond, 0);
- if (op->listener)
- bonobo_object_ref (BONOBO_OBJECT (op->listener));
+ book->priv->current_op = op;
- book->priv->pending_ops =
- g_list_append (book->priv->pending_ops, op);
+ return op;
+}
- return op->tag;
+static EBookOp*
+e_book_get_op (EBook *book)
+{
+ if (!book->priv->current_op) {
+ g_warning ("unexpected response");
+ return NULL;
+ }
+
+ return book->priv->current_op;
}
-/*
- * Local response queue management.
- */
static void
-e_book_unqueue_op (EBook *book)
+e_book_op_free (EBookOp *op)
{
- EBookOp *op;
- GList *removed;
+ /* XXX more stuff here */
+ pthread_cond_destroy (&op->cond);
+ e_mutex_destroy (op->mutex);
+ g_free (op);
+}
- removed = g_list_last (book->priv->pending_ops);
+static void
+e_book_op_remove (EBook *book,
+ EBookOp *op)
+{
+ if (book->priv->current_op != op)
+ g_warning ("cannot remove op, it's not current");
- if (removed) {
- book->priv->pending_ops = g_list_remove_link (book->priv->pending_ops,
- removed);
- op = removed->data;
- e_book_op_free (op);
- g_list_free_1 (removed);
- book->priv->op_tag--;
- }
+ book->priv->current_op = NULL;
}
-static EBookOp *
-e_book_pop_op (EBook *book)
+static void
+e_book_clear_op (EBook *book,
+ EBookOp *op)
{
- GList *popped;
- EBookOp *op;
+ e_book_op_remove (book, op);
+ e_mutex_unlock (op->mutex);
+ e_book_op_free (op);
+}
- if (book->priv->pending_ops == NULL)
- return NULL;
+
- op = book->priv->pending_ops->data;
+/**
+ * e_book_add_card:
+ * @book: an #EBook
+ * @contact: an #EContact
+ *
+ * adds @contact to @book.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_add_contact (EBook *book,
+ EContact *contact,
+ GError **error)
+{
+ EBookOp *our_op;
+ EBookStatus status;
+ CORBA_Environment ev;
+ char *vcard_str;
- popped = book->priv->pending_ops;
- book->priv->pending_ops =
- g_list_remove_link (book->priv->pending_ops,
- book->priv->pending_ops);
+ printf ("e_book_add_contact\n");
- g_list_free_1 (popped);
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- return op;
-}
+ e_mutex_lock (book->priv->mutex);
-static gboolean
-e_book_cancel_op (EBook *book, guint tag)
-{
- GList *iter;
- gboolean cancelled = FALSE;
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_add_contact called on book before e_book_load_uri"));
+ return FALSE;
+ }
- for (iter = book->priv->pending_ops; iter != NULL && !cancelled; iter = g_list_next (iter)) {
- EBookOp *op = iter->data;
- if (op->tag == tag) {
- op->active = FALSE;
- cancelled = TRUE;
- }
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
-
- return cancelled;
-}
-static void
-e_book_do_response_create_card (EBook *book,
- EBookListenerResponse *resp)
-{
- EBookOp *op;
+ vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
- op = e_book_pop_op (book);
+ our_op = e_book_new_op (book);
- if (op == NULL) {
- g_warning ("e_book_do_response_create_card: Cannot find operation "
- "in local op queue!\n");
- return;
- }
+ e_mutex_lock (our_op->mutex);
- if (op->cb)
- ((EBookIdCallback) op->cb) (book, resp->status, resp->id, op->closure);
- g_free (resp->id);
- e_book_op_free (op);
-}
+ e_mutex_unlock (book->priv->mutex);
-static void
-e_book_do_response_generic (EBook *book,
- EBookListenerResponse *resp)
-{
- EBookOp *op;
+ CORBA_exception_init (&ev);
- op = e_book_pop_op (book);
+ /* will eventually end up calling e_book_response_add_contact */
+ GNOME_Evolution_Addressbook_Book_addContact (book->priv->corba_book,
+ (const GNOME_Evolution_Addressbook_VCard) vcard_str, &ev);
- if (op == NULL) {
- g_warning ("e_book_do_response_generic: Cannot find operation "
- "in local op queue!\n");
+ g_free (vcard_str);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+
+ e_book_clear_op (book, our_op);
+
+ CORBA_exception_free (&ev);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::addContact call"));
+ return FALSE;
}
- if (op->cb)
- ((EBookCallback) op->cb) (book, resp->status, op->closure);
+ CORBA_exception_free (&ev);
- e_book_op_free (op);
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
+
+ status = our_op->status;
+ e_contact_set (contact, E_CONTACT_UID, our_op->id);
+ g_free (our_op->id);
+
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
static void
-e_book_do_response_get_vcard (EBook *book,
- EBookListenerResponse *resp)
+e_book_response_add_contact (EBook *book,
+ EBookStatus status,
+ char *id)
{
EBookOp *op;
- ECard *card;
- op = e_book_pop_op (book);
+ printf ("e_book_response_add_contact\n");
+
+ op = e_book_get_op (book);
if (op == NULL) {
- g_warning ("e_book_do_response_get_vcard: Cannot find operation "
- "in local op queue!\n");
- return;
+ g_warning ("e_book_response_add_contact: Cannot find operation ");
+ return;
}
- if (resp->vcard != NULL) {
- card = e_card_new(resp->vcard);
+ e_mutex_lock (op->mutex);
- if (card != NULL) {
- e_card_set_book (card, book);
- if (op->cb) {
- if (op->active)
- ((EBookCardCallback) op->cb) (book, resp->status, card, op->closure);
- else
- ((EBookCardCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
- }
+ op->status = status;
+ op->id = g_strdup (id);
- g_object_unref(card);
- } else {
- ((EBookCursorCallback) op->cb) (book, resp->status, NULL, op->closure);
- }
- } else {
- ((EBookCardCallback) op->cb) (book, resp->status, NULL, op->closure);
- }
+ pthread_cond_signal (&op->cond);
- g_free (resp->vcard);
- e_book_op_free (op);
+ e_mutex_unlock (op->mutex);
}
-static void
-e_book_do_response_get_cursor (EBook *book,
- EBookListenerResponse *resp)
+
+
+/**
+ * e_book_commit_contact:
+ * @book: an #EBook
+ * @contact: an #EContact
+ *
+ * applies the changes made to @contact to the stored version in
+ * @book.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_commit_contact (EBook *book,
+ EContact *contact,
+ GError **error)
{
+ EBookOp *our_op;
+ EBookStatus status;
CORBA_Environment ev;
- EBookOp *op;
- ECardCursor *cursor;
+ char *vcard_str;
- op = e_book_pop_op (book);
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- if (op == NULL) {
- g_warning ("e_book_do_response_get_cursor: Cannot find operation "
- "in local op queue!\n");
- return;
+ e_mutex_lock (book->priv->mutex);
+
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_commit_contact called on book before e_book_load_uri"));
+ return FALSE;
}
- cursor = e_card_cursor_new(resp->cursor);
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
+ }
- if (cursor != NULL) {
- if (op->cb) {
- if (op->active)
- ((EBookCursorCallback) op->cb) (book, resp->status, cursor, op->closure);
- else
- ((EBookCursorCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
- }
+ vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
- /*
- * Release the remote GNOME_Evolution_Addressbook_Book in the PAS.
- */
- CORBA_exception_init (&ev);
+ our_op = e_book_new_op (book);
- bonobo_object_release_unref (resp->cursor, &ev);
+ e_mutex_lock (our_op->mutex);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_do_response_get_cursor: Exception releasing "
- "remote GNOME_Evolution_Addressbook_CardCursor interface!\n");
- }
+ e_mutex_unlock (book->priv->mutex);
- CORBA_exception_free (&ev);
+ CORBA_exception_init (&ev);
- g_object_unref(cursor);
- } else {
- ((EBookCursorCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
- }
-
- e_book_op_free (op);
-}
+ /* will eventually end up calling _e_book_response_generic */
+ GNOME_Evolution_Addressbook_Book_modifyContact (book->priv->corba_book,
+ (const GNOME_Evolution_Addressbook_VCard) vcard_str, &ev);
-static void
-e_book_do_response_get_view (EBook *book,
- EBookListenerResponse *resp)
-{
- CORBA_Environment ev;
- EBookOp *op;
- EBookView *book_view;
+ g_free (vcard_str);
- op = e_book_pop_op (book);
+ if (ev._major != CORBA_NO_EXCEPTION) {
- if (op == NULL) {
- g_warning ("e_book_do_response_get_view: Cannot find operation "
- "in local op queue!\n");
- return;
+ e_book_clear_op (book, our_op);
+
+ CORBA_exception_free (&ev);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::modifyContact call"));
+ return FALSE;
}
-
- book_view = e_book_view_new (resp->book_view, op->listener);
-
- if (book_view != NULL) {
- e_book_view_set_book (book_view, book);
-
- /* Only execute the callback if the operation is still flagged as active (i.e. hasn't
- been cancelled. This is mildly wasteful since we unnecessaryily create the
- book_view, etc... but I'm leery of tinkering with the CORBA magic. */
- if (op->cb) {
- if (op->active)
- ((EBookBookViewCallback) op->cb) (book, resp->status, book_view, op->closure);
- else
- ((EBookBookViewCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
- }
-
- /*
- * Release the remote GNOME_Evolution_Addressbook_Book in the PAS.
- */
- CORBA_exception_init (&ev);
- bonobo_object_release_unref (resp->book_view, &ev);
+ CORBA_exception_free (&ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_do_response_get_view: Exception releasing "
- "remote GNOME_Evolution_Addressbook_BookView interface!\n");
- }
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
- CORBA_exception_free (&ev);
+ status = our_op->status;
+ e_contact_set (contact, E_CONTACT_UID, our_op->id);
+ g_free (our_op->id);
- g_object_unref(book_view);
- } else {
- e_book_view_listener_stop (op->listener);
- ((EBookBookViewCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
- }
+ /* remove the op from the book's hash of operations */
+ e_book_clear_op (book, our_op);
- e_book_op_free (op);
+ E_BOOK_CHECK_STATUS (status, error);
}
-static void
-e_book_do_response_get_changes (EBook *book,
- EBookListenerResponse *resp)
+
+/**
+ * e_book_get_supported_fields:
+ * @book: an #EBook
+ * @fields: a #GList
+ *
+ * queries @book for the list of fields it supports. mostly for use
+ * by the contact editor so it knows what fields to sensitize.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_get_supported_fields (EBook *book,
+ GList **fields,
+ GError **error)
{
+ EBookOp *our_op;
+ EBookStatus status;
CORBA_Environment ev;
- EBookOp *op;
- EBookView *book_view;
- op = e_book_pop_op (book);
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (fields, E_BOOK_ERROR_INVALID_ARG);
- if (op == NULL) {
- g_warning ("e_book_do_response_get_changes: Cannot find operation "
- "in local op queue!\n");
- return;
+ e_mutex_lock (book->priv->mutex);
+
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_get_supported_fields on book before e_book_load_uri"));
+ return FALSE;
}
- book_view = e_book_view_new (resp->book_view, op->listener);
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ }
- if (book_view != NULL) {
- e_book_view_set_book (book_view, book);
-
- if (op->cb) {
- if (op->active)
- ((EBookBookViewCallback) op->cb) (book, resp->status, book_view, op->closure);
- else
- ((EBookBookViewCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
- }
+ our_op = e_book_new_op (book);
- /*
- * Release the remote GNOME_Evolution_Addressbook_BookView in the PAS.
- */
- CORBA_exception_init (&ev);
+ e_mutex_lock (our_op->mutex);
- bonobo_object_release_unref (resp->book_view, &ev);
+ e_mutex_unlock (book->priv->mutex);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_do_response_get_changes: Exception releasing "
- "remote GNOME_Evolution_Addressbook_BookView interface!\n");
- }
+ CORBA_exception_init (&ev);
+
+ /* will eventually end up calling
+ _e_book_response_get_supported_fields */
+ GNOME_Evolution_Addressbook_Book_getSupportedFields(book->priv->corba_book, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+
+ e_book_clear_op (book, our_op);
CORBA_exception_free (&ev);
- g_object_unref(book_view);
- } else {
- e_book_view_listener_stop (op->listener);
- ((EBookBookViewCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::getSupportedFields call"));
+ return FALSE;
}
- e_book_op_free (op);
-}
-static void
-backend_died_cb (EComponentListener *cl, gpointer user_data)
-{
- EBook *book = user_data;
+ CORBA_exception_free (&ev);
- book->priv->load_state = URINotLoaded;
- g_signal_emit (book, e_book_signals [BACKEND_DIED], 0);
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
+
+ status = our_op->status;
+ *fields = our_op->list;
+
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
static void
-e_book_do_response_open (EBook *book,
- EBookListenerResponse *resp)
+e_book_response_get_supported_fields (EBook *book,
+ EBookStatus status,
+ GList *fields)
{
EBookOp *op;
- if (resp->status == E_BOOK_STATUS_SUCCESS) {
- book->priv->corba_book = resp->book;
- book->priv->load_state = URILoaded;
-
- book->priv->comp_listener = e_component_listener_new (book->priv->corba_book);
- book->priv->died_signal = g_signal_connect (book->priv->comp_listener, "component_died",
- G_CALLBACK (backend_died_cb), book);
- }
-
- op = e_book_pop_op (book);
+ op = e_book_get_op (book);
if (op == NULL) {
- g_warning ("e_book_do_response_open: Cannot find operation "
- "in local op queue!\n");
- return;
+ g_warning ("e_book_response_get_supported_fields: Cannot find operation ");
+ return;
}
- if (op->cb)
- ((EBookCallback) op->cb) (book, resp->status, op->closure);
- e_book_op_free (op);
-}
+ e_mutex_lock (op->mutex);
-static void
-e_book_do_progress_event (EBook *book,
- EBookListenerResponse *resp)
-{
- g_signal_emit (book, e_book_signals [OPEN_PROGRESS], 0,
- resp->msg, resp->percent);
+ op->status = status;
+ op->list = fields;
- g_free (resp->msg);
-}
+ pthread_cond_signal (&op->cond);
-static void
-e_book_do_link_event (EBook *book,
- EBookListenerResponse *resp)
-{
- g_signal_emit (book, e_book_signals [LINK_STATUS], 0,
- resp->connected);
+ e_mutex_unlock (op->mutex);
}
-static void
-e_book_do_writable_event (EBook *book,
- EBookListenerResponse *resp)
+
+/**
+ * e_book_get_supported_auth_methods:
+ * @book: an #EBook
+ * @auth_methods: a #GList
+ *
+ * queries @book for the list of authentication methods it supports.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_get_supported_auth_methods (EBook *book,
+ GList **auth_methods,
+ GError **error)
{
- g_signal_emit (book, e_book_signals [WRITABLE_STATUS], 0,
- resp->writable);
-}
+ EBookOp *our_op;
+ EBookStatus status;
+ CORBA_Environment ev;
-static void
-e_book_do_response_get_supported_fields (EBook *book,
- EBookListenerResponse *resp)
-{
- EBookOp *op;
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (auth_methods, E_BOOK_ERROR_INVALID_ARG);
- op = e_book_pop_op (book);
+ e_mutex_lock (book->priv->mutex);
- if (op == NULL) {
- g_warning ("e_book_do_response_get_supported_fields: Cannot find operation "
- "in local op queue!\n");
- return;
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_get_supported_auth_methods on book before e_book_load_uri"));
+ return FALSE;
}
- if (op->cb) {
- if (op->active)
- ((EBookFieldsCallback) op->cb) (book, resp->status, resp->list, op->closure);
- else
- ((EBookFieldsCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
- g_object_unref(resp->list);
+ our_op = e_book_new_op (book);
- e_book_op_free (op);
-}
+ e_mutex_lock (our_op->mutex);
-static void
-e_book_do_response_get_supported_auth_methods (EBook *book,
- EBookListenerResponse *resp)
-{
- EBookOp *op;
+ e_mutex_unlock (book->priv->mutex);
- op = e_book_pop_op (book);
+ CORBA_exception_init (&ev);
- if (op == NULL) {
- g_warning ("e_book_do_response_get_supported_auth_methods: Cannot find operation "
- "in local op queue!\n");
- return;
- }
+ /* will eventually end up calling
+ e_book_response_get_supported_fields */
+ GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods(book->priv->corba_book, &ev);
- if (op->cb) {
- if (op->active)
- ((EBookAuthMethodsCallback) op->cb) (book, resp->status, resp->list, op->closure);
- else
- ((EBookAuthMethodsCallback) op->cb) (book, E_BOOK_STATUS_CANCELLED, NULL, op->closure);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+
+ e_book_clear_op (book, our_op);
+
+ CORBA_exception_free (&ev);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::getSupportedAuthMethods call"));
+ return FALSE;
}
- g_object_unref(resp->list);
- e_book_op_free (op);
+ CORBA_exception_free (&ev);
+
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
+
+ status = our_op->status;
+ *auth_methods = our_op->list;
+
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
-/*
- * Reading notices out of the EBookListener's queue.
- */
static void
-e_book_check_listener_queue (EBookListener *listener, EBook *book)
+e_book_response_get_supported_auth_methods (EBook *book,
+ EBookStatus status,
+ GList *auth_methods)
{
- EBookListenerResponse *resp;
+ EBookOp *op;
- resp = e_book_listener_pop_response (listener);
+ op = e_book_get_op (book);
- if (resp == NULL)
- return;
+ if (op == NULL) {
+ g_warning ("e_book_response_get_supported_auth_methods: Cannot find operation ");
+ return;
+ }
- switch (resp->op) {
- case CreateCardResponse:
- e_book_do_response_create_card (book, resp);
- break;
- case RemoveCardResponse:
- case ModifyCardResponse:
- case AuthenticationResponse:
- e_book_do_response_generic (book, resp);
- break;
- case GetCardResponse:
- e_book_do_response_get_vcard (book, resp);
- break;
- case GetCursorResponse:
- e_book_do_response_get_cursor (book, resp);
- break;
- case GetBookViewResponse:
- e_book_do_response_get_view(book, resp);
- break;
- case GetChangesResponse:
- e_book_do_response_get_changes(book, resp);
- break;
- case OpenBookResponse:
- e_book_do_response_open (book, resp);
- break;
- case GetSupportedFieldsResponse:
- e_book_do_response_get_supported_fields (book, resp);
- break;
- case GetSupportedAuthMethodsResponse:
- e_book_do_response_get_supported_auth_methods (book, resp);
- break;
+ e_mutex_lock (op->mutex);
- case OpenProgressEvent:
- e_book_do_progress_event (book, resp);
- break;
- case LinkStatusEvent:
- e_book_do_link_event (book, resp);
- break;
- case WritableStatusEvent:
- e_book_do_writable_event (book, resp);
- break;
- default:
- g_error ("EBook: Unknown operation %d in listener queue!\n",
- resp->op);
- }
+ op->status = status;
+ op->list = auth_methods;
- g_free (resp);
+ pthread_cond_signal (&op->cond);
+
+ e_mutex_unlock (op->mutex);
}
+
+
/**
- * e_book_load_uri:
- */
+ * e_book_authenticate_user:
+ * @book: an #EBook
+ * @user: a string
+ * @passwd: a string
+ * @auth_method: a string
+ *
+ * authenticates @user with @passwd, using the auth method
+ * @auth_method. @auth_method must be one of the authentication
+ * methods returned using e_book_get_supported_auth_methods.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_authenticate_user (EBook *book,
+ const char *user,
+ const char *passwd,
+ const char *auth_method,
+ GError **error)
+{
+ EBookOp *our_op;
+ EBookStatus status;
+ CORBA_Environment ev;
-typedef struct {
- char *uri;
- EBookCallback open_response;
- gpointer closure;
-} EBookLoadURIData;
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (user, E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (passwd, E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (auth_method, E_BOOK_ERROR_INVALID_ARG);
-static void e_book_load_uri_from_factory (EBook *book,
- GNOME_Evolution_Addressbook_BookFactory factory,
- EBookLoadURIData *load_uri_data);
+ e_mutex_lock (book->priv->mutex);
-static void
-e_book_load_uri_step (EBook *book, EBookStatus status, EBookLoadURIData *data)
-{
- /* iterate to the next possible CardFactory, or fail
- if it's the last one */
- book->priv->iter = book->priv->iter->next;
- if (book->priv->iter) {
- GNOME_Evolution_Addressbook_BookFactory factory = book->priv->iter->data;
- e_book_load_uri_from_factory (book, factory, data);
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_authenticate_user on book before e_book_load_uri"));
+ return FALSE;
}
- else {
- EBookCallback cb = data->open_response;
- gpointer closure = data->closure;
-
- /* reset the load_state to NotLoaded so people can
- attempt another load_uri on the book. */
- book->priv->load_state = URINotLoaded;
- g_free (data);
-
- cb (book, status, closure);
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
-}
-
-static void
-e_book_load_uri_open_cb (EBook *book, EBookStatus status, EBookLoadURIData *data)
-{
- if (status == E_BOOK_STATUS_SUCCESS) {
- EBookCallback cb = data->open_response;
- gpointer closure = data->closure;
- g_free (data);
+ our_op = e_book_new_op (book);
- cb (book, status, closure);
- }
- else {
- e_book_load_uri_step (book, status, data);
- }
-}
+ e_mutex_lock (our_op->mutex);
-static void
-e_book_load_uri_from_factory (EBook *book,
- GNOME_Evolution_Addressbook_BookFactory factory,
- EBookLoadURIData *load_uri_data)
-{
- CORBA_Environment ev;
+ e_mutex_unlock (book->priv->mutex);
CORBA_exception_init (&ev);
- e_book_queue_op (book, e_book_load_uri_open_cb, load_uri_data, NULL);
-
- GNOME_Evolution_Addressbook_BookFactory_openBook (
- factory, book->priv->uri,
- bonobo_object_corba_objref (BONOBO_OBJECT (book->priv->listener)),
- &ev);
+ /* will eventually end up calling
+ e_book_response_generic */
+ GNOME_Evolution_Addressbook_Book_authenticateUser (book->priv->corba_book,
+ user, passwd,
+ auth_method,
+ &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_load_uri: CORBA exception while opening addressbook!\n");
- e_book_unqueue_op (book);
+
+ e_book_clear_op (book, our_op);
+
CORBA_exception_free (&ev);
- e_book_load_uri_step (book, E_BOOK_STATUS_OTHER_ERROR, load_uri_data);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::authenticateUser call"));
+ return FALSE;
}
CORBA_exception_free (&ev);
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
+
+ status = our_op->status;
+
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
+
-static gboolean
-activate_factories_for_uri (EBook *book, const char *uri)
+/**
+ * e_book_get_contact:
+ * @book: an #EBook
+ * @id: a string
+ * @contact: an #EContact
+ *
+ * Fills in @contact with the contents of the vcard in @book
+ * corresponding to @id.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_get_contact (EBook *book,
+ const char *id,
+ EContact **contact,
+ GError **error)
{
+ EBookOp *our_op;
+ EBookStatus status;
CORBA_Environment ev;
- Bonobo_ServerInfoList *info_list = NULL;
- int i;
- char *protocol, *query, *colon;
- gboolean retval = FALSE;
- colon = strchr (uri, ':');
- if (!colon) {
- g_warning ("e_book_load_uri: Unable to determine protocol in the URI\n");
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (contact, E_BOOK_ERROR_INVALID_ARG);
+
+ e_mutex_lock (book->priv->mutex);
+
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_get_contact on book before e_book_load_uri"));
return FALSE;
}
- protocol = g_strndup (uri, colon-uri);
- query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/BookFactory:1.0')"
- " AND addressbook:supported_protocols.has ('%s')", protocol
- );
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
+ }
+
+ our_op = e_book_new_op (book);
+
+ e_mutex_lock (our_op->mutex);
+
+ e_mutex_unlock (book->priv->mutex);
CORBA_exception_init (&ev);
-
- info_list = bonobo_activation_query (query, NULL, &ev);
+
+ /* will eventually end up calling e_book_response_generic */
+ GNOME_Evolution_Addressbook_Book_getContact (book->priv->corba_book,
+ (const GNOME_Evolution_Addressbook_VCard) id, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("Eeek! Cannot perform bonobo-activation query for book factories.");
- CORBA_exception_free (&ev);
- goto shutdown;
- }
- if (info_list->_length == 0) {
- g_warning ("Can't find installed BookFactory that handles protocol '%s'.", protocol);
+ e_book_clear_op (book, our_op);
+
CORBA_exception_free (&ev);
- goto shutdown;
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::getContact call"));
+ return FALSE;
}
CORBA_exception_free (&ev);
- for (i = 0; i < info_list->_length; i ++) {
- const Bonobo_ServerInfo *info;
- GNOME_Evolution_Addressbook_BookFactory factory;
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
- info = info_list->_buffer + i;
+ status = our_op->status;
+ *contact = our_op->contact;
- factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL);
+ e_book_clear_op (book, our_op);
- if (factory == CORBA_OBJECT_NIL)
- g_warning ("e_book_construct: Could not obtain a handle "
- "to the Personal Addressbook Server with IID `%s'\n", info->iid);
- else
- book->priv->book_factories = g_list_append (book->priv->book_factories,
- factory);
- }
+ E_BOOK_CHECK_STATUS (status, error);
+}
- if (!book->priv->book_factories) {
- g_warning ("Couldn't activate any book factories.");
- goto shutdown;
+static void
+e_book_response_get_contact (EBook *book,
+ EBookStatus status,
+ EContact *contact)
+{
+ EBookOp *op;
+
+ printf ("e_book_response_get_contact\n");
+
+ op = e_book_get_op (book);
+
+ if (op == NULL) {
+ g_warning ("e_book_response_get_contact: Cannot find operation ");
+ return;
}
- retval = TRUE;
+ e_mutex_lock (op->mutex);
- shutdown:
- if (info_list)
- CORBA_free (info_list);
- g_free (query);
- g_free (protocol);
+ op->status = status;
+ op->contact = contact;
- return retval;
+ pthread_cond_signal (&op->cond);
+
+ e_mutex_unlock (op->mutex);
}
-void
-e_book_load_uri (EBook *book,
- const char *uri,
- EBookCallback open_response,
- gpointer closure)
+
+/**
+ * e_book_remove_contact:
+ * @book: an #EBook
+ * @id: a string
+ *
+ * Removes the contact with id @id from @book.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_remove_contact (EBook *book,
+ const char *id,
+ GError **error)
{
- EBookLoadURIData *load_uri_data;
- GNOME_Evolution_Addressbook_BookFactory factory;
+ GList *list;
+ gboolean rv;
- g_return_if_fail (book != NULL);
- g_return_if_fail (E_IS_BOOK (book));
- g_return_if_fail (uri != NULL);
- g_return_if_fail (open_response != NULL);
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
- if (book->priv->load_state != URINotLoaded) {
- g_warning ("e_book_load_uri: Attempted to load a URI "
- "on a book which already has a URI loaded!\n");
- open_response (book, E_BOOK_STATUS_OTHER_ERROR, closure); /* XXX need a new status code here */
- return;
- }
+ e_mutex_lock (book->priv->mutex);
- /* try to find a list of factories that can handle the protocol */
- if (!activate_factories_for_uri (book, uri)) {
- open_response (book, E_BOOK_STATUS_PROTOCOL_NOT_SUPPORTED, closure);
- return;
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_remove_contact on book before e_book_load_uri"));
+ return FALSE;
}
-
- g_free (book->priv->uri);
- book->priv->uri = g_strdup (uri);
- /*
- * Create our local BookListener interface.
- */
- book->priv->listener = e_book_listener_new ();
- if (book->priv->listener == NULL) {
- g_warning ("e_book_load_uri: Could not create EBookListener!\n");
- open_response (NULL, E_BOOK_STATUS_OTHER_ERROR, closure); /* XXX need a new status code here */
- return;
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
- book->priv->listener_signal = g_signal_connect (book->priv->listener, "responses_queued",
- G_CALLBACK (e_book_check_listener_queue), book);
+ e_mutex_lock (book->priv->mutex);
- load_uri_data = g_new (EBookLoadURIData, 1);
- load_uri_data->open_response = open_response;
- load_uri_data->closure = closure;
+ list = g_list_append (NULL, (char*)id);
- /* initialize the iterator, and load from the first one*/
- book->priv->iter = book->priv->book_factories;
+ rv = e_book_remove_contacts (book, list, error);
- factory = book->priv->iter->data;
-
- e_book_load_uri_from_factory (book, factory, load_uri_data);
-
- book->priv->load_state = URILoading;
+ return rv;
}
/**
- * e_book_unload_uri:
- */
-void
-e_book_unload_uri (EBook *book)
+ * e_book_remove_contacts:
+ * @book: an #EBook
+ * @ids: an #GList of const char *id's
+ *
+ * Removes the contacts with ids from the list @ids from @book. This is
+ * always more efficient than calling e_book_remove_contact_by_id if you
+ * have more than one id to remove, as some backends can implement it
+ * as a batch request.
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_remove_contacts (EBook *book,
+ GList *ids,
+ GError **error)
{
+ GNOME_Evolution_Addressbook_ContactIdList idlist;
CORBA_Environment ev;
+ GList *iter;
+ int num_ids, i;
+ EBookOp *our_op;
+ EBookStatus status;
- g_return_if_fail (book != NULL);
- g_return_if_fail (E_IS_BOOK (book));
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (ids, E_BOOK_ERROR_INVALID_ARG);
- /*
- * FIXME: Make sure this works if the URI is still being
- * loaded.
- */
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_unload_uri: No URI is loaded!\n");
- return;
- }
+ e_mutex_lock (book->priv->mutex);
- /*
- * Release the remote GNOME_Evolution_Addressbook_Book in the PAS.
- */
- CORBA_exception_init (&ev);
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_remove_contacts on book before e_book_load_uri"));
+ return FALSE;
+ }
- bonobo_object_release_unref (book->priv->corba_book, &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_unload_uri: Exception releasing "
- "remote book interface!\n");
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
- CORBA_exception_free (&ev);
+ our_op = e_book_new_op (book);
- e_book_listener_stop (book->priv->listener);
- bonobo_object_unref (BONOBO_OBJECT (book->priv->listener));
+ e_mutex_lock (our_op->mutex);
- book->priv->listener = NULL;
- book->priv->load_state = URINotLoaded;
-}
+ e_mutex_unlock (book->priv->mutex);
-const char *
-e_book_get_uri (EBook *book)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
-
- return book->priv->uri;
-}
-
-char *
-e_book_get_static_capabilities (EBook *book)
-{
- if (!book->priv->cap_queried) {
- CORBA_Environment ev;
- char *temp;
+ CORBA_exception_init (&ev);
- CORBA_exception_init (&ev);
+ num_ids = g_list_length (ids);
+ idlist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_allocbuf (num_ids);
+ idlist._maximum = num_ids;
+ idlist._length = num_ids;
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_unload_uri: No URI is loaded!\n");
- return g_strdup("");
- }
+ for (iter = ids, i = 0; iter; iter = iter->next)
+ idlist._buffer[i++] = CORBA_string_dup (iter->data);
- temp = GNOME_Evolution_Addressbook_Book_getStaticCapabilities(book->priv->corba_book, &ev);
+ /* will eventually end up calling e_book_response_generic */
+ GNOME_Evolution_Addressbook_Book_removeContacts (book->priv->corba_book, &idlist, &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_static_capabilities: Exception "
- "during get_static_capabilities!\n");
- CORBA_exception_free (&ev);
- return g_strdup("");
- }
+ CORBA_free(idlist._buffer);
- book->priv->cap = g_strdup(temp);
- book->priv->cap_queried = TRUE;
+ if (ev._major != CORBA_NO_EXCEPTION) {
- CORBA_free(temp);
+ e_book_clear_op (book, our_op);
CORBA_exception_free (&ev);
- }
- return g_strdup (book->priv->cap);
-}
-
-gboolean
-e_book_check_static_capability (EBook *book, const char *cap)
-{
- gboolean rv = FALSE;
- char *caps = e_book_get_static_capabilities (book);
- if (!caps)
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::removeContacts call"));
return FALSE;
+ }
+
+ CORBA_exception_free (&ev);
- /* XXX this is an inexact test but it works for our use */
- if (strstr (caps, cap))
- rv = TRUE;
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
- g_free (caps);
+ status = our_op->status;
- return rv;
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
-guint
-e_book_get_supported_fields (EBook *book,
- EBookFieldsCallback cb,
- gpointer closure)
+
+/**
+ * e_book_get_book_view:
+ * @book: an #EBook
+ * @query: an #EBookQuery
+ * @requested_fields a #GList containing the names of fields to return, or NULL for all
+ * @max_results the maximum number of contacts to show (or 0 for all)
+ *
+ * need docs here..
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_get_book_view (EBook *book,
+ EBookQuery *query,
+ GList *requested_fields,
+ int max_results,
+ EBookView **book_view,
+ GError **error)
{
+ GNOME_Evolution_Addressbook_stringlist stringlist;
CORBA_Environment ev;
- guint tag;
+ EBookOp *our_op;
+ EBookStatus status;
+ int num_fields, i;
+ GList *iter;
+ char *query_string;
- CORBA_exception_init (&ev);
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book_view, E_BOOK_ERROR_INVALID_ARG);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_unload_uri: No URI is loaded!\n");
- return 0;
- }
+ e_mutex_lock (book->priv->mutex);
- tag = e_book_queue_op (book, cb, closure, NULL);
-
- GNOME_Evolution_Addressbook_Book_getSupportedFields(book->priv->corba_book, &ev);
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_get_book_view on book before e_book_load_uri"));
+ return FALSE;
+ }
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_supported_fields: Exception "
- "during get_supported_fields!\n");
- CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
- CORBA_exception_free (&ev);
+ our_op = e_book_new_op (book);
- return tag;
-}
+ e_mutex_lock (our_op->mutex);
-guint
-e_book_get_supported_auth_methods (EBook *book,
- EBookAuthMethodsCallback cb,
- gpointer closure)
-{
- CORBA_Environment ev;
- guint tag;
+ e_mutex_unlock (book->priv->mutex);
CORBA_exception_init (&ev);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_unload_uri: No URI is loaded!\n");
- return 0;
- }
+ our_op->listener = e_book_view_listener_new();
- tag = e_book_queue_op (book, cb, closure, NULL);
+ num_fields = g_list_length (requested_fields);
- GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods(book->priv->corba_book, &ev);
+ stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
+ stringlist._maximum = num_fields;
+ stringlist._length = num_fields;
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_supported_auth_methods: Exception "
- "during get_supported_auth_methods!\n");
- CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
+ for (i = 0, iter = requested_fields; iter; iter = iter->next, i ++) {
+ stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data);
}
- CORBA_exception_free (&ev);
+ query_string = e_book_query_to_string (query);
- return tag;
-}
+ /* will eventually end up calling e_book_response_get_book_view */
+ GNOME_Evolution_Addressbook_Book_getBookView (book->priv->corba_book,
+ bonobo_object_corba_objref(BONOBO_OBJECT(our_op->listener)),
+ query_string,
+ &stringlist, max_results, &ev);
-static gboolean
-e_book_construct (EBook *book)
-{
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+ CORBA_free(stringlist._buffer);
+ g_free (query_string);
- book->priv->book_factories = NULL;
+ if (ev._major != CORBA_NO_EXCEPTION) {
- return TRUE;
-}
+ e_book_clear_op (book, our_op);
-/**
- * e_book_new:
- */
-EBook *
-e_book_new (void)
-{
- EBook *book;
+ CORBA_exception_free (&ev);
- book = g_object_new (E_TYPE_BOOK, NULL);
+ g_warning ("corba exception._major = %d\n", ev._major);
- if (! e_book_construct (book)) {
- g_object_unref (book);
- return NULL;
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::getBookView call"));
+ return FALSE;
}
+
+ CORBA_exception_free (&ev);
- return book;
-}
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
-/* User authentication. */
+ status = our_op->status;
+ *book_view = our_op->view;
-void
-e_book_authenticate_user (EBook *book,
- const char *user,
- const char *passwd,
- const char *auth_method,
- EBookCallback cb,
- gpointer closure)
-{
- CORBA_Environment ev;
+ e_book_clear_op (book, our_op);
- g_return_if_fail (book != NULL);
- g_return_if_fail (E_IS_BOOK (book));
+ E_BOOK_CHECK_STATUS (status, error);
+}
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_authenticate_user: No URI loaded!\n");
- return;
- }
+static void
+e_book_response_get_book_view (EBook *book,
+ EBookStatus status,
+ GNOME_Evolution_Addressbook_BookView corba_book_view)
+{
- CORBA_exception_init (&ev);
+ EBookOp *op;
- e_book_queue_op (book, cb, closure, NULL);
+ printf ("e_book_response_get_book_view\n");
- GNOME_Evolution_Addressbook_Book_authenticateUser (book->priv->corba_book,
- user,
- passwd,
- auth_method,
- &ev);
+ op = e_book_get_op (book);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_authenticate_user: Exception authenticating user with the PAS!\n");
- CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return;
+ if (op == NULL) {
+ g_warning ("e_book_response_get_book_view: Cannot find operation ");
+ return;
}
- CORBA_exception_free (&ev);
+ e_mutex_lock (op->mutex);
+
+ op->status = status;
+ op->view = e_book_view_new (corba_book_view, op->listener);
+
+ pthread_cond_signal (&op->cond);
+
+ e_mutex_unlock (op->mutex);
}
-/* Fetching cards */
+
/**
- * e_book_get_card:
- */
-guint
-e_book_get_card (EBook *book,
- const char *id,
- EBookCardCallback cb,
- gpointer closure)
+ * e_book_get_contacts:
+ * @book: an #EBook
+ * @query: an #EBookQuery
+ *
+ * need docs here..
+ *
+ * Return value: a #EBookStatus value.
+ **/
+gboolean
+e_book_get_contacts (EBook *book,
+ EBookQuery *query,
+ GList **contacts,
+ GError **error)
{
CORBA_Environment ev;
- guint tag;
+ EBookOp *our_op;
+ EBookStatus status;
+ char *query_string;
+
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (contacts, E_BOOK_ERROR_INVALID_ARG);
+
+ e_mutex_lock (book->priv->mutex);
- g_return_val_if_fail (book != NULL, 0);
- g_return_val_if_fail (E_IS_BOOK (book), 0);
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_get_contacts on book before e_book_load_uri"));
+ return FALSE;
+ }
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_get_card: No URI loaded!\n");
- return 0;
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
}
+ our_op = e_book_new_op (book);
+
+ e_mutex_lock (our_op->mutex);
+
+ e_mutex_unlock (book->priv->mutex);
+
CORBA_exception_init (&ev);
- tag = e_book_queue_op (book, cb, closure, NULL);
+ query_string = e_book_query_to_string (query);
- GNOME_Evolution_Addressbook_Book_getVCard (book->priv->corba_book, (const GNOME_Evolution_Addressbook_VCard) id, &ev);
+ /* will eventually end up calling e_book_response_get_contacts */
+ GNOME_Evolution_Addressbook_Book_getContactList (book->priv->corba_book, query_string, &ev);
+
+ g_free (query_string);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_card: Exception "
- "getting card!\n");
+
+ e_book_clear_op (book, our_op);
+
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
- }
+ g_warning ("corba exception._major = %d\n", ev._major);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::getContactList call"));
+ return FALSE;
+ }
+
CORBA_exception_free (&ev);
- return tag;
-}
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
-/* Deleting cards. */
+ status = our_op->status;
+ *contacts = our_op->list;
-/**
- * e_book_remove_card:
- */
-gboolean
-e_book_remove_card (EBook *book,
- ECard *card,
- EBookCallback cb,
- gpointer closure)
-{
- const char *id;
+ e_book_clear_op (book, our_op);
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (card != NULL, FALSE);
- g_return_val_if_fail (E_IS_CARD (card), FALSE);
+ E_BOOK_CHECK_STATUS (status, error);
+}
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_remove_card: No URI loaded!\n");
- return FALSE;
- }
+static void
+e_book_response_get_contacts (EBook *book,
+ EBookStatus status,
+ GList *contact_list)
+{
- id = e_card_get_id (card);
- g_assert (id != NULL);
+ EBookOp *op;
- return e_book_remove_card_by_id (book, id, cb, closure);
-}
+ op = e_book_get_op (book);
-/**
- * e_book_remove_card_by_id:
- */
-gboolean
-e_book_remove_card_by_id (EBook *book,
- const char *id,
- EBookCallback cb,
- gpointer closure)
+ if (op == NULL) {
+ g_warning ("e_book_response_get_contacts: Cannot find operation ");
+ return;
+ }
-{
- GList *list = NULL;
- gboolean rv;
+ e_mutex_lock (op->mutex);
- list = g_list_prepend (list, (char*)id);
-
- rv = e_book_remove_cards (book, list, cb, closure);
+ op->status = status;
+ op->list = contact_list;
- g_list_free (list);
+ pthread_cond_signal (&op->cond);
- return rv;
+ e_mutex_unlock (op->mutex);
}
+
gboolean
-e_book_remove_cards (EBook *book,
- GList *ids,
- EBookCallback cb,
- gpointer closure)
+e_book_get_changes (EBook *book,
+ char *changeid,
+ GList **changes,
+ GError **error)
{
- GNOME_Evolution_Addressbook_CardIdList idlist;
CORBA_Environment ev;
- GList *l;
- int num_ids, i;
+ EBookOp *our_op;
+ EBookStatus status;
+
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (changeid, E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (changes, E_BOOK_ERROR_INVALID_ARG);
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (ids != NULL, FALSE);
+ e_mutex_lock (book->priv->mutex);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_remove_card_by_id: No URI loaded!\n");
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_get_changes on book before e_book_load_uri"));
return FALSE;
}
- CORBA_exception_init (&ev);
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
+ }
- e_book_queue_op (book, cb, closure, NULL);
+ our_op = e_book_new_op (book);
- num_ids = g_list_length (ids);
- idlist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_CardId_allocbuf (num_ids);
- idlist._maximum = num_ids;
- idlist._length = num_ids;
+ e_mutex_lock (our_op->mutex);
- for (l = ids, i = 0; l; l=l->next, i ++) {
- idlist._buffer[i] = CORBA_string_dup (l->data);
- }
+ e_mutex_unlock (book->priv->mutex);
- GNOME_Evolution_Addressbook_Book_removeCards (book->priv->corba_book, &idlist, &ev);
+ CORBA_exception_init (&ev);
+
+ /* will eventually end up calling e_book_response_get_changes */
+ GNOME_Evolution_Addressbook_Book_getChanges (book->priv->corba_book, changeid, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_remove_card_by_id: CORBA exception "
- "talking to PAS!\n");
+
+ e_book_clear_op (book, our_op);
+
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
+
+ g_warning ("corba exception._major = %d\n", ev._major);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::getChanges call"));
return FALSE;
}
CORBA_exception_free (&ev);
- CORBA_free(idlist._buffer);
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
- return TRUE;
+ status = our_op->status;
+ *changes = our_op->list;
+
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
+static void
+e_book_response_get_changes (EBook *book,
+ EBookStatus status,
+ GList *change_list)
+{
+
+ EBookOp *op;
-/* Adding cards. */
+ op = e_book_get_op (book);
-/**
- * e_book_add_card:
- */
-gboolean
-e_book_add_card (EBook *book,
- ECard *card,
- EBookIdCallback cb,
- gpointer closure)
+ if (op == NULL) {
+ g_warning ("e_book_response_get_contacts: Cannot find operation ");
+ return;
+ }
-{
- char *vcard;
- gboolean retval;
+ e_mutex_lock (op->mutex);
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (card != NULL, FALSE);
- g_return_val_if_fail (E_IS_CARD (card), FALSE);
+ op->status = status;
+ op->list = change_list;
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_add_card: No URI loaded!\n");
- return FALSE;
+ pthread_cond_signal (&op->cond);
+
+ e_mutex_unlock (op->mutex);
+}
+
+void
+e_book_free_change_list (GList *change_list)
+{
+ GList *l;
+ for (l = change_list; l; l = l->next) {
+ EBookChange *change = l->data;
+
+ g_free (change->vcard);
+ g_free (change);
}
- vcard = e_card_get_vcard_assume_utf8 (card);
+ g_list_free (change_list);
+}
+
+
- if (vcard == NULL) {
- g_warning ("e_book_add_card: Cannot convert card to VCard string!\n");
- return FALSE;
+static void
+e_book_response_generic (EBook *book,
+ EBookStatus status)
+{
+ EBookOp *op;
+
+ op = e_book_get_op (book);
+
+ if (op == NULL) {
+ g_warning ("e_book_response_generic: Cannot find operation ");
+ return;
}
- retval = e_book_add_vcard (book, vcard, cb, closure);
+ e_mutex_lock (op->mutex);
- g_free (vcard);
+ op->status = status;
- e_card_set_book (card, book);
+ pthread_cond_signal (&op->cond);
- return retval;
+ e_mutex_unlock (op->mutex);
}
/**
- * e_book_add_vcard:
- */
+ * e_book_cancel:
+ * @book: an #EBook
+ *
+ * Used to cancel an already running operation on @book. This
+ * function makes a synchronous CORBA to the backend telling it to
+ * cancel the operation. If the operation wasn't cancellable (either
+ * transiently or permanently) or had already comopleted on the wombat
+ * side, this function will return E_BOOK_STATUS_COULD_NOT_CANCEL, and
+ * the operation will continue uncancelled. If the operation could be
+ * cancelled, this function will return E_BOOK_ERROR_OK, and the
+ * blocked e_book function corresponding to current operation will
+ * return with a status of E_BOOK_STATUS_CANCELLED.
+ *
+ * Return value: a #EBookStatus value.
+ **/
gboolean
-e_book_add_vcard (EBook *book,
- const char *vcard,
- EBookIdCallback cb,
- gpointer closure)
+e_book_cancel (EBook *book,
+ GError **error)
{
+ EBookOp *op;
+ EBookStatus status;
+ gboolean rv;
CORBA_Environment ev;
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (vcard != NULL, FALSE);
+ e_mutex_lock (book->priv->mutex);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_add_vcard: No URI loaded!\n");
+ if (book->priv->current_op == NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
+ _("e_book_cancel: there is no current operation"));
return FALSE;
}
- CORBA_exception_init (&ev);
+ op = book->priv->current_op;
+
+ e_mutex_lock (op->mutex);
- e_book_queue_op (book, (EBookCallback) cb, closure, NULL);
+ e_mutex_unlock (book->priv->mutex);
- GNOME_Evolution_Addressbook_Book_addCard (
- book->priv->corba_book, (const GNOME_Evolution_Addressbook_VCard) vcard, &ev);
+ status = GNOME_Evolution_Addressbook_Book_cancelOperation(book->priv->corba_book, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_add_vcard: Exception adding card to PAS!\n");
+
+ e_mutex_unlock (op->mutex);
+
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::cancelOperation call"));
return FALSE;
}
CORBA_exception_free (&ev);
- return TRUE;
-}
-
-/* Modifying cards. */
+ if (status == E_BOOK_ERROR_OK) {
+ op->status = E_BOOK_ERROR_CANCELLED;
-/**
- * e_book_commit_card:
- */
-gboolean
-e_book_commit_card (EBook *book,
- ECard *card,
- EBookCallback cb,
- gpointer closure)
-{
- char *vcard;
- gboolean retval;
-
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (card != NULL, FALSE);
- g_return_val_if_fail (E_IS_CARD (card), FALSE);
+ pthread_cond_signal (&op->cond);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_commit_card: No URI loaded!\n");
- return FALSE;
+ rv = TRUE;
+ }
+ else {
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
+ _("e_book_cancel: couldn't cancel"));
+ rv = FALSE;
}
- vcard = e_card_get_vcard_assume_utf8 (card);
+ e_mutex_unlock (op->mutex);
- if (vcard == NULL) {
- g_warning ("e_book_commit_card: Error "
- "getting VCard for card!\n");
- return FALSE;
+ return rv;
+}
+
+static void
+e_book_response_open (EBook *book,
+ EBookStatus status)
+{
+ EBookOp *op;
+
+ op = e_book_get_op (book);
+
+ if (op == NULL) {
+ g_warning ("e_book_response_open: Cannot find operation ");
+ return;
}
- retval = e_book_commit_vcard (book, vcard, cb, closure);
+ e_mutex_lock (op->mutex);
- g_free (vcard);
+ op->status = status;
- e_card_set_book (card, book);
+ pthread_cond_signal (&op->cond);
- return retval;
+ e_mutex_unlock (op->mutex);
}
-/**
- * e_book_commit_vcard:
- */
+
+
gboolean
-e_book_commit_vcard (EBook *book,
- const char *vcard,
- EBookCallback cb,
- gpointer closure)
+e_book_remove (EBook *book,
+ GError **error)
{
CORBA_Environment ev;
+ EBookOp *our_op;
+ EBookStatus status;
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (vcard != NULL, FALSE);
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_commit_vcard: No URI loaded!\n");
+ e_mutex_lock (book->priv->mutex);
+
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_URI_NOT_LOADED,
+ _("e_book_remove on book before e_book_load_uri"));
return FALSE;
}
- CORBA_exception_init (&ev);
+ if (book->priv->current_op != NULL) {
+ e_mutex_unlock (book->priv->mutex);
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
+ _("book busy"));
+ return FALSE;
+ }
- e_book_queue_op (book, cb, closure, NULL);
+ our_op = e_book_new_op (book);
- GNOME_Evolution_Addressbook_Book_modifyCard (
- book->priv->corba_book, (const GNOME_Evolution_Addressbook_VCard) vcard, &ev);
+ e_mutex_lock (our_op->mutex);
+
+ e_mutex_unlock (book->priv->mutex);
+
+ CORBA_exception_init (&ev);
+
+ /* will eventually end up calling e_book_response_remove */
+ GNOME_Evolution_Addressbook_Book_remove (book->priv->corba_book, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_commit_vcard: Exception "
- "modifying card in PAS!\n");
+
+ e_book_clear_op (book, our_op);
+
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
+
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ _("Corba exception making Book::remove call"));
return FALSE;
}
CORBA_exception_free (&ev);
- return TRUE;
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
+
+ status = our_op->status;
+
+ e_book_clear_op (book, our_op);
+
+ E_BOOK_CHECK_STATUS (status, error);
}
-/**
- * e_book_check_connection:
- */
-gboolean
-e_book_check_connection (EBook *book)
+static void
+e_book_response_remove (EBook *book,
+ EBookStatus status)
{
- CORBA_Environment ev;
+ EBookOp *op;
- g_return_val_if_fail (book != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+ printf ("e_book_response_remove\n");
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_check_connection: No URI loaded!\n");
- return FALSE;
+ op = e_book_get_op (book);
+
+ if (op == NULL) {
+ g_warning ("e_book_response_remove: Cannot find operation ");
+ return;
}
- CORBA_exception_init (&ev);
+ e_mutex_lock (op->mutex);
+
+ op->status = status;
+
+ pthread_cond_signal (&op->cond);
+
+ e_mutex_unlock (op->mutex);
+}
- GNOME_Evolution_Addressbook_Book_checkConnection (book->priv->corba_book, &ev);
+
+static void
+e_book_handle_response (EBookListener *listener, EBookListenerResponse *resp, EBook *book)
+{
+ switch (resp->op) {
+ case CreateContactResponse:
+ e_book_response_add_contact (book, resp->status, resp->id);
+ break;
+ case RemoveContactResponse:
+ case ModifyContactResponse:
+ case AuthenticationResponse:
+ e_book_response_generic (book, resp->status);
+ break;
+ case GetContactResponse: {
+ EContact *contact = e_contact_new_from_vcard (resp->vcard);
+ e_book_response_get_contact (book, resp->status, contact);
+ break;
+ }
+ case GetContactListResponse:
+ e_book_response_get_contacts (book, resp->status, resp->list);
+ break;
+ case GetBookViewResponse:
+ e_book_response_get_book_view(book, resp->status, resp->book_view);
+ break;
+ case GetChangesResponse:
+ e_book_response_get_changes(book, resp->status, resp->list);
+ break;
+ case OpenBookResponse:
+ e_book_response_open (book, resp->status);
+ break;
+ case RemoveBookResponse:
+ e_book_response_remove (book, resp->status);
+ break;
+ case GetSupportedFieldsResponse:
+ e_book_response_get_supported_fields (book, resp->status, resp->list);
+ break;
+ case GetSupportedAuthMethodsResponse:
+ e_book_response_get_supported_auth_methods (book, resp->status, resp->list);
+ break;
+ case WritableStatusEvent:
+ book->priv->writable = resp->writable;
+ g_signal_emit (book, e_book_signals [WRITABLE_STATUS], 0, resp->writable);
+ break;
+ default:
+ g_error ("EBook: Unknown response code %d!\n",
+ resp->op);
+ }
+}
+
+
+
+gboolean
+e_book_unload_uri (EBook *book,
+ GError **error)
+{
+ CORBA_Environment ev;
+
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->load_state != E_BOOK_URI_NOT_LOADED, E_BOOK_ERROR_URI_NOT_LOADED);
+
+ /* Release the remote GNOME_Evolution_Addressbook_Book in the PAS. */
+ CORBA_exception_init (&ev);
+
+ bonobo_object_release_unref (book->priv->corba_book, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_check_connection: Exception "
- "querying the PAS!\n");
- CORBA_exception_free (&ev);
- return FALSE;
+ g_warning ("e_book_unload_uri: Exception releasing "
+ "remote book interface!\n");
}
-
+
CORBA_exception_free (&ev);
+ e_book_listener_stop (book->priv->listener);
+ bonobo_object_unref (BONOBO_OBJECT (book->priv->listener));
+
+ book->priv->listener = NULL;
+ book->priv->load_state = E_BOOK_URI_NOT_LOADED;
+ g_free (book->priv->cap);
+ book->priv->cap = NULL;
+ book->priv->writable = FALSE;
+
return TRUE;
}
-guint
-e_book_get_cursor (EBook *book,
- gchar *query,
- EBookCursorCallback cb,
- gpointer closure)
+
+
+/**
+ * e_book_load_uri:
+ */
+
+static void
+backend_died_cb (EComponentListener *cl, gpointer user_data)
+{
+ EBook *book = user_data;
+
+ book->priv->load_state = E_BOOK_URI_NOT_LOADED;
+ g_signal_emit (book, e_book_signals [BACKEND_DIED], 0);
+}
+
+static GList *
+activate_factories_for_uri (EBook *book, const char *uri)
{
CORBA_Environment ev;
- guint tag;
-
- g_return_val_if_fail (book != NULL, 0);
- g_return_val_if_fail (E_IS_BOOK (book), 0);
+ Bonobo_ServerInfoList *info_list = NULL;
+ int i;
+ char *protocol, *query, *colon;
+ GList *factories = NULL;
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_check_connection: No URI loaded!\n");
- return 0;
+ colon = strchr (uri, ':');
+ if (!colon) {
+ g_warning ("e_book_load_uri: Unable to determine protocol in the URI\n");
+ return FALSE;
}
-
- CORBA_exception_init (&ev);
- tag = e_book_queue_op (book, cb, closure, NULL);
+ protocol = g_strndup (uri, colon-uri);
+ query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/BookFactory:1.0')"
+ " AND addressbook:supported_protocols.has ('%s')", protocol
+ );
+
+ CORBA_exception_init (&ev);
- GNOME_Evolution_Addressbook_Book_getCursor (book->priv->corba_book, query, &ev);
+ info_list = bonobo_activation_query (query, NULL, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_all_cards: Exception "
- "querying list of cards!\n");
+ g_warning ("Eeek! Cannot perform bonobo-activation query for book factories.");
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
+ goto done;
+ return NULL;
}
-
+
+ if (info_list->_length == 0) {
+ g_warning ("Can't find installed BookFactory that handles protocol '%s'.", protocol);
+ CORBA_exception_free (&ev);
+ goto done;
+ }
+
CORBA_exception_free (&ev);
- return tag;
+ for (i = 0; i < info_list->_length; i ++) {
+ const Bonobo_ServerInfo *info;
+ GNOME_Evolution_Addressbook_BookFactory factory;
+
+ info = info_list->_buffer + i;
+
+ factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL);
+
+ if (factory == CORBA_OBJECT_NIL)
+ g_warning ("e_book_construct: Could not obtain a handle "
+ "to the Personal Addressbook Server with IID `%s'\n", info->iid);
+ else
+ factories = g_list_append (factories, factory);
+ }
+
+ done:
+ if (info_list)
+ CORBA_free (info_list);
+ g_free (query);
+ g_free (protocol);
+
+ return factories;
}
-guint
-e_book_get_book_view (EBook *book,
- const gchar *query,
- EBookBookViewCallback cb,
- gpointer closure)
+gboolean
+e_book_load_uri (EBook *book,
+ const char *uri,
+ gboolean only_if_exists,
+ GError **error)
{
- CORBA_Environment ev;
- EBookViewListener *listener;
- guint tag;
-
- g_return_val_if_fail (book != NULL, 0);
- g_return_val_if_fail (E_IS_BOOK (book), 0);
+ GList *factories;
+ GList *l;
+ gboolean rv = FALSE;
+ GNOME_Evolution_Addressbook_Book corba_book = CORBA_OBJECT_NIL;
+
+ e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (uri, E_BOOK_ERROR_INVALID_ARG);
+
+ /* XXX this needs to happen while holding the book's lock i would think... */
+ e_return_error_if_fail (book->priv->load_state == E_BOOK_URI_NOT_LOADED, E_BOOK_ERROR_URI_ALREADY_LOADED);
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_get_book_view: No URI loaded!\n");
- return 0;
+ /* try to find a list of factories that can handle the protocol */
+ if (! (factories = activate_factories_for_uri (book, uri))) {
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
+ _("e_book_load_uri: no factories available for uri `%s'"), uri);
+ return FALSE;
}
- listener = e_book_view_listener_new();
-
- CORBA_exception_init (&ev);
- tag = e_book_queue_op (book, cb, closure, listener);
-
- GNOME_Evolution_Addressbook_Book_getBookView (book->priv->corba_book, bonobo_object_corba_objref(BONOBO_OBJECT(listener)), query, &ev);
+ book->priv->load_state = E_BOOK_URI_LOADING;
+
+ /*
+ * Create our local BookListener interface.
+ */
+ book->priv->listener = e_book_listener_new ();
+ if (book->priv->listener == NULL) {
+ g_warning ("e_book_load_uri: Could not create EBookListener!\n");
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
+ _("e_book_load_uri: Could not create EBookListener"));
+ return FALSE;
+ }
+ book->priv->listener_signal = g_signal_connect (book->priv->listener, "response",
+ G_CALLBACK (e_book_handle_response), book);
+
+ g_free (book->priv->uri);
+ book->priv->uri = g_strdup (uri);
+
+ for (l = factories; l; l = l->next) {
+ GNOME_Evolution_Addressbook_BookFactory factory = l->data;
+ EBookOp *our_op;
+ CORBA_Environment ev;
+ EBookStatus status;
+
+ our_op = e_book_new_op (book);
+
+ e_mutex_lock (our_op->mutex);
+
+ CORBA_exception_init (&ev);
+
+ corba_book = GNOME_Evolution_Addressbook_BookFactory_getBook (factory, book->priv->uri,
+ bonobo_object_corba_objref (BONOBO_OBJECT (book->priv->listener)),
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+
+ e_book_clear_op (book, our_op);
+
+ CORBA_exception_free (&ev);
+ continue;
+ }
+
+ GNOME_Evolution_Addressbook_Book_open (corba_book,
+ only_if_exists,
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ /* kill the listener so the book will die */
+ g_signal_handler_disconnect (book->priv->listener, book->priv->listener_signal);
+ bonobo_object_unref (book->priv->listener);
+ book->priv->listener = NULL;
+
+ e_book_clear_op (book, our_op);
+
+ CORBA_exception_free (&ev);
+ continue;
+ }
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_book_view: Exception "
- "getting book_view!\n");
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
+
+ /* wait for something to happen (both cancellation and a
+ successful response will notity us via our cv */
+ e_mutex_cond_wait (&our_op->cond, our_op->mutex);
+
+ status = our_op->status;
+
+ /* remove the op from the book's hash of operations */
+ e_book_clear_op (book, our_op);
+
+ if (status == E_BOOK_ERROR_CANCELLED
+ || status == E_BOOK_ERROR_OK) {
+ rv = TRUE;
+ break;
+ }
}
-
- CORBA_exception_free (&ev);
- return tag;
+ /* free up the factories */
+ for (l = factories; l; l = l->next)
+ CORBA_Object_release ((CORBA_Object)l->data, NULL);
+
+ if (rv == TRUE) {
+ book->priv->corba_book = corba_book;
+ book->priv->load_state = E_BOOK_URI_LOADED;
+ book->priv->comp_listener = e_component_listener_new (book->priv->corba_book);
+ book->priv->died_signal = g_signal_connect (book->priv->comp_listener, "component_died",
+ G_CALLBACK (backend_died_cb), book);
+ return TRUE;
+ }
+ else {
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
+ _("e_book_load_uri: no factories available for uri `%s'"), uri);
+ return FALSE;
+ }
+
+ return rv;
}
-guint
-e_book_get_completion_view (EBook *book,
- const gchar *query,
- EBookBookViewCallback cb,
- gpointer closure)
+gboolean
+e_book_load_local_addressbook (EBook *book,
+ GError **error)
{
- CORBA_Environment ev;
- EBookViewListener *listener;
- guint tag;
-
- g_return_val_if_fail (book != NULL, 0);
- g_return_val_if_fail (E_IS_BOOK (book), 0);
+ char *filename;
+ char *uri;
+ gboolean rv;
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_get_completion_view: No URI loaded!\n");
- return 0;
- }
+ filename = g_build_filename (g_get_home_dir(),
+ "evolution/local/Contacts",
+ NULL);
+ uri = g_strdup_printf ("file://%s", filename);
- listener = e_book_view_listener_new();
+ g_free (filename);
- CORBA_exception_init (&ev);
-
- tag = e_book_queue_op (book, cb, closure, listener);
+ rv = e_book_load_uri (book, uri, TRUE, error);
- GNOME_Evolution_Addressbook_Book_getCompletionView (book->priv->corba_book,
- bonobo_object_corba_objref(BONOBO_OBJECT(listener)),
- query, &ev);
+ g_free (uri);
+
+ return rv;
+}
+
+const char *
+e_book_get_uri (EBook *book)
+{
+ return book->priv->uri;
+}
+
+const char *
+e_book_get_static_capabilities (EBook *book,
+ GError **error)
+{
+ if (!book->priv->cap_queried) {
+ CORBA_Environment ev;
+ char *temp;
+
+ CORBA_exception_init (&ev);
+
+ if (book->priv->load_state != E_BOOK_URI_LOADED) {
+ g_warning ("e_book_unload_uri: No URI is loaded!\n");
+ return g_strdup("");
+ }
+
+ temp = GNOME_Evolution_Addressbook_Book_getStaticCapabilities(book->priv->corba_book, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("e_book_get_static_capabilities: Exception "
+ "during get_static_capabilities!\n");
+ CORBA_exception_free (&ev);
+ return g_strdup("");
+ }
+
+ book->priv->cap = g_strdup(temp);
+ book->priv->cap_queried = TRUE;
+
+ CORBA_free(temp);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_completion_view: Exception "
- "getting completion_view!\n");
CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
}
-
- CORBA_exception_free (&ev);
- return tag;
+ return book->priv->cap;
}
-guint
-e_book_get_changes (EBook *book,
- gchar *changeid,
- EBookBookViewCallback cb,
- gpointer closure)
+gboolean
+e_book_check_static_capability (EBook *book,
+ const char *cap)
{
- CORBA_Environment ev;
- EBookViewListener *listener;
- guint tag;
-
- g_return_val_if_fail (book != NULL, 0);
- g_return_val_if_fail (E_IS_BOOK (book), 0);
+ const char *caps = e_book_get_static_capabilities (book, NULL);
+
+ /* XXX this is an inexact test but it works for our use */
+ if (caps && strstr (caps, cap))
+ return TRUE;
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_get_changes: No URI loaded!\n");
+ return FALSE;
+}
+
+gboolean
+e_book_is_writable (EBook *book)
+{
+ return book->priv->writable;
+}
+
+
+
+
+gboolean
+e_book_get_self (EContact **contact, EBook **book, GError **error)
+{
+ GError *e = NULL;
+
+ if (!e_book_get_default_addressbook (book, &e)) {
+ g_propagate_error (error, e);
return FALSE;
}
- listener = e_book_view_listener_new();
-
- CORBA_exception_init (&ev);
+#if notyet
+ EBook *b;
+ char *self_uri, *self_uid;
- tag = e_book_queue_op (book, cb, closure, listener);
-
- GNOME_Evolution_Addressbook_Book_getChanges (book->priv->corba_book, bonobo_object_corba_objref(BONOBO_OBJECT(listener)), changeid, &ev);
+ /* XXX get the setting for the self book and self uid from gconf */
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_changes: Exception "
- "getting changes!\n");
- CORBA_exception_free (&ev);
- e_book_unqueue_op (book);
- return 0;
+ b = e_book_new();
+ if (! e_book_load_uri (b, self_uri, TRUE, error)) {
+ g_object_unref (b);
+ return FALSE;
}
-
- CORBA_exception_free (&ev);
- return tag;
-}
+ if (! e_book_get_contact (b, self_uid,
+ contact, error)) {
+ g_object_unref (b);
+ return FALSE;
+ }
-/**
- * e_book_cancel
- */
+ if (book)
+ *book = b;
+ else
+ g_object_unref (b);
+ return TRUE;
+#endif
+}
-void
-e_book_cancel (EBook *book, guint tag)
+gboolean
+e_book_set_self (EBook *book, const char *id, GError **error)
{
- g_return_if_fail (book != NULL);
- g_return_if_fail (E_IS_BOOK (book));
- g_return_if_fail (tag != 0);
-
- /* In an attempt to be useful, we take a bit of extra care in reporting
- errors. This might come in handy someday. */
- if (tag >= book->priv->op_tag)
- g_warning ("Attempt to cancel unassigned operation (%u)", tag);
- else if (! e_book_cancel_op (book, tag))
- g_warning ("Attempt to cancel unknown operation (%u)", tag);
}
-/**
- * e_book_get_name:
- */
-char *
-e_book_get_name (EBook *book)
+
+
+gboolean
+e_book_get_default_addressbook (EBook **book, GError **error)
{
- CORBA_Environment ev;
- char *retval;
- char *name;
+ /* XXX for now just load the local ~/evolution/local/Contacts */
+ char *path, *uri;
+ gboolean rv;
- g_return_val_if_fail (book != NULL, NULL);
- g_return_val_if_fail (E_IS_BOOK (book), NULL);
+ *book = e_book_new ();
- if (book->priv->load_state != URILoaded) {
- g_warning ("e_book_get_name: No URI loaded!\n");
- return NULL;
- }
+ path = g_build_filename (g_get_home_dir (),
+ "evolution/local/Contacts",
+ NULL);
+ uri = g_strdup_printf ("file://%s", path);
+ g_free (path);
- CORBA_exception_init (&ev);
+ rv = e_book_load_uri (*book, uri, FALSE, error);
- name = GNOME_Evolution_Addressbook_Book_getName (book->priv->corba_book, &ev);
+ g_free (uri);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_get_name: Exception getting name from PAS!\n");
- CORBA_exception_free (&ev);
- return NULL;
+ if (!rv) {
+ g_object_unref (*book);
+ *book = NULL;
}
- CORBA_exception_free (&ev);
+ return rv;
+#if notyet
+ EConfigListener *listener = e_config_listener_new ();
+ ESourceList *sources = ...;
+ ESource *default_source;
+
+ default_source = e_source_list_peek_source_by_uid (sources,
+ "default_");
+#endif
+}
- if (name == NULL) {
- g_warning ("e_book_get_name: Got NULL name from PAS!\n");
- return NULL;
+#if notyet
+ESourceList*
+e_book_get_addressbooks (GError **error)
+{
+}
+#endif
+
+
+static void*
+startup_mainloop (void *arg)
+{
+ bonobo_main();
+ return NULL;
+}
+
+/* one-time start up for libebook */
+static void
+e_book_activate()
+{
+ static GStaticMutex e_book_lock = G_STATIC_MUTEX_INIT;
+ static gboolean activated = FALSE;
+
+ g_static_mutex_lock (&e_book_lock);
+ if (!activated) {
+ pthread_t ebook_mainloop_thread;
+ activated = TRUE;
+ pthread_create(&ebook_mainloop_thread, NULL, startup_mainloop, NULL);
}
+ g_static_mutex_unlock (&e_book_lock);
+}
- retval = g_strdup (name);
- CORBA_free (name);
+
- return retval;
+EBook*
+e_book_new (void)
+{
+ e_book_activate ();
+ return g_object_new (E_TYPE_BOOK, NULL);
}
+
static void
e_book_init (EBook *book)
{
book->priv = g_new0 (EBookPrivate, 1);
- book->priv->load_state = URINotLoaded;
- book->priv->op_tag = 1;
+ book->priv->load_state = E_BOOK_URI_NOT_LOADED;
book->priv->uri = NULL;
+ book->priv->mutex = e_mutex_new (E_MUTEX_REC);
}
static void
@@ -1598,8 +1967,8 @@ e_book_dispose (GObject *object)
book->priv->comp_listener = NULL;
}
- if (book->priv->load_state == URILoaded)
- e_book_unload_uri (book);
+ if (book->priv->load_state == E_BOOK_URI_LOADED)
+ e_book_unload_uri (book, NULL);
CORBA_exception_init (&ev);
@@ -1640,16 +2009,6 @@ e_book_class_init (EBookClass *klass)
parent_class = g_type_class_ref (G_TYPE_OBJECT);
- e_book_signals [LINK_STATUS] =
- g_signal_new ("link_status",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookClass, link_status),
- NULL, NULL,
- e_book_marshal_NONE__BOOL,
- G_TYPE_NONE, 1,
- G_TYPE_BOOLEAN);
-
e_book_signals [WRITABLE_STATUS] =
g_signal_new ("writable_status",
G_OBJECT_CLASS_TYPE (object_class),
diff --git a/addressbook/backend/ebook/e-book.h b/addressbook/backend/ebook/e-book.h
index d2c5a7bce4..1d2a4dc2d4 100644
--- a/addressbook/backend/ebook/e-book.h
+++ b/addressbook/backend/ebook/e-book.h
@@ -3,9 +3,9 @@
* The Evolution addressbook client object.
*
* Author:
- * Nat Friedman (nat@ximian.com)
+ * Chris Toshok (toshok@ximian.com)
*
- * Copyright 1999, 2000, Ximian, Inc.
+ * Copyright (C) 1999-2003, Ximian, Inc.
*/
#ifndef __E_BOOK_H__
@@ -14,10 +14,13 @@
#include <glib.h>
#include <glib-object.h>
-#include <ebook/e-card.h>
-#include <ebook/e-card-cursor.h>
+#include <ebook/e-contact.h>
+#include <ebook/e-book-query.h>
#include <ebook/e-book-view.h>
#include <ebook/e-book-types.h>
+#if notyet
+#include <e-util/e-source-list.h>
+#endif
#define E_TYPE_BOOK (e_book_get_type ())
#define E_BOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK, EBook))
@@ -43,127 +46,120 @@ struct _EBookClass {
/*
* Signals.
*/
- void (* open_progress) (EBook *book, const char *msg, short percent);
- void (* link_status) (EBook *book, gboolean connected);
void (* writable_status) (EBook *book, gboolean writable);
void (* backend_died) (EBook *book);
-};
-/* Callbacks for asynchronous functions. */
-typedef void (*EBookCallback) (EBook *book, EBookStatus status, gpointer closure);
-typedef void (*EBookOpenProgressCallback) (EBook *book,
- const char *status_message,
- short percent,
- gpointer closure);
-typedef void (*EBookIdCallback) (EBook *book, EBookStatus status, const char *id, gpointer closure);
-typedef void (*EBookCardCallback) (EBook *book, EBookStatus status, ECard *card, gpointer closure);
-typedef void (*EBookCursorCallback) (EBook *book, EBookStatus status, ECardCursor *cursor, gpointer closure);
-typedef void (*EBookBookViewCallback) (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure);
-typedef void (*EBookFieldsCallback) (EBook *book, EBookStatus status, EList *fields, gpointer closure);
-typedef void (*EBookAuthMethodsCallback) (EBook *book, EBookStatus status, EList *auth_methods, gpointer closure);
+ /* Padding for future expansion */
+ void (*_ebook_reserved0) (void);
+ void (*_ebook_reserved1) (void);
+ void (*_ebook_reserved2) (void);
+ void (*_ebook_reserved3) (void);
+ void (*_ebook_reserved4) (void);
+};
/* Creating a new addressbook. */
-EBook *e_book_new (void);
+EBook *e_book_new (void);
+
+/* loading arbitrary addressbooks */
+gboolean e_book_load_uri (EBook *book,
+ const char *uri,
+ gboolean only_if_exists,
+ GError **error);
-void e_book_load_uri (EBook *book,
- const char *uri,
- EBookCallback open_response,
- gpointer closure);
-void e_book_unload_uri (EBook *book);
+gboolean e_book_unload_uri (EBook *book,
+ GError **error);
-const char *e_book_get_uri (EBook *book);
+gboolean e_book_remove (EBook *book,
+ GError **error);
-char *e_book_get_static_capabilities (EBook *book);
-gboolean e_book_check_static_capability (EBook *book, const char *cap);
+/* convenience function for loading the "local" contact folder */
+gboolean e_book_load_local_addressbook (EBook *book,
+ GError **error);
-guint e_book_get_supported_fields (EBook *book,
- EBookFieldsCallback cb,
- gpointer closure);
+gboolean e_book_get_supported_fields (EBook *book,
+ GList **fields,
+ GError **error);
-guint e_book_get_supported_auth_methods (EBook *book,
- EBookAuthMethodsCallback cb,
- gpointer closure);
+gboolean e_book_get_supported_auth_methods (EBook *book,
+ GList **auth_methods,
+ GError **error);
/* User authentication. */
-void e_book_authenticate_user (EBook *book,
- const char *user,
- const char *passwd,
- const char *auth_method,
- EBookCallback cb,
- gpointer closure);
-
-/* Fetching cards. */
-guint e_book_get_card (EBook *book,
- const char *id,
- EBookCardCallback cb,
- gpointer closure);
-
-/* Deleting cards. */
-gboolean e_book_remove_card (EBook *book,
- ECard *card,
- EBookCallback cb,
- gpointer closure);
-gboolean e_book_remove_card_by_id (EBook *book,
- const char *id,
- EBookCallback cb,
- gpointer closure);
-
-gboolean e_book_remove_cards (EBook *book,
- GList *id_list,
- EBookCallback cb,
- gpointer closure);
-
-/* Adding cards. */
-gboolean e_book_add_card (EBook *book,
- ECard *card,
- EBookIdCallback cb,
- gpointer closure);
-gboolean e_book_add_vcard (EBook *book,
- const char *vcard,
- EBookIdCallback cb,
- gpointer closure);
-
-/* Modifying cards. */
-gboolean e_book_commit_card (EBook *book,
- ECard *card,
- EBookCallback cb,
- gpointer closure);
-gboolean e_book_commit_vcard (EBook *book,
- const char *vcard,
- EBookCallback cb,
- gpointer closure);
-
-/* Checking to see if we're connected to the card repository. */
-gboolean e_book_check_connection (EBook *book);
-guint e_book_get_cursor (EBook *book,
- char *query,
- EBookCursorCallback cb,
- gpointer closure);
-
-guint e_book_get_book_view (EBook *book,
- const gchar *query,
- EBookBookViewCallback cb,
- gpointer closure);
-
-guint e_book_get_completion_view (EBook *book,
- const gchar *query,
- EBookBookViewCallback cb,
- gpointer closure);
-
-guint e_book_get_changes (EBook *book,
- char *changeid,
- EBookBookViewCallback cb,
- gpointer closure);
+gboolean e_book_authenticate_user (EBook *book,
+ const char *user,
+ const char *passwd,
+ const char *auth_method,
+ GError **error);
+
+/* Fetching contacts. */
+gboolean e_book_get_contact (EBook *book,
+ const char *id,
+ EContact **contact,
+ GError **error);
+
+/* Deleting contacts. */
+gboolean e_book_remove_contact (EBook *book,
+ const char *id,
+ GError **error);
+
+gboolean e_book_remove_contacts (EBook *book,
+ GList *id_list,
+ GError **error);
+
+/* Adding contacts. */
+gboolean e_book_add_contact (EBook *book,
+ EContact *contact,
+ GError **error);
+
+/* Modifying contacts. */
+gboolean e_book_commit_contact (EBook *book,
+ EContact *contact,
+ GError **error);
+
+/* Returns a live view of a query. */
+gboolean e_book_get_book_view (EBook *book,
+ EBookQuery *query,
+ GList *requested_fields,
+ int max_results,
+ EBookView **book_view,
+ GError **error);
+
+/* Returns a static snapshot of a query. */
+gboolean e_book_get_contacts (EBook *book,
+ EBookQuery *query,
+ GList **contacts,
+ GError **error);
+
+gboolean e_book_get_changes (EBook *book,
+ char *changeid,
+ GList **changes,
+ GError **error);
+
+void e_book_free_change_list (GList *change_list);
+
+const char *e_book_get_uri (EBook *book);
+
+const char *e_book_get_static_capabilities (EBook *book,
+ GError **error);
+gboolean e_book_check_static_capability (EBook *book,
+ const char *cap);
+gboolean e_book_is_writable (EBook *book);
/* Cancel a pending operation. */
-void e_book_cancel (EBook *book,
- guint tag);
+gboolean e_book_cancel (EBook *book,
+ GError **error);
+/* Identity */
+gboolean e_book_get_self (EContact **contact, EBook **book, GError **error);
+gboolean e_book_set_self (EBook *book, const char *id, GError **error);
-/* Getting the name of the repository. */
-char *e_book_get_name (EBook *book);
+/* Addressbook Discovery */
+gboolean e_book_get_default_addressbook (EBook **book, GError **error);
+#if notyet
+gboolean e_book_get_addressbooks (ESourceList** addressbook_sources, GError **error);
+#endif
-GType e_book_get_type (void);
+GType e_book_get_type (void);
G_END_DECLS
diff --git a/addressbook/backend/ebook/e-card-compare.c b/addressbook/backend/ebook/e-card-compare.c
deleted file mode 100644
index 2413d987e5..0000000000
--- a/addressbook/backend/ebook/e-card-compare.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-card-compare.c
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Developed by Jon Trowbridge <trow@ximian.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA.
- */
-
-#include <config.h>
-#include <ctype.h>
-#include <string.h>
-#include "e-book-util.h"
-#include "e-card-compare.h"
-
-/* This is an "optimistic" combiner: the best of the two outcomes is
- selected. */
-static ECardMatchType
-combine_comparisons (ECardMatchType prev,
- ECardMatchType new_info)
-{
- if (new_info == E_CARD_MATCH_NOT_APPLICABLE)
- return prev;
- return (ECardMatchType) MAX ((gint) prev, (gint) new_info);
-}
-
-
-/*** Name comparisons ***/
-
-/* This *so* doesn't belong here... at least not implemented in a
- sucky way like this. But it can be fixed later. */
-
-/* This is very Anglocentric. */
-static gchar *name_synonyms[][2] = {
- { "jon", "john" }, /* Ah, the hacker's perogative */
- { "joseph", "joe" },
- { "robert", "bob" },
- { "gene", "jean" },
- { "jesse", "jessie" },
- { "ian", "iain" },
- { "richard", "dick" },
- { "william", "bill" },
- { "william", "will" },
- { "anthony", "tony" },
- { "michael", "mike" },
- { "eric", "erik" },
- { "elizabeth", "liz" },
- { "jeff", "geoff" },
- { "jeff", "geoffrey" },
- { "tom", "thomas" },
- { "dave", "david" },
- { "jim", "james" },
- { "abigal", "abby" },
- { "amanda", "amy" },
- { "amanda", "manda" },
- { "jennifer", "jenny" },
- { "christopher", "chris" },
- { "rebecca", "becca" },
- { "rebecca", "becky" },
- { "anderson", "andersen" },
- { "johnson", "johnsen" },
- /* We could go on and on... */
- /* We should add soundex here. */
- { NULL, NULL }
-};
-
-static gboolean
-name_fragment_match (const gchar *a, const gchar *b, gboolean strict)
-{
- gint len;
-
- if (!(a && b && *a && *b))
- return FALSE;
-
- /* If we are in 'strict' mode, b must match the beginning of a.
- So "Robert", "Rob" would match, but "Robert", "Robbie" wouldn't.
-
- If strict is FALSE, it is sufficient for the strings to share
- some leading characters. In this case, "Robert" and "Robbie"
- would match, as would "Dave" and "Dan". */
-
- if (strict) {
- len = g_utf8_strlen (b, -1);
- } else {
- len = MIN (g_utf8_strlen (a, -1), g_utf8_strlen (b, -1));
- }
-
- return !e_utf8_casefold_collate_len (a, b, len);
-}
-
-static gboolean
-name_fragment_match_with_synonyms (const gchar *a, const gchar *b, gboolean strict)
-{
- gint i;
-
- if (!(a && b && *a && *b))
- return FALSE;
-
- if (name_fragment_match (a, b, strict))
- return TRUE;
-
- /* Check for nicknames. Yes, the linear search blows. */
- for (i=0; name_synonyms[i][0]; ++i) {
-
- if (!e_utf8_casefold_collate (name_synonyms[i][0], a)
- && !e_utf8_casefold_collate (name_synonyms[i][1], b))
- return TRUE;
-
- if (!e_utf8_casefold_collate (name_synonyms[i][0], b)
- && !e_utf8_casefold_collate (name_synonyms[i][1], a))
- return TRUE;
- }
-
- return FALSE;
-}
-
-ECardMatchType
-e_card_compare_name_to_string (ECard *card, const gchar *str)
-{
- return e_card_compare_name_to_string_full (card, str, FALSE, NULL, NULL, NULL);
-}
-
-ECardMatchType
-e_card_compare_name_to_string_full (ECard *card, const gchar *str, gboolean allow_partial_matches,
- gint *matched_parts_out, ECardMatchPart *first_matched_part_out, gint *matched_character_count_out)
-{
- gchar **namev, **givenv = NULL, **addv = NULL, **familyv = NULL;
-
- gint matched_parts = E_CARD_MATCH_PART_NONE;
- ECardMatchPart first_matched_part = E_CARD_MATCH_PART_NONE;
- ECardMatchPart this_part_match = E_CARD_MATCH_PART_NOT_APPLICABLE;
- ECardMatchType match_type;
-
- gint match_count = 0, matched_character_count = 0, fragment_count;
- gint i, j;
- gchar *str_cpy, *s;
-
- g_return_val_if_fail (E_IS_CARD (card), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (card->name != NULL, E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (str != NULL, E_CARD_MATCH_NOT_APPLICABLE);
-
- str_cpy = s = g_strdup (str);
- while (*s) {
- if (*s == ',' || *s == '"')
- *s = ' ';
- ++s;
- }
- namev = g_strsplit (str_cpy, " ", 0);
- g_free (str_cpy);
-
- if (card->name->given)
- givenv = g_strsplit (card->name->given, " ", 0);
- if (card->name->additional)
- addv = g_strsplit (card->name->additional, " ", 0);
- if (card->name->family)
- familyv = g_strsplit (card->name->family, " ", 0);
-
- fragment_count = 0;
- for (i = 0; givenv && givenv[i]; ++i)
- ++fragment_count;
- for (i = 0; addv && addv[i]; ++i)
- ++fragment_count;
- for (i = 0; familyv && familyv[i]; ++i)
- ++fragment_count;
-
- for (i = 0; namev[i] && this_part_match != E_CARD_MATCH_PART_NONE; ++i) {
-
- if (*namev[i]) {
-
- this_part_match = E_CARD_MATCH_PART_NONE;
-
- /* When we are allowing partials, we are strict about the matches we allow.
- Does this make sense? Not really, but it does the right thing for the purposes
- of completion. */
-
- if (givenv && this_part_match == E_CARD_MATCH_PART_NONE) {
- for (j = 0; givenv[j]; ++j) {
- if (name_fragment_match_with_synonyms (givenv[j], namev[i], allow_partial_matches)) {
-
- this_part_match = E_CARD_MATCH_PART_GIVEN_NAME;
-
- /* We remove a piece of a name once it has been matched against, so
- that "john john" won't match "john doe". */
- g_free (givenv[j]);
- givenv[j] = g_strdup ("");
- break;
- }
- }
- }
-
- if (addv && this_part_match == E_CARD_MATCH_PART_NONE) {
- for (j = 0; addv[j]; ++j) {
- if (name_fragment_match_with_synonyms (addv[j], namev[i], allow_partial_matches)) {
-
- this_part_match = E_CARD_MATCH_PART_ADDITIONAL_NAME;
-
- g_free (addv[j]);
- addv[j] = g_strdup ("");
- break;
- }
- }
- }
-
- if (familyv && this_part_match == E_CARD_MATCH_PART_NONE) {
- for (j = 0; familyv[j]; ++j) {
- if (allow_partial_matches ? name_fragment_match_with_synonyms (familyv[j], namev[i], allow_partial_matches)
- : !e_utf8_casefold_collate (familyv[j], namev[i])) {
-
- this_part_match = E_CARD_MATCH_PART_FAMILY_NAME;
-
- g_free (familyv[j]);
- familyv[j] = g_strdup ("");
- break;
- }
- }
- }
-
- if (this_part_match != E_CARD_MATCH_PART_NONE) {
- ++match_count;
- matched_character_count += g_utf8_strlen (namev[i], -1);
- matched_parts |= this_part_match;
- if (first_matched_part == E_CARD_MATCH_PART_NONE)
- first_matched_part = this_part_match;
- }
- }
- }
-
- match_type = E_CARD_MATCH_NONE;
-
- if (this_part_match != E_CARD_MATCH_PART_NONE) {
-
- if (match_count > 0)
- match_type = E_CARD_MATCH_VAGUE;
-
- if (fragment_count == match_count) {
-
- match_type = E_CARD_MATCH_EXACT;
-
- } else if (fragment_count == match_count + 1) {
-
- match_type = E_CARD_MATCH_PARTIAL;
-
- }
- }
-
- if (matched_parts_out)
- *matched_parts_out = matched_parts;
- if (first_matched_part_out)
- *first_matched_part_out = first_matched_part;
- if (matched_character_count_out)
- *matched_character_count_out = matched_character_count;
-
- g_strfreev (namev);
- g_strfreev (givenv);
- g_strfreev (addv);
- g_strfreev (familyv);
-
- return match_type;
-}
-
-ECardMatchType
-e_card_compare_name (ECard *card1, ECard *card2)
-{
- ECardName *a, *b;
- gint matches=0, possible=0;
- gboolean given_match = FALSE, additional_match = FALSE, family_match = FALSE;
-
- g_return_val_if_fail (E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
-
- a = card1->name;
- b = card2->name;
-
- if (a == NULL || b == NULL)
- return E_CARD_MATCH_NOT_APPLICABLE;
-
- if (a->given && b->given) {
- ++possible;
- if (name_fragment_match_with_synonyms (a->given, b->given, FALSE /* both inputs are complete */)) {
- ++matches;
- given_match = TRUE;
- }
- }
-
- if (a->additional && b->additional) {
- ++possible;
- if (name_fragment_match_with_synonyms (a->additional, b->additional, FALSE /* both inputs are complete */)) {
- ++matches;
- additional_match = TRUE;
- }
- }
-
- if (a->family && b->family) {
- ++possible;
- /* We don't allow "loose matching" (i.e. John vs. Jon) on family names */
- if (! e_utf8_casefold_collate (a->family, b->family)) {
- ++matches;
- family_match = TRUE;
- }
- }
-
- /* Now look at the # of matches and try to intelligently map
- an E_CARD_MATCH_* type to it. Special consideration is given
- to family-name matches. */
-
- if (possible == 0)
- return E_CARD_MATCH_NOT_APPLICABLE;
-
- if (possible == 1)
- return family_match ? E_CARD_MATCH_VAGUE : E_CARD_MATCH_NONE;
-
- if (possible == matches)
- return family_match ? E_CARD_MATCH_EXACT : E_CARD_MATCH_PARTIAL;
-
- if (possible == matches+1)
- return family_match ? E_CARD_MATCH_VAGUE : E_CARD_MATCH_NONE;
-
- return E_CARD_MATCH_NONE;
-}
-
-
-/*** Nickname Comparisons ***/
-
-ECardMatchType
-e_card_compare_nickname (ECard *card1, ECard *card2)
-{
- g_return_val_if_fail (card1 && E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (card2 && E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
-
- return E_CARD_MATCH_NOT_APPLICABLE;
-}
-
-
-
-/*** E-mail Comparisons ***/
-
-static gboolean
-match_email_username (const gchar *addr1, const gchar *addr2)
-{
- gint c1, c2;
- if (addr1 == NULL || addr2 == NULL)
- return FALSE;
-
- while (*addr1 && *addr2 && *addr1 != '@' && *addr2 != '@') {
- c1 = isupper (*addr1) ? tolower (*addr1) : *addr1;
- c2 = isupper (*addr2) ? tolower (*addr2) : *addr2;
- if (c1 != c2)
- return FALSE;
- ++addr1;
- ++addr2;
- }
-
- return *addr1 == *addr2;
-}
-
-static gboolean
-match_email_hostname (const gchar *addr1, const gchar *addr2)
-{
- gint c1, c2;
- gboolean seen_at1, seen_at2;
- if (addr1 == NULL || addr2 == NULL)
- return FALSE;
-
- /* Walk to the end of each string. */
- seen_at1 = FALSE;
- if (*addr1) {
- while (*addr1) {
- if (*addr1 == '@')
- seen_at1 = TRUE;
- ++addr1;
- }
- --addr1;
- }
-
- seen_at2 = FALSE;
- if (*addr2) {
- while (*addr2) {
- if (*addr2 == '@')
- seen_at2 = TRUE;
- ++addr2;
- }
- --addr2;
- }
-
- if (!seen_at1 && !seen_at2)
- return TRUE;
- if (!seen_at1 || !seen_at2)
- return FALSE;
-
- while (*addr1 != '@' && *addr2 != '@') {
- c1 = isupper (*addr1) ? tolower (*addr1) : *addr1;
- c2 = isupper (*addr2) ? tolower (*addr2) : *addr2;
- if (c1 != c2)
- return FALSE;
- --addr1;
- --addr2;
- }
-
- /* This will match bob@foo.ximian.com and bob@ximian.com */
- return *addr1 == '.' || *addr2 == '.';
-}
-
-static ECardMatchType
-compare_email_addresses (const gchar *addr1, const gchar *addr2)
-{
- if (addr1 == NULL || *addr1 == 0 ||
- addr2 == NULL || *addr2 == 0)
- return E_CARD_MATCH_NOT_APPLICABLE;
-
- if (match_email_username (addr1, addr2))
- return match_email_hostname (addr1, addr2) ? E_CARD_MATCH_EXACT : E_CARD_MATCH_VAGUE;
-
- return E_CARD_MATCH_NONE;
-}
-
-ECardMatchType
-e_card_compare_email (ECard *card1, ECard *card2)
-{
- EIterator *i1, *i2;
- ECardMatchType match = E_CARD_MATCH_NOT_APPLICABLE;
-
- g_return_val_if_fail (card1 && E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (card2 && E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
-
- if (card1->email == NULL || card2->email == NULL)
- return E_CARD_MATCH_NOT_APPLICABLE;
-
- i1 = e_list_get_iterator (card1->email);
- i2 = e_list_get_iterator (card2->email);
-
- /* Do pairwise-comparisons on all of the e-mail addresses. If
- we find an exact match, there is no reason to keep
- checking. */
- e_iterator_reset (i1);
- while (e_iterator_is_valid (i1) && match != E_CARD_MATCH_EXACT) {
- const gchar *addr1 = (const gchar *) e_iterator_get (i1);
-
- e_iterator_reset (i2);
- while (e_iterator_is_valid (i2) && match != E_CARD_MATCH_EXACT) {
- const gchar *addr2 = (const gchar *) e_iterator_get (i2);
-
- match = combine_comparisons (match, compare_email_addresses (addr1, addr2));
-
- e_iterator_next (i2);
- }
-
- e_iterator_next (i1);
- }
-
- g_object_unref (i1);
- g_object_unref (i2);
-
- return match;
-}
-
-ECardMatchType
-e_card_compare_address (ECard *card1, ECard *card2)
-{
- g_return_val_if_fail (card1 && E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (card2 && E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
-
- /* Unimplemented */
-
- return E_CARD_MATCH_NOT_APPLICABLE;
-}
-
-ECardMatchType
-e_card_compare_telephone (ECard *card1, ECard *card2)
-{
- g_return_val_if_fail (card1 && E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (card2 && E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
-
- /* Unimplemented */
-
- return E_CARD_MATCH_NOT_APPLICABLE;
-}
-
-ECardMatchType
-e_card_compare (ECard *card1, ECard *card2)
-{
- ECardMatchType result;
-
- g_return_val_if_fail (card1 && E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
- g_return_val_if_fail (card2 && E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
-
- result = E_CARD_MATCH_NONE;
- result = combine_comparisons (result, e_card_compare_name (card1, card2));
- result = combine_comparisons (result, e_card_compare_nickname (card1, card2));
- result = combine_comparisons (result, e_card_compare_email (card1, card2));
- result = combine_comparisons (result, e_card_compare_address (card1, card2));
- result = combine_comparisons (result, e_card_compare_telephone (card1, card2));
-
- return result;
-}
-
-typedef struct _MatchSearchInfo MatchSearchInfo;
-struct _MatchSearchInfo {
- ECard *card;
- GList *avoid;
- ECardMatchQueryCallback cb;
- gpointer closure;
-};
-
-static void
-match_search_info_free (MatchSearchInfo *info)
-{
- if (info) {
- g_object_unref (info->card);
-
- /* This should already have been deallocated, but just in case... */
- if (info->avoid) {
- g_list_foreach (info->avoid, (GFunc) g_object_unref, NULL);
- g_list_free (info->avoid);
- info->avoid = NULL;
- }
-
- g_free (info);
- }
-}
-
-static void
-simple_query_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
-{
- MatchSearchInfo *info = (MatchSearchInfo *) closure;
- ECardMatchType best_match = E_CARD_MATCH_NONE;
- ECard *best_card = NULL;
- GList *remaining_cards = NULL;
- const GList *i;
-
- if (status != E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS) {
- info->cb (info->card, NULL, E_CARD_MATCH_NONE, info->closure);
- match_search_info_free (info);
- return;
- }
-
- /* remove the cards we're to avoid from the list, if they're present */
- for (i = cards; i != NULL; i = g_list_next (i)) {
- ECard *this_card = E_CARD (i->data);
- GList *iterator;
- gboolean avoid = FALSE;
- for (iterator = info->avoid; iterator; iterator = iterator->next) {
- if (!strcmp (e_card_get_id (iterator->data), e_card_get_id (this_card))) {
- avoid = TRUE;
- break;
- }
- }
- if (!avoid)
- remaining_cards = g_list_prepend (remaining_cards, this_card);
- }
-
- remaining_cards = g_list_reverse (remaining_cards);
-
- for (i = remaining_cards; i != NULL; i = g_list_next (i)) {
- ECard *this_card = E_CARD (i->data);
- ECardMatchType this_match = e_card_compare (info->card, this_card);
- if ((gint)this_match > (gint)best_match) {
- best_match = this_match;
- best_card = this_card;
- }
- }
-
- g_list_free (remaining_cards);
-
- info->cb (info->card, best_card, best_match, info->closure);
- match_search_info_free (info);
-}
-
-#define MAX_QUERY_PARTS 10
-static void
-use_common_book_cb (EBook *book, gpointer closure)
-{
- MatchSearchInfo *info = (MatchSearchInfo *) closure;
- ECard *card = info->card;
- gchar *query_parts[MAX_QUERY_PARTS];
- gint p=0;
- gchar *query, *qj;
- int i;
-
- if (book == NULL) {
- info->cb (info->card, NULL, E_CARD_MATCH_NONE, info->closure);
- match_search_info_free (info);
- return;
- }
-
-#if 0
- if (card->nickname && *card->nickname)
- query_parts[p++] = g_strdup_printf ("(beginswith \"nickname\" \"%s\")", card->nickname);
-#endif
-
- if (card->name->given && strlen (card->name->given) > 1)
- query_parts[p++] = g_strdup_printf ("(contains \"full_name\" \"%s\")", card->name->given);
-
- if (card->name->additional && strlen (card->name->additional) > 1)
- query_parts[p++] = g_strdup_printf ("(contains \"full_name\" \"%s\")", card->name->additional);
-
- if (card->name->family && strlen (card->name->family) > 1)
- query_parts[p++] = g_strdup_printf ("(contains \"full_name\" \"%s\")", card->name->family);
-
-
- if (card->email) {
- EIterator *iter = e_list_get_iterator (card->email);
- while (e_iterator_is_valid (iter) && p < MAX_QUERY_PARTS) {
- gchar *addr = g_strdup (e_iterator_get (iter));
- if (addr && *addr) {
- gchar *s = addr;
- while (*s) {
- if (*s == '@') {
- *s = '\0';
- break;
- }
- ++s;
- }
- query_parts[p++] = g_strdup_printf ("(beginswith \"email\" \"%s\")", addr);
- g_free (addr);
- }
- e_iterator_next (iter);
- }
- }
-
-
-
- /* Build up our full query from the parts. */
- query_parts[p] = NULL;
- qj = g_strjoinv (" ", query_parts);
- for(i = 0; query_parts[i] != NULL; i++)
- g_free(query_parts[i]);
- if (p > 0) {
- query = g_strdup_printf ("(or %s)", qj);
- g_free (qj);
- } else {
- query = qj;
- }
-
- e_book_simple_query (book, query, simple_query_cb, info);
-
- g_free (query);
-}
-
-void
-e_card_locate_match (ECard *card, ECardMatchQueryCallback cb, gpointer closure)
-{
- MatchSearchInfo *info;
-
- g_return_if_fail (card && E_IS_CARD (card));
- g_return_if_fail (cb != NULL);
-
- info = g_new (MatchSearchInfo, 1);
- info->card = card;
- g_object_ref (card);
- info->cb = cb;
- info->closure = closure;
- info->avoid = NULL;
-
- e_book_use_default_book (use_common_book_cb, info);
-}
-
-/**
- * e_card_locate_match_full:
- * @book: The book to look in. If this is NULL, use the default
- * addressbook.
- * @card: The card to compare to.
- * @avoid: A list of cards to not match. These will not show up in the search.
- * @cb: The function to call.
- * @closure: The closure to add to the call.
- *
- * Look for the best match and return it using the ECardMatchQueryCallback.
- **/
-void
-e_card_locate_match_full (EBook *book, ECard *card, GList *avoid, ECardMatchQueryCallback cb, gpointer closure)
-{
- MatchSearchInfo *info;
-
- g_return_if_fail (card && E_IS_CARD (card));
- g_return_if_fail (cb != NULL);
-
- info = g_new (MatchSearchInfo, 1);
- info->card = card;
- g_object_ref (card);
- info->cb = cb;
- info->closure = closure;
- info->avoid = g_list_copy (avoid);
- g_list_foreach (info->avoid, (GFunc) g_object_ref, NULL);
-
- if (book)
- use_common_book_cb (book, info);
- else
- e_book_use_default_book (use_common_book_cb, info);
-}
-
diff --git a/addressbook/backend/ebook/e-card-compare.h b/addressbook/backend/ebook/e-card-compare.h
deleted file mode 100644
index 07ccb54e89..0000000000
--- a/addressbook/backend/ebook/e-card-compare.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-card-compare.h
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Developed by Jon Trowbridge <trow@ximian.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA.
- */
-
-#ifndef __E_CARD_COMPARE_H__
-#define __E_CARD_COMPARE_H__
-
-#include "e-book.h"
-#include "e-card.h"
-
-typedef enum {
- E_CARD_MATCH_NOT_APPLICABLE = 0,
- E_CARD_MATCH_NONE = 1,
- E_CARD_MATCH_VAGUE = 2,
- E_CARD_MATCH_PARTIAL = 3,
- E_CARD_MATCH_EXACT = 4
-} ECardMatchType;
-
-typedef enum {
- E_CARD_MATCH_PART_NOT_APPLICABLE = -1,
- E_CARD_MATCH_PART_NONE = 0,
- E_CARD_MATCH_PART_GIVEN_NAME = 1<<0,
- E_CARD_MATCH_PART_ADDITIONAL_NAME = 1<<2,
- E_CARD_MATCH_PART_FAMILY_NAME = 1<<3
-} ECardMatchPart;
-
-typedef void (*ECardMatchQueryCallback) (ECard *card, ECard *match, ECardMatchType type, gpointer closure);
-
-ECardMatchType e_card_compare_name_to_string (ECard *card, const gchar *str);
-
-ECardMatchType e_card_compare_name_to_string_full (ECard *card, const gchar *str,
- gboolean allow_partial_matches,
- gint *matched_parts, ECardMatchPart *first_matched_part,
- gint *matched_character_count);
-
-ECardMatchType e_card_compare_name (ECard *card1, ECard *card2);
-ECardMatchType e_card_compare_nickname (ECard *card1, ECard *card2);
-ECardMatchType e_card_compare_email (ECard *card1, ECard *card2);
-ECardMatchType e_card_compare_address (ECard *card1, ECard *card2);
-ECardMatchType e_card_compare_telephone (ECard *card1, ECard *card2);
-
-ECardMatchType e_card_compare (ECard *card1, ECard *card2);
-
-void e_card_locate_match (ECard *card, ECardMatchQueryCallback cb, gpointer closure);
-void e_card_locate_match_full (EBook *book, ECard *card, GList *avoid, ECardMatchQueryCallback cb, gpointer closure);
-
-
-
-#endif /* __E_CARD_COMPARE_H__ */
-
diff --git a/addressbook/backend/ebook/e-card-cursor.c b/addressbook/backend/ebook/e-card-cursor.c
deleted file mode 100644
index 0aa9c8c1e0..0000000000
--- a/addressbook/backend/ebook/e-card-cursor.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * e-card-cursor.c: Implements card cursors.
- *
- * Author:
- * Christopher James Lahey <clahey@ximian.com.
- */
-
-#include <config.h>
-#include "addressbook.h"
-#include "e-card-cursor.h"
-
-struct _ECardCursorPrivate {
- GNOME_Evolution_Addressbook_CardCursor corba_cursor;
-};
-
-/*
- * A pointer to our parent object class
- */
-static GObjectClass *parent_class;
-
-/*
- * Implemented GObject::dispose
- */
-static void
-e_card_cursor_dispose (GObject *object)
-{
- ECardCursor *cursor = E_CARD_CURSOR (object);
-
- if (cursor->priv) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_CardCursor_unref( cursor->priv->corba_cursor, &ev );
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning("e_card_cursor_destroy: Exception unreffing "
- "corba cursor.\n");
- CORBA_exception_free (&ev);
- CORBA_exception_init (&ev);
- }
-
- CORBA_Object_release (cursor->priv->corba_cursor, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning("e_card_cursor_destroy: Exception releasing "
- "corba cursor.\n");
- }
-
- CORBA_exception_free (&ev);
-
- g_free ( cursor->priv );
- cursor->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-/**
- * e_card_cursor_get_length:
- * @cursor: the #ECardCursor whose length is being queried
- *
- * Returns: the number of items the cursor references, or -1 there's
- * an error.
- */
-long
-e_card_cursor_get_length (ECardCursor *cursor)
-{
- if ( cursor->priv->corba_cursor != CORBA_OBJECT_NIL ) {
- CORBA_Environment ev;
- long ret_val;
-
- CORBA_exception_init (&ev);
-
- ret_val = GNOME_Evolution_Addressbook_CardCursor_count (cursor->priv->corba_cursor, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning("e_card_cursor_get_length: Exception during "
- "get_length corba call.\n");
- ret_val = -1;
- }
-
- CORBA_exception_free (&ev);
-
- return ret_val;
- }
- else
- return -1;
-}
-
-/**
- * e_card_cursor_get_nth:
- * @cursor: an #ECardCursor object
- * @n: the index of the item requested
- *
- * Gets an #ECard based on an index.
- *
- * Returns: a new #ECard on success, or %NULL on failure.
- */
-ECard *
-e_card_cursor_get_nth (ECardCursor *cursor,
- const long n)
-{
- if ( cursor->priv->corba_cursor != CORBA_OBJECT_NIL ) {
- CORBA_Environment en;
- CORBA_char *vcard;
- ECard *card;
-
- CORBA_exception_init (&en);
-
- vcard = GNOME_Evolution_Addressbook_CardCursor_getNth(cursor->priv->corba_cursor, n, &en);
-
- if (en._major != CORBA_NO_EXCEPTION) {
- g_warning("e_card_cursor_get_nth: Exception during "
- "get_nth corba call.\n");
- }
-
- CORBA_exception_free (&en);
-
- card = e_card_new (vcard);
-
- CORBA_free(vcard);
-
- return card;
- }
- else
- return e_card_new("");
-}
-
-static void
-e_card_cursor_class_init (ECardCursorClass *klass)
-{
- GObjectClass *object_class = (GObjectClass *) klass;
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- object_class->dispose = e_card_cursor_dispose;
-}
-
-static void
-e_card_cursor_init (ECardCursor *cursor)
-{
- cursor->priv = g_new(ECardCursorPrivate, 1);
- cursor->priv->corba_cursor = CORBA_OBJECT_NIL;
-}
-
-GType
-e_card_cursor_get_type (void)
-{
- static GType type = 0;
-
- if (!type){
- static const GTypeInfo info = {
- sizeof (ECardCursorClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_card_cursor_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (ECardCursor),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_card_cursor_init,
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "ECardCursor", &info, 0);
- }
-
- return type;
-}
-
-/**
- * e_card_cursor_construct:
- * @cursor: an #ECardCursor object
- * @corba_cursor: an #GNOME_Evolution_Addressbook_CardCursor
- *
- * Wraps an #GNOME_Evolution_Addressbook_CardCursor object inside the #ECardCursor
- * @cursor object.
- *
- * Returns: a new #ECardCursor on success, or %NULL on failure.
- */
-ECardCursor *
-e_card_cursor_construct (ECardCursor *cursor,
- GNOME_Evolution_Addressbook_CardCursor corba_cursor)
-{
- CORBA_Environment ev;
- g_return_val_if_fail (cursor != NULL, NULL);
- g_return_val_if_fail (E_IS_CARD_CURSOR (cursor), NULL);
- g_return_val_if_fail (corba_cursor != CORBA_OBJECT_NIL, NULL);
-
- CORBA_exception_init (&ev);
-
- /*
- * Initialize cursor
- */
- cursor->priv->corba_cursor = CORBA_Object_duplicate(corba_cursor, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning("e_card_cursor_construct: Exception duplicating "
- "corba cursor.\n");
- CORBA_exception_free (&ev);
- CORBA_exception_init (&ev);
- }
-
- GNOME_Evolution_Addressbook_CardCursor_ref(cursor->priv->corba_cursor, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning("e_card_cursor_construct: Exception reffing "
- "corba cursor.\n");
- }
-
- CORBA_exception_free (&ev);
-
- /*
- * Success: return the GType we were given
- */
- return cursor;
-}
-
-/**
- * e_card_cursor_new:
- * @cursor: the #GNOME_Evolution_Addressbook_CardCursor to be wrapped
- *
- * Creates a new #ECardCursor, which wraps an #GNOME_Evolution_Addressbook_CardCursor
- * object.
- *
- * Returns: a new #ECardCursor on success, or %NULL on failure.
- */
-ECardCursor *
-e_card_cursor_new (GNOME_Evolution_Addressbook_CardCursor corba_cursor)
-{
- ECardCursor *cursor;
-
- cursor = g_object_new (E_TYPE_CARD_CURSOR, NULL);
-
- return e_card_cursor_construct (cursor,
- corba_cursor);
-}
diff --git a/addressbook/backend/ebook/e-card-cursor.h b/addressbook/backend/ebook/e-card-cursor.h
deleted file mode 100644
index b8da39f023..0000000000
--- a/addressbook/backend/ebook/e-card-cursor.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *
- * Author:
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright 2000, Ximian, Inc.
- */
-
-#ifndef __E_CARD_CURSOR_H__
-#define __E_CARD_CURSOR_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <ebook/addressbook.h>
-#include <ebook/e-card.h>
-
-#define E_TYPE_CARD_CURSOR (e_card_cursor_get_type ())
-#define E_CARD_CURSOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_CARD_CURSOR, ECardCursor))
-#define E_CARD_CURSOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_CARD_CURSOR, ECardCursorClass))
-#define E_IS_CARD_CURSOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_CARD_CURSOR))
-#define E_IS_CARD_CURSOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_CARD_CURSOR))
-#define E_CARD_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CARD_CURSOR, ECardCursorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECardCursor ECardCursor;
-typedef struct _ECardCursorPrivate ECardCursorPrivate;
-typedef struct _ECardCursorClass ECardCursorClass;
-
-struct _ECardCursor {
- GObject parent;
- ECardCursorPrivate *priv;
-};
-
-struct _ECardCursorClass {
- GObjectClass parent;
-};
-
-/* Creating a new addressbook. */
-ECardCursor *e_card_cursor_new (GNOME_Evolution_Addressbook_CardCursor corba_cursor);
-ECardCursor *e_card_cursor_construct (ECardCursor *cursor,
- GNOME_Evolution_Addressbook_CardCursor corba_cursor);
-
-GType e_card_cursor_get_type (void);
-
-/* Fetching cards. */
-long e_card_cursor_get_length (ECardCursor *cursor);
-ECard *e_card_cursor_get_nth (ECardCursor *cursor,
- const long nth);
-G_END_DECLS
-
-#endif /* ! __E_CARD_CURSOR_H__ */
diff --git a/addressbook/backend/ebook/e-card-pairs.h b/addressbook/backend/ebook/e-card-pairs.h
deleted file mode 100644
index f82f948ebb..0000000000
--- a/addressbook/backend/ebook/e-card-pairs.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* GnomeCard - a graphical contact manager.
- *
- * pairs.h: This file is part of GnomeCard.
- *
- * Copyright (C) 1999 The Free Software Foundation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __E_CARD_PAIRS_H__
-#define __E_CARD_PAIRS_H__
-
-#include <libversit/vcc.h>
-#include <ebook/e-card.h>
-
-
-#if 0
-struct pair
-{
- char *str;
- ECardPropertyType i ;
-};
-
-struct pair prop_lookup[] = {
- { VCFullNameProp, PROP_FNAME },
- { VCNameProp, PROP_NAME },
- { VCPhotoProp, PROP_PHOTO },
- { VCBirthDateProp, PROP_BDAY },
- { VCAdrProp, PROP_DELADDR },
- { VCDeliveryLabelProp, PROP_DELLABEL },
- { VCTelephoneProp, PROP_PHONE },
- { VCEmailAddressProp, PROP_EMAIL },
- { VCMailerProp, PROP_MAILER },
- { VCTimeZoneProp, PROP_TIMEZN },
- { VCGeoProp, PROP_GEOPOS },
- { VCTitleProp, PROP_TITLE },
- { VCBusinessRoleProp, PROP_ROLE },
- { VCLogoProp, PROP_LOGO },
- { VCAgentProp, PROP_AGENT },
- { VCOrgProp, PROP_ORG },
- { VCCategoriesProp, PROP_CATEGORIES },
- { VCCommentProp, PROP_COMMENT },
- { VCLastRevisedProp, PROP_REV },
- { VCPronunciationProp, PROP_SOUND },
- { VCURLProp, PROP_URL },
- { VCUniqueStringProp, PROP_UID },
- { VCVersionProp, PROP_VERSION },
- { VCPublicKeyProp, PROP_KEY },
- { VCValueProp, PROP_VALUE },
- { VCEncodingProp, PROP_ENCODING },
- { VCQuotedPrintableProp, PROP_QUOTED_PRINTABLE },
- { VC8bitProp, PROP_8BIT },
- { VCBase64Prop, PROP_BASE64 },
- { VCLanguageProp, PROP_LANG },
- { VCCharSetProp, PROP_CHARSET },
- { NULL, PROP_NONE} };
-
-struct pair photo_pairs[] = {
- { VCGIFProp, PHOTO_GIF },
- { VCCGMProp, PHOTO_CGM },
- { VCWMFProp, PHOTO_WMF },
- { VCBMPProp, PHOTO_BMP },
- { VCMETProp, PHOTO_MET },
- { VCPMBProp, PHOTO_PMB },
- { VCDIBProp, PHOTO_DIB },
- { VCPICTProp, PHOTO_PICT },
- { VCTIFFProp, PHOTO_TIFF },
- { VCPDFProp, PHOTO_PDF },
- { VCPSProp, PHOTO_PS },
- { VCJPEGProp, PHOTO_JPEG },
- { VCMPEGProp, PHOTO_MPEG },
- { VCMPEG2Prop, PHOTO_MPEG2 },
- { VCAVIProp, PHOTO_AVI },
- { VCQuickTimeProp, PHOTO_QTIME },
- { NULL, 0 } };
-
-struct pair email_pairs[] = {
- { VCAOLProp, EMAIL_AOL },
- { VCAppleLinkProp, EMAIL_APPLE_LINK },
- { VCATTMailProp, EMAIL_ATT },
- { VCCISProp, EMAIL_CIS },
- { VCEWorldProp, EMAIL_EWORLD },
- { VCInternetProp, EMAIL_INET },
- { VCIBMMailProp, EMAIL_IBM },
- { VCMCIMailProp, EMAIL_MCI },
- { VCPowerShareProp, EMAIL_POWERSHARE },
- { VCProdigyProp, EMAIL_PRODIGY },
- { VCTLXProp, EMAIL_TLX },
- { VCX400Prop, EMAIL_X400 },
- { NULL, 0 } };
-
-struct pair sound_pairs[] = {
- { VCAIFFProp, SOUND_AIFF },
- { VCPCMProp, SOUND_PCM },
- { VCWAVEProp, SOUND_WAVE },
- { NULL, 0 } };
-
-struct pair key_pairs[] = {
- { VCX509Prop, KEY_X509 },
- { VCPGPProp, KEY_PGP },
- { NULL, 0 } };
-
-
-#endif
-#endif /* ! __E_CARD_PAIRS_H__ */
diff --git a/addressbook/backend/ebook/e-card-simple.c b/addressbook/backend/ebook/e-card-simple.c
deleted file mode 100644
index b9e32762fe..0000000000
--- a/addressbook/backend/ebook/e-card-simple.c
+++ /dev/null
@@ -1,1344 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- * Arturo Espinosa (arturo@nuclecu.unam.mx)
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 1999 The Free Software Foundation
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bonobo/bonobo-i18n.h>
-#include <gal/util/e-util.h>
-
-#include <libversit/vcc.h>
-#include "e-card-simple.h"
-
-/* Object property IDs */
-enum {
- PROP_0,
- PROP_CARD,
-};
-
-static GObjectClass *parent_class;
-
-typedef enum _ECardSimpleInternalType ECardSimpleInternalType;
-typedef struct _ECardSimpleFieldData ECardSimpleFieldData;
-
-enum _ECardSimpleInternalType {
- E_CARD_SIMPLE_INTERNAL_TYPE_STRING,
- E_CARD_SIMPLE_INTERNAL_TYPE_DATE,
- E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS,
- E_CARD_SIMPLE_INTERNAL_TYPE_PHONE,
- E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL,
- E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL,
- E_CARD_SIMPLE_INTERNAL_TYPE_BOOL,
-};
-
-struct _ECardSimpleFieldData {
- ECardSimpleField field;
- char *ecard_field;
- char *name;
- char *short_name;
- int list_type_index;
- ECardSimpleInternalType type;
-};
-
-/* This order must match the order in the .h. */
-
-/* the ecard_field data below should only be used for TYPE_STRING,
- TYPE_DATE, and TYPE_SPECIAL fields. that is, it's only valid for
- e-cards for those types. it is used as a unique name for fields
- for the get_supported functionality. */
-static ECardSimpleFieldData field_data[] =
-{
- { E_CARD_SIMPLE_FIELD_FILE_AS, "file_as", N_("File As"), "", 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_FULL_NAME, "full_name", N_("Name"), N_("Name"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_EMAIL, "email", N_("Email"), N_("Email"), E_CARD_SIMPLE_EMAIL_ID_EMAIL, E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL },
- { E_CARD_SIMPLE_FIELD_PHONE_PRIMARY, "primary_phone", N_("Primary"), N_("Prim"), E_CARD_SIMPLE_PHONE_ID_PRIMARY, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_ASSISTANT, "assistant_phone", N_("Assistant"), N_("Assistant"),E_CARD_SIMPLE_PHONE_ID_ASSISTANT, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_BUSINESS, "business_phone", N_("Business"), N_("Bus"), E_CARD_SIMPLE_PHONE_ID_BUSINESS, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_CALLBACK, "callback_phone", N_("Callback"), N_("Callback"), E_CARD_SIMPLE_PHONE_ID_CALLBACK, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_COMPANY, "company_phone", N_("Company"), N_("Comp"), E_CARD_SIMPLE_PHONE_ID_COMPANY, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_HOME, "home_phone", N_("Home"), N_("Home"), E_CARD_SIMPLE_PHONE_ID_HOME, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_ORG, "org", N_("Organization"), N_("Org"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_ADDRESS_BUSINESS, "business_address",N_("Business"), N_("Bus"), E_CARD_SIMPLE_ADDRESS_ID_BUSINESS, E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS },
- { E_CARD_SIMPLE_FIELD_ADDRESS_HOME, "home_address", N_("Home"), N_("Home"), E_CARD_SIMPLE_ADDRESS_ID_HOME, E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS },
- { E_CARD_SIMPLE_FIELD_PHONE_MOBILE, "mobile_phone", N_("Mobile"), N_("Mobile"), E_CARD_SIMPLE_PHONE_ID_MOBILE, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_CAR, "car_phone", N_("Car"), N_("Car"), E_CARD_SIMPLE_PHONE_ID_CAR, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_FAX, "business_fax", N_("Business Fax"), N_("Bus Fax"), E_CARD_SIMPLE_PHONE_ID_BUSINESS_FAX, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_HOME_FAX, "home_fax", N_("Home Fax"), N_("Home Fax"), E_CARD_SIMPLE_PHONE_ID_HOME_FAX, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_2, "business_phone_2",N_("Business 2"), N_("Bus 2"), E_CARD_SIMPLE_PHONE_ID_BUSINESS_2, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_HOME_2, "home_phone_2", N_("Home 2"), N_("Home 2"), E_CARD_SIMPLE_PHONE_ID_HOME_2, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_ISDN, "isdn", N_("ISDN"), N_("ISDN"), E_CARD_SIMPLE_PHONE_ID_ISDN, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_OTHER, "other_phone", N_("Other"), N_("Other"), E_CARD_SIMPLE_PHONE_ID_OTHER, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_OTHER_FAX, "other_fax", N_("Other Fax"), N_("Other Fax"), E_CARD_SIMPLE_PHONE_ID_OTHER_FAX, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_PAGER, "pager", N_("Pager"), N_("Pager"), E_CARD_SIMPLE_PHONE_ID_PAGER, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_RADIO, "radio", N_("Radio"), N_("Radio"), E_CARD_SIMPLE_PHONE_ID_RADIO, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_TELEX, "telex", N_("Telex"), N_("Telex"), E_CARD_SIMPLE_PHONE_ID_TELEX, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_PHONE_TTYTDD, "tty", N_("TTY"), N_("TTY"), E_CARD_SIMPLE_PHONE_ID_TTYTDD, E_CARD_SIMPLE_INTERNAL_TYPE_PHONE },
- { E_CARD_SIMPLE_FIELD_ADDRESS_OTHER, "other_address", N_("Other"), N_("Other"), E_CARD_SIMPLE_ADDRESS_ID_OTHER, E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS },
- { E_CARD_SIMPLE_FIELD_EMAIL_2, "email_2", N_("Email 2"), N_("Email 2"), E_CARD_SIMPLE_EMAIL_ID_EMAIL_2, E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL },
- { E_CARD_SIMPLE_FIELD_EMAIL_3, "email_3", N_("Email 3"), N_("Email 3"), E_CARD_SIMPLE_EMAIL_ID_EMAIL_3, E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL },
- { E_CARD_SIMPLE_FIELD_URL, "url", N_("Web Site"), N_("Url"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_ORG_UNIT, "org_unit", N_("Department"), N_("Dep"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_OFFICE, "office", N_("Office"), N_("Off"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_TITLE, "title", N_("Title"), N_("Title"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_ROLE, "role", N_("Profession"), N_("Prof"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_MANAGER, "manager", N_("Manager"), N_("Man"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_ASSISTANT, "assistant", N_("Assistant"), N_("Ass"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_NICKNAME, "nickname", N_("Nickname"), N_("Nick"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_SPOUSE, "spouse", N_("Spouse"), N_("Spouse"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_NOTE, "note", N_("Note"), N_("Note"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_CALURI, "caluri", N_("Calendar URI"), N_("CALUri"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_FBURL, "fburl", N_("Free-busy URL"), N_("FBUrl"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_ICSCALENDAR, "icscalendar", N_("Default server calendar"), N_("icsCalendar"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_ANNIVERSARY, "anniversary", N_("Anniversary"), N_("Anniv"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_DATE },
- { E_CARD_SIMPLE_FIELD_BIRTH_DATE, "birth_date", N_("Birth Date"), "", 0, E_CARD_SIMPLE_INTERNAL_TYPE_DATE },
- { E_CARD_SIMPLE_FIELD_MAILER, "mailer", "", "", 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_NAME_OR_ORG, "nameororg", "", "", 0, E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL },
- { E_CARD_SIMPLE_FIELD_CATEGORIES, "categories", N_("Categories"), N_("Categories"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_STRING },
- { E_CARD_SIMPLE_FIELD_FAMILY_NAME, "family_name", N_("Family Name"), N_("Family Name"), 0, E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL },
- { E_CARD_SIMPLE_FIELD_GIVEN_NAME, "given_name", "Given Name", "Given Name", 0, E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL },
- { E_CARD_SIMPLE_FIELD_ADDITIONAL_NAME, "additional_name", "Additional Name", "Additional Name", 0, E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL },
- { E_CARD_SIMPLE_FIELD_NAME_SUFFIX, "name_suffix", "Name Suffix", "Name Suffix", 0, E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL },
- { E_CARD_SIMPLE_FIELD_WANTS_HTML, "wants_html", "Wants HTML", "Wants HTML", 0, E_CARD_SIMPLE_INTERNAL_TYPE_BOOL },
- { E_CARD_SIMPLE_FIELD_IS_LIST, "list", "Is List", "Is List", 0, E_CARD_SIMPLE_INTERNAL_TYPE_BOOL },
-};
-static int field_data_count = sizeof (field_data) / sizeof (field_data[0]);
-
-static void e_card_simple_init (ECardSimple *simple);
-static void e_card_simple_class_init (ECardSimpleClass *klass);
-
-static void e_card_simple_dispose (GObject *object);
-static void e_card_simple_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void e_card_simple_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-
-static void fill_in_info(ECardSimple *simple);
-
-ECardPhoneFlags phone_correspondences[] = {
- E_CARD_PHONE_ASSISTANT, /* E_CARD_SIMPLE_PHONE_ID_ASSISTANT, */
- E_CARD_PHONE_WORK | E_CARD_PHONE_VOICE, /* E_CARD_SIMPLE_PHONE_ID_BUSINESS, */
- E_CARD_PHONE_WORK | E_CARD_PHONE_VOICE, /* E_CARD_SIMPLE_PHONE_ID_BUSINESS_2, */
- E_CARD_PHONE_WORK | E_CARD_PHONE_FAX, /* E_CARD_SIMPLE_PHONE_ID_BUSINESS_FAX, */
- E_CARD_PHONE_CALLBACK, /* E_CARD_SIMPLE_PHONE_ID_CALLBACK, */
- E_CARD_PHONE_CAR, /* E_CARD_SIMPLE_PHONE_ID_CAR, */
- E_CARD_PHONE_WORK, /* E_CARD_SIMPLE_PHONE_ID_COMPANY, */
- E_CARD_PHONE_HOME, /* E_CARD_SIMPLE_PHONE_ID_HOME, */
- E_CARD_PHONE_HOME, /* E_CARD_SIMPLE_PHONE_ID_HOME_2, */
- E_CARD_PHONE_HOME | E_CARD_PHONE_FAX, /* E_CARD_SIMPLE_PHONE_ID_HOME_FAX, */
- E_CARD_PHONE_ISDN, /* E_CARD_SIMPLE_PHONE_ID_ISDN, */
- E_CARD_PHONE_CELL, /* E_CARD_SIMPLE_PHONE_ID_MOBILE, */
- E_CARD_PHONE_VOICE, /* E_CARD_SIMPLE_PHONE_ID_OTHER, */
- E_CARD_PHONE_FAX, /* E_CARD_SIMPLE_PHONE_ID_OTHER_FAX, */
- E_CARD_PHONE_PAGER, /* E_CARD_SIMPLE_PHONE_ID_PAGER, */
- E_CARD_PHONE_PREF, /* E_CARD_SIMPLE_PHONE_ID_PRIMARY, */
- E_CARD_PHONE_RADIO, /* E_CARD_SIMPLE_PHONE_ID_RADIO, */
- E_CARD_PHONE_TELEX, /* E_CARD_SIMPLE_PHONE_ID_TELEX, */
- E_CARD_PHONE_TTYTDD, /* E_CARD_SIMPLE_PHONE_ID_TTYTDD, */
-};
-
-char *phone_names[] = {
- NULL, /* E_CARD_SIMPLE_PHONE_ID_ASSISTANT, */
- "Business",
- "Business 2",
- "Business Fax",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_CALLBACK, */
- "Car",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_COMPANY, */
- "Home",
- "Home 2",
- "Home Fax",
- "ISDN",
- "Mobile",
- "Other",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_OTHER_FAX, */
- "Pager",
- "Primary",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_RADIO, */
- NULL, /* E_CARD_SIMPLE_PHONE_ID_TELEX, */
- NULL, /* E_CARD_SIMPLE_PHONE_ID_TTYTDD, */
-};
-
-char *phone_short_names[] = {
- NULL, /* E_CARD_SIMPLE_PHONE_ID_ASSISTANT, */
- "Bus",
- "Bus 2",
- "Bus Fax",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_CALLBACK, */
- "Car",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_COMPANY, */
- "Home",
- "Home 2",
- "Home Fax",
- "ISDN",
- "Mob",
- "Other",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_OTHER_FAX, */
- "Pag",
- "Prim",
- NULL, /* E_CARD_SIMPLE_PHONE_ID_RADIO, */
- NULL, /* E_CARD_SIMPLE_PHONE_ID_TELEX, */
- NULL, /* E_CARD_SIMPLE_PHONE_ID_TTYTDD, */
-};
-
-ECardAddressFlags addr_correspondences[] = {
- E_CARD_ADDR_WORK, /* E_CARD_SIMPLE_ADDRESS_ID_BUSINESS, */
- E_CARD_ADDR_HOME, /* E_CARD_SIMPLE_ADDRESS_ID_HOME, */
- E_CARD_ADDR_POSTAL, /* E_CARD_SIMPLE_ADDRESS_ID_OTHER, */
-};
-
-char *address_names[] = {
- "Business",
- "Home",
- "Other",
-};
-
-/**
- * e_card_simple_get_type:
- * @void:
- *
- * Registers the &ECardSimple class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the &ECardSimple class.
- **/
-GType
-e_card_simple_get_type (void)
-{
- static GType simple_type = 0;
-
- if (!simple_type) {
- static const GTypeInfo simple_info = {
- sizeof (ECardSimpleClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_card_simple_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (ECardSimple),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_card_simple_init,
- };
-
- simple_type = g_type_register_static (G_TYPE_OBJECT, "ECardSimple", &simple_info, 0);
- }
-
- return simple_type;
-}
-
-/**
- * e_card_simple_new:
- * @VCard: a string in vCard format
- *
- * Returns: a new #ECardSimple that wraps the @VCard.
- */
-ECardSimple *
-e_card_simple_new (ECard *card)
-{
- ECardSimple *simple = g_object_new (E_TYPE_CARD_SIMPLE, NULL);
- g_object_set(simple,
- "card", card,
- NULL);
- return simple;
-}
-
-ECardSimple *
-e_card_simple_duplicate(ECardSimple *simple)
-{
- ECard *card = simple->card ? e_card_duplicate (simple->card) : e_card_new ("");
- ECardSimple *new_simple = e_card_simple_new(card);
- return new_simple;
-}
-
-/**
- * e_card_simple_get_id:
- * @simple: an #ECardSimple
- *
- * Returns: a string representing the id of the simple, which is unique
- * within its book.
- */
-const char *
-e_card_simple_get_id (ECardSimple *simple)
-{
- if (simple->card)
- return e_card_get_id(simple->card);
- else
- return "";
-}
-
-/**
- * e_card_simple_get_id:
- * @simple: an #ECardSimple
- * @id: a id in string format
- *
- * Sets the identifier of a simple, which should be unique within its
- * book.
- */
-void
-e_card_simple_set_id (ECardSimple *simple, const char *id)
-{
- if ( simple->card )
- e_card_set_id(simple->card, id);
-}
-
-/**
- * e_card_simple_get_vcard:
- * @simple: an #ECardSimple
- *
- * Returns: a string in vcard format, which is wrapped by the @simple.
- */
-char *
-e_card_simple_get_vcard (ECardSimple *simple)
-{
- if (simple->card)
- return e_card_get_vcard(simple->card);
- else
- return g_strdup("");
-}
-
-/**
- * e_card_simple_get_vcard_assume_utf8:
- * @simple: an #ECardSimple
- *
- * Returns: a string in vcard format, which is wrapped by the @simple.
- */
-char *
-e_card_simple_get_vcard_assume_utf8 (ECardSimple *simple)
-{
- if (simple->card)
- return e_card_get_vcard_assume_utf8(simple->card);
- else
- return g_strdup("");
-}
-
-static void
-e_card_simple_class_init (ECardSimpleClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS(klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- object_class->dispose = e_card_simple_dispose;
- object_class->get_property = e_card_simple_get_property;
- object_class->set_property = e_card_simple_set_property;
-
- g_object_class_install_property (object_class, PROP_CARD,
- g_param_spec_object ("card",
- _("ECard"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_CARD,
- G_PARAM_READWRITE));
-}
-
-/*
- * ECardSimple lifecycle management and vcard loading/saving.
- */
-
-static void
-e_card_simple_dispose (GObject *object)
-{
- ECardSimple *simple;
- int i;
-
- simple = E_CARD_SIMPLE (object);
-
- if (simple->card) {
- g_object_unref(simple->card);
- simple->card = NULL;
- }
- if (simple->temp_fields) {
- g_list_foreach(simple->temp_fields, (GFunc) g_free, NULL);
- g_list_free(simple->temp_fields);
- simple->temp_fields = NULL;
- }
-
- for(i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i++) {
- if (simple->phone[i]) {
- e_card_phone_unref (simple->phone[i]);
- simple->phone[i] = NULL;
- }
- }
- for(i = 0; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i++) {
- if (simple->email[i]) {
- g_free(simple->email[i]);
- simple->email[i] = NULL;
- }
- }
- for(i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i++) {
- if (simple->address[i]) {
- e_card_address_label_unref(simple->address[i]);
- simple->address[i] = NULL;
- }
- }
- for(i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i++) {
- if (simple->delivery[i]) {
- e_card_delivery_address_unref(simple->delivery[i]);
- simple->delivery[i] = NULL;
- }
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-
-/* Set_arg handler for the simple */
-static void
-e_card_simple_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ECardSimple *simple;
-
- simple = E_CARD_SIMPLE (object);
-
- switch (prop_id) {
- case PROP_CARD:
- if (simple->card)
- g_object_unref(simple->card);
- g_list_foreach(simple->temp_fields, (GFunc) g_free, NULL);
- g_list_free(simple->temp_fields);
- simple->temp_fields = NULL;
- if (g_value_get_object (value))
- simple->card = E_CARD(g_value_get_object (value));
- else
- simple->card = NULL;
- if(simple->card)
- g_object_ref(simple->card);
- fill_in_info(simple);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* Get_arg handler for the simple */
-static void
-e_card_simple_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ECardSimple *simple;
-
- simple = E_CARD_SIMPLE (object);
-
- switch (prop_id) {
- case PROP_CARD:
- e_card_simple_sync_card(simple);
- g_value_set_object (value, simple->card);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-/**
- * e_card_simple_init:
- */
-static void
-e_card_simple_init (ECardSimple *simple)
-{
- int i;
- simple->card = NULL;
- for(i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i++)
- simple->phone[i] = NULL;
- for(i = 0; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i++)
- simple->email[i] = NULL;
- for(i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i++)
- simple->address[i] = NULL;
- simple->temp_fields = NULL;
-
- simple->changed = TRUE;
-}
-
-static void
-fill_in_info(ECardSimple *simple)
-{
- ECard *card = simple->card;
- if (card) {
- EList *address_list;
- EList *phone_list;
- EList *email_list;
- EList *delivery_list;
- const ECardPhone *phone;
- const char *email;
- const ECardAddrLabel *address;
- const ECardDeliveryAddress *delivery;
- int i;
-
- EIterator *iterator;
-
- g_object_get(card,
- "address_label", &address_list,
- "address", &delivery_list,
- "phone", &phone_list,
- "email", &email_list,
- NULL);
- for (i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i++) {
- e_card_phone_unref(simple->phone[i]);
- simple->phone[i] = NULL;
- }
- for (iterator = e_list_get_iterator(phone_list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- gboolean found = FALSE;
- phone = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i ++) {
- if ((phone->flags == phone_correspondences[i]) && (simple->phone[i] == NULL)) {
- simple->phone[i] = e_card_phone_ref(phone);
- found = TRUE;
- break;
- }
- }
- if (found)
- continue;
- for (i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i ++) {
- if (((phone->flags & phone_correspondences[i]) == phone_correspondences[i]) && (simple->phone[i] == NULL)) {
- simple->phone[i] = e_card_phone_ref(phone);
- break;
- }
- }
- }
- g_object_unref(iterator);
-
- for (i = 0; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i++) {
- g_free(simple->email[i]);
- simple->email[i] = NULL;
- }
- for (iterator = e_list_get_iterator(email_list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- email = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i ++) {
- if ((simple->email[i] == NULL)) {
- simple->email[i] = g_strdup(email);
- break;
- }
- }
- }
- g_object_unref(iterator);
-
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i++) {
- e_card_address_label_unref(simple->address[i]);
- simple->address[i] = NULL;
- }
- for (iterator = e_list_get_iterator(address_list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- address = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i ++) {
- if (((address->flags & addr_correspondences[i]) == addr_correspondences[i]) && (simple->address[i] == NULL)) {
- simple->address[i] = e_card_address_label_ref(address);
- break;
- }
- }
- }
- g_object_unref(iterator);
-
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i++) {
- e_card_delivery_address_unref(simple->delivery[i]);
- simple->delivery[i] = NULL;
- }
- for (iterator = e_list_get_iterator(delivery_list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- delivery = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i ++) {
- if (((delivery->flags & addr_correspondences[i]) == addr_correspondences[i]) && (simple->delivery[i] == NULL)) {
- simple->delivery[i] = e_card_delivery_address_ref(delivery);
- break;
- }
- }
- }
- g_object_unref(iterator);
-
- g_object_unref(phone_list);
- g_object_unref(email_list);
- g_object_unref(address_list);
- g_object_unref(delivery_list);
- e_card_free_empty_lists (card);
- }
-}
-
-void
-e_card_simple_sync_card(ECardSimple *simple)
-{
- ECard *card = simple->card;
- if (card && simple->changed) {
- EList *address_list;
- EList *phone_list;
- EList *email_list;
- EList *delivery_list;
- const ECardPhone *phone;
- const ECardAddrLabel *address;
- const ECardDeliveryAddress *delivery;
- const char *email;
- int i;
-
- EIterator *iterator;
-
- g_object_get(card,
- "address_label", &address_list,
- "address", &delivery_list,
- "phone", &phone_list,
- "email", &email_list,
- NULL);
-
- for (iterator = e_list_get_iterator(phone_list); e_iterator_is_valid(iterator); e_iterator_next(iterator) ) {
- int i;
- gboolean found = FALSE;
- phone = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i ++) {
- if (phone->flags == phone_correspondences[i]) {
- if (simple->phone[i]) {
- simple->phone[i]->flags = phone_correspondences[i];
- if (simple->phone[i]->number && *simple->phone[i]->number) {
- e_iterator_set(iterator, simple->phone[i]);
- } else {
- e_iterator_delete(iterator);
- }
- e_card_phone_unref(simple->phone[i]);
- simple->phone[i] = NULL;
- found = TRUE;
- break;
- }
- }
- }
- if (found)
- continue;
- for (i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i ++) {
- if ((phone->flags & phone_correspondences[i]) == phone_correspondences[i]) {
- if (simple->phone[i]) {
- simple->phone[i]->flags = phone_correspondences[i];
- if (simple->phone[i]->number && *simple->phone[i]->number) {
- e_iterator_set(iterator, simple->phone[i]);
- } else {
- e_iterator_delete(iterator);
- }
- e_card_phone_unref(simple->phone[i]);
- simple->phone[i] = NULL;
- break;
- }
- }
- }
- }
- g_object_unref(iterator);
- for (i = 0; i < E_CARD_SIMPLE_PHONE_ID_LAST; i ++) {
- if (simple->phone[i]) {
- simple->phone[i]->flags = phone_correspondences[i];
- e_list_append(phone_list, simple->phone[i]);
- e_card_phone_unref(simple->phone[i]);
- simple->phone[i] = NULL;
- }
- }
-
- for (iterator = e_list_get_iterator(email_list); e_iterator_is_valid(iterator); e_iterator_next(iterator) ) {
- int i;
- email = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i ++) {
- if (simple->email[i]) {
- if (*simple->email[i]) {
- e_iterator_set(iterator, simple->email[i]);
- } else {
- e_iterator_delete(iterator);
- }
- g_free(simple->email[i]);
- simple->email[i] = NULL;
- break;
- }
- }
- }
- g_object_unref(iterator);
- for (i = 0; i < E_CARD_SIMPLE_EMAIL_ID_LAST; i ++) {
- if (simple->email[i]) {
- e_list_append(email_list, simple->email[i]);
- g_free(simple->email[i]);
- simple->email[i] = NULL;
- }
- }
-
- for (iterator = e_list_get_iterator(address_list); e_iterator_is_valid(iterator); e_iterator_next(iterator) ) {
- int i;
- address = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i ++) {
- if ((address->flags & addr_correspondences[i]) == addr_correspondences[i]) {
- if (simple->address[i]) {
- simple->address[i]->flags &= ~E_CARD_ADDR_MASK;
- simple->address[i]->flags |= addr_correspondences[i];
- if (simple->address[i]->data && *simple->address[i]->data) {
- e_iterator_set(iterator, simple->address[i]);
- } else {
- e_iterator_delete(iterator);
- }
- e_card_address_label_unref(simple->address[i]);
- simple->address[i] = NULL;
- break;
- }
- }
- }
- }
- g_object_unref(iterator);
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i ++) {
- if (simple->address[i]) {
- simple->address[i]->flags &= ~E_CARD_ADDR_MASK;
- simple->address[i]->flags |= addr_correspondences[i];
- e_list_append(address_list, simple->address[i]);
- e_card_address_label_unref(simple->address[i]);
- simple->address[i] = NULL;
- }
- }
-
- for (iterator = e_list_get_iterator(delivery_list); e_iterator_is_valid(iterator); e_iterator_next(iterator) ) {
- int i;
- delivery = e_iterator_get(iterator);
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i ++) {
- if ((delivery->flags & addr_correspondences[i]) == addr_correspondences[i]) {
- if (simple->delivery[i]) {
- simple->delivery[i]->flags &= ~E_CARD_ADDR_MASK;
- simple->delivery[i]->flags |= addr_correspondences[i];
- if (!e_card_delivery_address_is_empty(simple->delivery[i])) {
- e_iterator_set(iterator, simple->delivery[i]);
- } else {
- e_iterator_delete(iterator);
- }
- e_card_delivery_address_unref(simple->delivery[i]);
- simple->delivery[i] = NULL;
- break;
- }
- }
- }
- }
- g_object_unref(iterator);
- for (i = 0; i < E_CARD_SIMPLE_ADDRESS_ID_LAST; i ++) {
- if (simple->delivery[i]) {
- simple->delivery[i]->flags &= ~E_CARD_ADDR_MASK;
- simple->delivery[i]->flags |= addr_correspondences[i];
- e_list_append(delivery_list, simple->delivery[i]);
- e_card_delivery_address_unref(simple->delivery[i]);
- simple->delivery[i] = NULL;
- }
- }
- fill_in_info(simple);
-
- g_object_unref(phone_list);
- g_object_unref(email_list);
- g_object_unref(address_list);
- g_object_unref(delivery_list);
- e_card_free_empty_lists (card);
- }
-
- simple->changed = FALSE;
-}
-
-const ECardPhone *e_card_simple_get_phone (ECardSimple *simple,
- ECardSimplePhoneId id)
-{
- return simple->phone[id];
-}
-
-const char *e_card_simple_get_email (ECardSimple *simple,
- ECardSimpleEmailId id)
-{
- return simple->email[id];
-}
-
-const ECardAddrLabel *e_card_simple_get_address (ECardSimple *simple,
- ECardSimpleAddressId id)
-{
- return simple->address[id];
-}
-
-const ECardDeliveryAddress *e_card_simple_get_delivery_address (ECardSimple *simple,
- ECardSimpleAddressId id)
-{
- return simple->delivery[id];
-}
-
-void e_card_simple_set_phone (ECardSimple *simple,
- ECardSimplePhoneId id,
- const ECardPhone *phone)
-{
- e_card_phone_unref(simple->phone[id]);
- simple->phone[id] = e_card_phone_ref(phone);
- simple->changed = TRUE;
-}
-
-void e_card_simple_set_email (ECardSimple *simple,
- ECardSimpleEmailId id,
- const char *email)
-{
- g_free(simple->email[id]);
- simple->email[id] = g_strdup(email);
- simple->changed = TRUE;
-}
-
-void
-e_card_simple_set_address (ECardSimple *simple, ECardSimpleAddressId id, const ECardAddrLabel *address)
-{
- e_card_address_label_unref(simple->address[id]);
- simple->address[id] = e_card_address_label_ref(address);
- e_card_delivery_address_unref(simple->delivery[id]);
- simple->delivery[id] = e_card_delivery_address_from_label(simple->address[id]);
- simple->changed = TRUE;
-}
-
-void e_card_simple_set_delivery_address (ECardSimple *simple,
- ECardSimpleAddressId id,
- const ECardDeliveryAddress *delivery)
-{
- e_card_delivery_address_unref(simple->delivery[id]);
- simple->delivery[id] = e_card_delivery_address_ref(delivery);
- e_card_address_label_unref(simple->address[id]);
- simple->address[id] = e_card_delivery_address_to_label(simple->delivery[id]);
- simple->changed = TRUE;
-}
-
-const char *e_card_simple_get_const (ECardSimple *simple,
- ECardSimpleField field)
-{
- char *ret_val = e_card_simple_get(simple, field);
- if (ret_val)
- simple->temp_fields = g_list_prepend(simple->temp_fields, ret_val);
- return ret_val;
-}
-
-char *e_card_simple_get (ECardSimple *simple,
- ECardSimpleField field)
-{
- ECardSimpleInternalType type = field_data[field].type;
- const ECardAddrLabel *addr;
- const ECardPhone *phone;
- char *string;
- ECardDate *date;
- ECardName *name;
- switch(type) {
- case E_CARD_SIMPLE_INTERNAL_TYPE_STRING:
- if (simple->card) {
- g_object_get(simple->card,
- field_data[field].ecard_field, &string,
- NULL);
- return string;
- } else
- return NULL;
- case E_CARD_SIMPLE_INTERNAL_TYPE_DATE:
- if (simple->card) {
- g_object_get(simple->card,
- field_data[field].ecard_field, &date,
- NULL);
- if (date != NULL) {
- char buf[26];
- struct tm then;
- then.tm_year = date->year;
- then.tm_mon = date->month - 1;
- then.tm_mday = date->day;
- then.tm_hour = 12;
- then.tm_min = 0;
- then.tm_sec = 0;
- e_strftime_fix_am_pm (buf, 26, _("%x"), &then);
- return g_strdup (buf);
- } else {
- return NULL;
- }
- } else
- return NULL;
- case E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS:
- addr = e_card_simple_get_address(simple,
- field_data[field].list_type_index);
- if (addr)
- return g_strdup(addr->data);
- else
- return NULL;
- case E_CARD_SIMPLE_INTERNAL_TYPE_PHONE:
- phone = e_card_simple_get_phone(simple,
- field_data[field].list_type_index);
- if (phone)
- return g_strdup(phone->number);
- else
- return NULL;
- case E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL:
- string = e_card_simple_get_email(simple,
- field_data[field].list_type_index);
- return g_strdup(string);
- case E_CARD_SIMPLE_INTERNAL_TYPE_BOOL:
- if (simple->card) {
- gboolean boole;
- g_object_get (simple->card,
- field_data[field].ecard_field, &boole,
- NULL);
- if (boole)
- return g_strdup("true");
- else
- return NULL;
- } else {
- return NULL;
- }
- case E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL:
- switch (field) {
- case E_CARD_SIMPLE_FIELD_NAME_OR_ORG:
- if (simple->card) {
- gboolean is_list;
-
- g_object_get(simple->card,
- "file_as", &string,
- NULL);
- if (string && *string)
- return string
-; else
- g_free (string);
-
- g_object_get(simple->card,
- "full_name", &string,
- NULL);
- if (string && *string)
- return g_strdup(string);
- else
- g_free (string);
-
- g_object_get(simple->card,
- "org", &string,
- NULL);
- if (string && *string)
- return g_strdup(string);
- else
- g_free (string);
-
- is_list = e_card_evolution_list (simple->card);
- if (is_list)
- string = _("Unnamed List");
- else
- string = e_card_simple_get_email(simple,
- E_CARD_SIMPLE_EMAIL_ID_EMAIL);
- return g_strdup(string);
- } else
- return NULL;
- case E_CARD_SIMPLE_FIELD_FAMILY_NAME:
- if (simple->card) {
- g_object_get (simple->card,
- "name", &name,
- NULL);
- return g_strdup (name->family);
- } else
- return NULL;
- case E_CARD_SIMPLE_FIELD_GIVEN_NAME:
- if (simple->card) {
- g_object_get (simple->card,
- "name", &name,
- NULL);
- return g_strdup (name->given);
- } else
- return NULL;
- case E_CARD_SIMPLE_FIELD_ADDITIONAL_NAME:
- if (simple->card) {
- g_object_get (simple->card,
- "name", &name,
- NULL);
- return g_strdup (name->additional);
- } else
- return NULL;
- case E_CARD_SIMPLE_FIELD_NAME_SUFFIX:
- if (simple->card) {
- g_object_get (simple->card,
- "name", &name,
- NULL);
- return g_strdup (name->suffix);
- } else
- return NULL;
- default:
- return NULL;
- }
- default:
- return NULL;
- }
-}
-
-static char *
-name_to_style(const ECardName *name, char *company, int style)
-{
- char *string;
- char *strings[4], **stringptr;
- char *substring;
- switch (style) {
- case 0:
- stringptr = strings;
- if (name->family && *name->family)
- *(stringptr++) = name->family;
- if (name->given && *name->given)
- *(stringptr++) = name->given;
- *stringptr = NULL;
- string = g_strjoinv(", ", strings);
- break;
- case 1:
- stringptr = strings;
- if (name->given && *name->given)
- *(stringptr++) = name->given;
- if (name->family && *name->family)
- *(stringptr++) = name->family;
- *stringptr = NULL;
- string = g_strjoinv(" ", strings);
- break;
- case 2:
- string = g_strdup(company);
- break;
- case 3: /* Fall Through */
- case 4:
- stringptr = strings;
- if (name->family && *name->family)
- *(stringptr++) = name->family;
- if (name->given && *name->given)
- *(stringptr++) = name->given;
- *stringptr = NULL;
- substring = g_strjoinv(", ", strings);
- if (!(company && *company))
- company = "";
- if (style == 3)
- string = g_strdup_printf("%s (%s)", substring, company);
- else
- string = g_strdup_printf("%s (%s)", company, substring);
- g_free(substring);
- break;
- default:
- string = g_strdup("");
- }
- return string;
-}
-
-static int
-file_as_get_style (ECardSimple *simple)
-{
- char *filestring = e_card_simple_get(simple, E_CARD_SIMPLE_FIELD_FILE_AS);
- char *trystring;
- char *company = e_card_simple_get(simple, E_CARD_SIMPLE_FIELD_ORG);
- ECardName *name = NULL;
- int i;
- int style;
- style = 0;
- if (!company)
- company = g_strdup("");
- if (filestring) {
- g_object_get (simple->card,
- "name", &name,
- NULL);
-
- if (!name) {
- goto end;
- }
-
- style = -1;
-
- for (i = 0; i < 5; i++) {
- trystring = name_to_style(name, company, i);
- if (!strcmp(trystring, filestring)) {
- g_free(trystring);
- style = i;
- goto end;
- }
- g_free(trystring);
- }
- }
- end:
-
- g_free(filestring);
- g_free(company);
-
- return style;
-}
-
-static void
-file_as_set_style(ECardSimple *simple, int style)
-{
- if (style != -1) {
- char *string;
- char *company = e_card_simple_get(simple, E_CARD_SIMPLE_FIELD_ORG);
- ECardName *name;
-
- if (!company)
- company = g_strdup("");
- g_object_get (simple->card,
- "name", &name,
- NULL);
- if (name) {
- string = name_to_style(name, company, style);
- e_card_simple_set(simple, E_CARD_SIMPLE_FIELD_FILE_AS, string);
- g_free(string);
- }
- g_free(company);
- }
-}
-
-void e_card_simple_set (ECardSimple *simple,
- ECardSimpleField field,
- const char *data)
-{
- ECardSimpleInternalType type = field_data[field].type;
- ECardAddrLabel *address;
- ECardPhone *phone;
- int style;
- simple->changed = TRUE;
- switch (field) {
- case E_CARD_SIMPLE_FIELD_FULL_NAME:
- case E_CARD_SIMPLE_FIELD_ORG:
- style = file_as_get_style(simple);
- g_object_set(simple->card,
- field_data[field].ecard_field, data,
- NULL);
- file_as_set_style(simple, style);
- break;
- default:
- switch(type) {
- case E_CARD_SIMPLE_INTERNAL_TYPE_STRING:
- g_object_set(simple->card,
- field_data[field].ecard_field, data,
- NULL);
- break;
- case E_CARD_SIMPLE_INTERNAL_TYPE_DATE:
- break; /* FIXME!!!! */
- case E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS:
- address = e_card_address_label_new();
- address->data = g_strdup (data);
- e_card_simple_set_address(simple,
- field_data[field].list_type_index,
- address);
- e_card_address_label_unref(address);
- break;
- case E_CARD_SIMPLE_INTERNAL_TYPE_PHONE:
- phone = e_card_phone_new();
- phone->number = g_strdup (data);
- e_card_simple_set_phone(simple,
- field_data[field].list_type_index,
- phone);
- e_card_phone_unref(phone);
- break;
- case E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL:
- e_card_simple_set_email(simple,
- field_data[field].list_type_index,
- data);
- break;
- case E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL:
- break;
- case E_CARD_SIMPLE_INTERNAL_TYPE_BOOL:
- if (simple->card) {
- gboolean boole = TRUE;
- if (data == NULL)
- boole = FALSE;
- else if (!strcasecmp (data, "false"))
- boole = FALSE;
- g_object_set (simple->card,
- field_data[field].ecard_field, boole,
- NULL);
- }
- break;
- }
- break;
- }
-}
-
-ECardSimpleType e_card_simple_type (ECardSimple *simple,
- ECardSimpleField field)
-{
- ECardSimpleInternalType type = field_data[field].type;
- switch(type) {
- case E_CARD_SIMPLE_INTERNAL_TYPE_STRING:
- case E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS:
- case E_CARD_SIMPLE_INTERNAL_TYPE_PHONE:
- case E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL:
- default:
- return E_CARD_SIMPLE_TYPE_STRING;
-
- case E_CARD_SIMPLE_INTERNAL_TYPE_BOOL:
- return E_CARD_SIMPLE_TYPE_BOOL;
-
- case E_CARD_SIMPLE_INTERNAL_TYPE_DATE:
- return E_CARD_SIMPLE_TYPE_DATE;
-
- case E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL:
- return E_CARD_SIMPLE_TYPE_STRING;
- }
-}
-
-const char *e_card_simple_get_ecard_field (ECardSimple *simple,
- ECardSimpleField field)
-{
- return field_data[field].ecard_field;
-}
-
-const char *e_card_simple_get_name (ECardSimple *simple,
- ECardSimpleField field)
-{
- return _(field_data[field].name);
-}
-
-gboolean
-e_card_simple_get_allow_newlines (ECardSimple *simple,
- ECardSimpleField field)
-{
- ECardSimpleInternalType type = field_data[field].type;
- switch(type) {
- case E_CARD_SIMPLE_INTERNAL_TYPE_STRING:
- case E_CARD_SIMPLE_INTERNAL_TYPE_PHONE:
- case E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL:
- case E_CARD_SIMPLE_INTERNAL_TYPE_BOOL:
- case E_CARD_SIMPLE_INTERNAL_TYPE_DATE:
- case E_CARD_SIMPLE_INTERNAL_TYPE_SPECIAL:
- default:
- switch (field) {
- case E_CARD_SIMPLE_FIELD_NOTE:
- return TRUE;
- default:
- return FALSE;
- }
-
- case E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS:
- return TRUE;
- }
-}
-
-const char *e_card_simple_get_short_name (ECardSimple *simple,
- ECardSimpleField field)
-{
- return _(field_data[field].short_name);
-}
-
-void e_card_simple_arbitrary_foreach (ECardSimple *simple,
- ECardSimpleArbitraryCallback *callback,
- gpointer closure)
-{
- if (simple->card) {
- EList *list;
- EIterator *iterator;
- g_object_get(simple->card,
- "arbitrary", &list,
- NULL);
- for (iterator = e_list_get_iterator(list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- const ECardArbitrary *arbitrary = e_iterator_get(iterator);
- if (callback)
- (*callback) (arbitrary, closure);
- }
-
- g_object_unref (list);
- e_card_free_empty_lists (simple->card);
- }
-}
-
-const ECardArbitrary *e_card_simple_get_arbitrary (ECardSimple *simple,
- const char *key)
-{
- if (simple->card) {
- EList *list;
- EIterator *iterator;
- g_object_get(simple->card,
- "arbitrary", &list,
- NULL);
- for (iterator = e_list_get_iterator(list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- const ECardArbitrary *arbitrary = e_iterator_get(iterator);
- if (!strcasecmp(arbitrary->key, key))
- return arbitrary;
- }
-
- g_object_unref (list);
- e_card_free_empty_lists (simple->card);
- }
- return NULL;
-}
-
-/* Any of these except key can be NULL */
-void e_card_simple_set_arbitrary (ECardSimple *simple,
- const char *key,
- const char *type,
- const char *value)
-{
- if (simple->card) {
- ECardArbitrary *new_arb;
- EList *list;
- EIterator *iterator;
-
- simple->changed = TRUE;
- g_object_get(simple->card,
- "arbitrary", &list,
- NULL);
- for (iterator = e_list_get_iterator(list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- const ECardArbitrary *arbitrary = e_iterator_get(iterator);
- if (!strcasecmp(arbitrary->key, key)) {
- new_arb = e_card_arbitrary_new();
- new_arb->key = g_strdup(key);
- new_arb->type = g_strdup(type);
- new_arb->value = g_strdup(value);
- e_iterator_set(iterator, new_arb);
- e_card_arbitrary_unref(new_arb);
- return;
- }
- }
- new_arb = e_card_arbitrary_new();
- new_arb->key = g_strdup(key);
- new_arb->type = g_strdup(type);
- new_arb->value = g_strdup(value);
- e_list_append(list, new_arb);
- g_object_unref(list);
- e_card_arbitrary_unref(new_arb);
- }
-}
-
-void
-e_card_simple_set_name (ECardSimple *simple, ECardName *name)
-{
- int style;
- style = file_as_get_style(simple);
- g_object_set (simple->card,
- "name", name,
- NULL);
- file_as_set_style(simple, style);
-}
-
-/* These map between the individual list types and ECardSimpleField */
-ECardSimpleField
-e_card_simple_map_phone_to_field (ECardSimplePhoneId phone_id)
-{
- int i;
-
- g_return_val_if_fail (phone_id < E_CARD_SIMPLE_PHONE_ID_LAST, 0);
-
- for (i = 0; i < field_data_count; i ++)
- if (field_data[i].list_type_index == phone_id
- && field_data[i].type == E_CARD_SIMPLE_INTERNAL_TYPE_PHONE)
- return i;
-
- g_warning ("couldn't find phone id %d, returning 0 (which is almost assuredly incorrect)\n", phone_id);
-
- return 0;
-}
-
-ECardSimpleField
-e_card_simple_map_email_to_field (ECardSimpleEmailId email_id)
-{
- int i;
-
- g_return_val_if_fail (email_id < E_CARD_SIMPLE_EMAIL_ID_LAST, 0);
-
- for (i = 0; i < field_data_count; i ++)
- if (field_data[i].list_type_index == email_id
- && field_data[i].type == E_CARD_SIMPLE_INTERNAL_TYPE_EMAIL)
- return i;
-
- g_warning ("couldn't find email id %d, returning 0 (which is almost assuredly incorrect)\n", email_id);
- return 0;
-}
-
-ECardSimpleField
-e_card_simple_map_address_to_field (ECardSimpleAddressId address_id)
-{
- int i;
-
- g_return_val_if_fail (address_id < E_CARD_SIMPLE_ADDRESS_ID_LAST, 0);
-
- for (i = 0; i < field_data_count; i ++)
- if (field_data[i].list_type_index == address_id
- && field_data[i].type == E_CARD_SIMPLE_INTERNAL_TYPE_ADDRESS)
- return i;
-
- g_warning ("couldn't find address id %d, returning 0 (which is almost assuredly incorrect)\n", address_id);
- return 0;
-}
diff --git a/addressbook/backend/ebook/e-card-simple.h b/addressbook/backend/ebook/e-card-simple.h
deleted file mode 100644
index 868d4e1573..0000000000
--- a/addressbook/backend/ebook/e-card-simple.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- * Arturo Espinosa
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 1999 The Free Software Foundation
- */
-
-#ifndef __E_CARD_SIMPLE_H__
-#define __E_CARD_SIMPLE_H__
-
-#include <time.h>
-#include <glib-object.h>
-#include <stdio.h>
-#include <ebook/e-card.h>
-#include <ebook/e-card-types.h>
-#include <e-util/e-list.h>
-
-#define E_TYPE_CARD_SIMPLE (e_card_simple_get_type ())
-#define E_CARD_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CARD_SIMPLE, ECardSimple))
-#define E_CARD_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CARD_SIMPLE, ECardSimpleClass))
-#define E_IS_CARD_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CARD_SIMPLE))
-#define E_IS_CARD_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CARD_SIMPLE))
-#define E_CARD_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CARD_SIMPLE, ECardSimpleClass))
-
-typedef enum _ECardSimplePhoneId ECardSimplePhoneId;
-typedef enum _ECardSimpleEmailId ECardSimpleEmailId;
-typedef enum _ECardSimpleAddressId ECardSimpleAddressId;
-typedef enum _ECardSimpleType ECardSimpleType;
-typedef enum _ECardSimpleField ECardSimpleField;
-
-enum _ECardSimplePhoneId {
- E_CARD_SIMPLE_PHONE_ID_ASSISTANT,
- E_CARD_SIMPLE_PHONE_ID_BUSINESS,
- E_CARD_SIMPLE_PHONE_ID_BUSINESS_2,
- E_CARD_SIMPLE_PHONE_ID_BUSINESS_FAX,
- E_CARD_SIMPLE_PHONE_ID_CALLBACK,
- E_CARD_SIMPLE_PHONE_ID_CAR,
- E_CARD_SIMPLE_PHONE_ID_COMPANY,
- E_CARD_SIMPLE_PHONE_ID_HOME,
- E_CARD_SIMPLE_PHONE_ID_HOME_2,
- E_CARD_SIMPLE_PHONE_ID_HOME_FAX,
- E_CARD_SIMPLE_PHONE_ID_ISDN,
- E_CARD_SIMPLE_PHONE_ID_MOBILE,
- E_CARD_SIMPLE_PHONE_ID_OTHER,
- E_CARD_SIMPLE_PHONE_ID_OTHER_FAX,
- E_CARD_SIMPLE_PHONE_ID_PAGER,
- E_CARD_SIMPLE_PHONE_ID_PRIMARY,
- E_CARD_SIMPLE_PHONE_ID_RADIO,
- E_CARD_SIMPLE_PHONE_ID_TELEX,
- E_CARD_SIMPLE_PHONE_ID_TTYTDD,
- E_CARD_SIMPLE_PHONE_ID_LAST
-};
-
-/* We need HOME and WORK email addresses here. */
-enum _ECardSimpleEmailId {
- E_CARD_SIMPLE_EMAIL_ID_EMAIL,
- E_CARD_SIMPLE_EMAIL_ID_EMAIL_2,
- E_CARD_SIMPLE_EMAIL_ID_EMAIL_3,
- E_CARD_SIMPLE_EMAIL_ID_LAST
-};
-
-/* Should this include (BILLING/SHIPPING)? */
-enum _ECardSimpleAddressId {
- E_CARD_SIMPLE_ADDRESS_ID_BUSINESS,
- E_CARD_SIMPLE_ADDRESS_ID_HOME,
- E_CARD_SIMPLE_ADDRESS_ID_OTHER,
- E_CARD_SIMPLE_ADDRESS_ID_LAST
-};
-
-enum _ECardSimpleType {
- E_CARD_SIMPLE_TYPE_STRING,
- E_CARD_SIMPLE_TYPE_DATE,
- E_CARD_SIMPLE_TYPE_BOOL,
-};
-
-enum _ECardSimpleField {
- E_CARD_SIMPLE_FIELD_FILE_AS,
- E_CARD_SIMPLE_FIELD_FULL_NAME,
- E_CARD_SIMPLE_FIELD_EMAIL,
- E_CARD_SIMPLE_FIELD_PHONE_PRIMARY,
- E_CARD_SIMPLE_FIELD_PHONE_ASSISTANT,
- E_CARD_SIMPLE_FIELD_PHONE_BUSINESS,
- E_CARD_SIMPLE_FIELD_PHONE_CALLBACK,
- E_CARD_SIMPLE_FIELD_PHONE_COMPANY,
- E_CARD_SIMPLE_FIELD_PHONE_HOME,
- E_CARD_SIMPLE_FIELD_ORG,
- E_CARD_SIMPLE_FIELD_ADDRESS_BUSINESS,
- E_CARD_SIMPLE_FIELD_ADDRESS_HOME,
- E_CARD_SIMPLE_FIELD_PHONE_MOBILE,
- E_CARD_SIMPLE_FIELD_PHONE_CAR,
- E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_FAX,
- E_CARD_SIMPLE_FIELD_PHONE_HOME_FAX,
- E_CARD_SIMPLE_FIELD_PHONE_BUSINESS_2,
- E_CARD_SIMPLE_FIELD_PHONE_HOME_2,
- E_CARD_SIMPLE_FIELD_PHONE_ISDN,
- E_CARD_SIMPLE_FIELD_PHONE_OTHER,
- E_CARD_SIMPLE_FIELD_PHONE_OTHER_FAX,
- E_CARD_SIMPLE_FIELD_PHONE_PAGER,
- E_CARD_SIMPLE_FIELD_PHONE_RADIO,
- E_CARD_SIMPLE_FIELD_PHONE_TELEX,
- E_CARD_SIMPLE_FIELD_PHONE_TTYTDD,
- E_CARD_SIMPLE_FIELD_ADDRESS_OTHER,
- E_CARD_SIMPLE_FIELD_EMAIL_2,
- E_CARD_SIMPLE_FIELD_EMAIL_3,
- E_CARD_SIMPLE_FIELD_URL,
- E_CARD_SIMPLE_FIELD_ORG_UNIT,
- E_CARD_SIMPLE_FIELD_OFFICE,
- E_CARD_SIMPLE_FIELD_TITLE,
- E_CARD_SIMPLE_FIELD_ROLE,
- E_CARD_SIMPLE_FIELD_MANAGER,
- E_CARD_SIMPLE_FIELD_ASSISTANT,
- E_CARD_SIMPLE_FIELD_NICKNAME,
- E_CARD_SIMPLE_FIELD_SPOUSE,
- E_CARD_SIMPLE_FIELD_NOTE,
- E_CARD_SIMPLE_FIELD_CALURI,
- E_CARD_SIMPLE_FIELD_FBURL,
- E_CARD_SIMPLE_FIELD_ICSCALENDAR,
- /* If you add after icscalendar, make sure to move LAST_SIMPLE_STRING */
- E_CARD_SIMPLE_FIELD_LAST_SIMPLE_STRING = E_CARD_SIMPLE_FIELD_ICSCALENDAR,
- E_CARD_SIMPLE_FIELD_ANNIVERSARY,
- E_CARD_SIMPLE_FIELD_BIRTH_DATE,
- E_CARD_SIMPLE_FIELD_MAILER,
- E_CARD_SIMPLE_FIELD_NAME_OR_ORG,
- E_CARD_SIMPLE_FIELD_CATEGORIES,
- E_CARD_SIMPLE_FIELD_FAMILY_NAME,
- E_CARD_SIMPLE_FIELD_GIVEN_NAME,
- E_CARD_SIMPLE_FIELD_ADDITIONAL_NAME,
- E_CARD_SIMPLE_FIELD_NAME_SUFFIX,
- E_CARD_SIMPLE_FIELD_WANTS_HTML,
- E_CARD_SIMPLE_FIELD_IS_LIST,
- E_CARD_SIMPLE_FIELD_LAST
-};
-
-typedef struct _ECardSimple ECardSimple;
-typedef struct _ECardSimpleClass ECardSimpleClass;
-
-struct _ECardSimple {
- GObject object;
- ECard *card;
-
- GList *temp_fields;
-
- ECardPhone *phone[E_CARD_SIMPLE_PHONE_ID_LAST];
- char *email[E_CARD_SIMPLE_EMAIL_ID_LAST];
- ECardAddrLabel *address[E_CARD_SIMPLE_ADDRESS_ID_LAST];
- ECardDeliveryAddress *delivery[E_CARD_SIMPLE_ADDRESS_ID_LAST];
-
- gboolean changed;
-};
-
-struct _ECardSimpleClass {
- GObjectClass parent_class;
-};
-
-typedef void (*ECardSimpleArbitraryCallback) (const ECardArbitrary *arbitrary, gpointer closure);
-ECardSimple *e_card_simple_new (ECard *card);
-const char *e_card_simple_get_id (ECardSimple *simple);
-void e_card_simple_set_id (ECardSimple *simple,
- const gchar *character);
-char *e_card_simple_get_vcard (ECardSimple *simple);
-char *e_card_simple_get_vcard_assume_utf8 (ECardSimple *simple);
-ECardSimple *e_card_simple_duplicate (ECardSimple *simple);
-char *e_card_simple_get (ECardSimple *simple,
- ECardSimpleField field);
-const char *e_card_simple_get_const (ECardSimple *simple,
- ECardSimpleField field);
-void e_card_simple_set (ECardSimple *simple,
- ECardSimpleField field,
- const char *data);
-ECardSimpleType e_card_simple_type (ECardSimple *simple,
- ECardSimpleField field);
-
-const char *e_card_simple_get_ecard_field (ECardSimple *simple,
- ECardSimpleField field);
-const char *e_card_simple_get_name (ECardSimple *simple,
- ECardSimpleField field);
-const char *e_card_simple_get_short_name (ECardSimple *simple,
- ECardSimpleField field);
-gboolean e_card_simple_get_allow_newlines (ECardSimple *simple,
- ECardSimpleField field);
-
-
-/* Use these only if building lists of specific types. It should be
- * easier to use the above if you consider a phone field to be the
- * same as any other field.
- */
-const ECardPhone *e_card_simple_get_phone (ECardSimple *simple,
- ECardSimplePhoneId id);
-const char *e_card_simple_get_email (ECardSimple *simple,
- ECardSimpleEmailId id);
-const ECardAddrLabel *e_card_simple_get_address (ECardSimple *simple,
- ECardSimpleAddressId id);
-const ECardDeliveryAddress *e_card_simple_get_delivery_address (ECardSimple *simple,
- ECardSimpleAddressId id);
-void e_card_simple_set_phone (ECardSimple *simple,
- ECardSimplePhoneId id,
- const ECardPhone *phone);
-void e_card_simple_set_email (ECardSimple *simple,
- ECardSimpleEmailId id,
- const char *email);
-void e_card_simple_set_address (ECardSimple *simple,
- ECardSimpleAddressId id,
- const ECardAddrLabel *address);
-void e_card_simple_set_delivery_address (ECardSimple *simple,
- ECardSimpleAddressId id,
- const ECardDeliveryAddress *delivery);
-void e_card_simple_arbitrary_foreach (ECardSimple *simple,
- ECardSimpleArbitraryCallback *callback,
- gpointer closure);
-const ECardArbitrary *e_card_simple_get_arbitrary (ECardSimple *simple,
- const char *key);
-/* Any of these except key can be NULL */
-void e_card_simple_set_arbitrary (ECardSimple *simple,
- const char *key,
- const char *type,
- const char *value);
-void e_card_simple_set_name (ECardSimple *simple,
- ECardName *name);
-void e_card_simple_sync_card (ECardSimple *simple);
-
-/* These map between the individual list types and ECardSimpleField */
-ECardSimpleField e_card_simple_map_phone_to_field (ECardSimplePhoneId phone_id);
-ECardSimpleField e_card_simple_map_email_to_field (ECardSimpleEmailId email_id);
-ECardSimpleField e_card_simple_map_address_to_field (ECardSimpleAddressId address_id);
-
-GType e_card_simple_get_type (void);
-
-#endif /* ! __E_CARD_SIMPLE_H__ */
-
-
diff --git a/addressbook/backend/ebook/e-card-types.h b/addressbook/backend/ebook/e-card-types.h
deleted file mode 100644
index 8d35c54924..0000000000
--- a/addressbook/backend/ebook/e-card-types.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors:
- * Arturo Espinosa
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 1999 The Free Software Foundation
- */
-
-#ifndef __E_CARD_TYPES_H__
-#define __E_CARD_TYPES_H__
-
-/* IDENTIFICATION PROPERTIES */
-
-typedef struct {
- gint ref_count;
- char *prefix; /* Mr. */
- char *given; /* John */
- char *additional; /* Quinlan */
- char *family; /* Public */
- char *suffix; /* Esq. */
-} ECardName;
-
-typedef struct {
- int year;
- int month;
- int day;
-} ECardDate;
-
-/* TELECOMMUNICATIONS ADDRESSING PROPERTIES */
-
-typedef enum {
- E_CARD_PHONE_PREF = 1 << 0,
- E_CARD_PHONE_WORK = 1 << 1,
- E_CARD_PHONE_HOME = 1 << 2,
- E_CARD_PHONE_VOICE = 1 << 3,
- E_CARD_PHONE_FAX = 1 << 4,
- E_CARD_PHONE_MSG = 1 << 5,
- E_CARD_PHONE_CELL = 1 << 6,
- E_CARD_PHONE_PAGER = 1 << 7,
- E_CARD_PHONE_BBS = 1 << 8,
- E_CARD_PHONE_MODEM = 1 << 9,
- E_CARD_PHONE_CAR = 1 << 10,
- E_CARD_PHONE_ISDN = 1 << 11,
- E_CARD_PHONE_VIDEO = 1 << 12,
- E_CARD_PHONE_ASSISTANT = 1 << 13,
- E_CARD_PHONE_CALLBACK = 1 << 14,
- E_CARD_PHONE_RADIO = 1 << 15,
- E_CARD_PHONE_TELEX = 1 << 16,
- E_CARD_PHONE_TTYTDD = 1 << 17,
-} ECardPhoneFlags;
-
-typedef struct {
- gint ref_count;
- ECardPhoneFlags flags;
- char *number;
-} ECardPhone;
-
-/* DELIVERY ADDRESSING PROPERTIES */
-
-typedef enum {
- E_CARD_ADDR_HOME = 1 << 0,
- E_CARD_ADDR_WORK = 1 << 1,
- E_CARD_ADDR_POSTAL = 1 << 2,
- E_CARD_ADDR_MASK = 7,
- E_CARD_ADDR_PARCEL = 1 << 3,
- E_CARD_ADDR_DOM = 1 << 4,
- E_CARD_ADDR_INTL = 1 << 5,
- E_CARD_ADDR_DEFAULT = 1 << 6
-} ECardAddressFlags;
-
-typedef struct {
- gint ref_count;
- ECardAddressFlags flags;
-
- char *po;
- char *ext;
- char *street;
- char *city;
- char *region;
- char *code;
- char *country;
-} ECardDeliveryAddress;
-
-typedef struct {
- gint ref_count;
- ECardAddressFlags flags;
- char *data;
-} ECardAddrLabel;
-
-/* ARBITRARY PROPERTIES */
-
-typedef struct {
- gint ref_count;
- char *key;
- char *type;
- char *value;
-} ECardArbitrary;
-
-#endif /* __E_CARD_TYPES_H__ */
diff --git a/addressbook/backend/ebook/e-card.c b/addressbook/backend/ebook/e-card.c
deleted file mode 100644
index 1b3bbfba88..0000000000
--- a/addressbook/backend/ebook/e-card.c
+++ /dev/null
@@ -1,2807 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors:
- * Arturo Espinosa (arturo@nuclecu.unam.mx)
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 1999 The Free Software Foundation
- */
-
-#include <config.h>
-
-#include "e-card.h"
-
-#include <gal/widgets/e-unicode.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <math.h>
-
-#include <bonobo/bonobo-i18n.h>
-#include <gal/util/e-util.h>
-
-#include <libversit/vcc.h>
-#include "e-util/ename/e-name-western.h"
-#include "e-util/ename/e-address-western.h"
-#include "e-book.h"
-
-#define is_a_prop_of(obj,prop) (isAPropertyOf ((obj),(prop)))
-#define str_val(obj) (the_str = (vObjectValueType (obj))? fakeCString (vObjectUStringZValue (obj)) : calloc (1, 1))
-#define has(obj,prop) (vo = isAPropertyOf ((obj), (prop)))
-
-#define XEV_WANTS_HTML "X-MOZILLA-HTML"
-#define XEV_ARBITRARY "X-EVOLUTION-ARBITRARY"
-#define XEV_LIST "X-EVOLUTION-LIST"
-#define XEV_LIST_SHOW_ADDRESSES "X-EVOLUTION-LIST-SHOW_ADDRESSES"
-#define XEV_RELATED_CONTACTS "X-EVOLUTION-RELATED_CONTACTS"
-
-/* Object property IDs */
-enum {
- PROP_0,
- PROP_FILE_AS,
- PROP_FULL_NAME,
- PROP_NAME,
- PROP_ADDRESS,
- PROP_ADDRESS_LABEL,
- PROP_PHONE,
- PROP_EMAIL,
- PROP_BIRTH_DATE,
- PROP_URL,
- PROP_ORG,
- PROP_ORG_UNIT,
- PROP_OFFICE,
- PROP_TITLE,
- PROP_ROLE,
- PROP_MANAGER,
- PROP_ASSISTANT,
- PROP_NICKNAME,
- PROP_SPOUSE,
- PROP_ANNIVERSARY,
- PROP_MAILER,
- PROP_CALURI,
- PROP_FBURL,
- PROP_ICSCALENDAR,
- PROP_NOTE,
- PROP_RELATED_CONTACTS,
- PROP_CATEGORIES,
- PROP_CATEGORY_LIST,
- PROP_WANTS_HTML,
- PROP_WANTS_HTML_SET,
- PROP_EVOLUTION_LIST,
- PROP_EVOLUTION_LIST_SHOW_ADDRESSES,
- PROP_ARBITRARY,
- PROP_ID,
- PROP_LAST_USE,
- PROP_USE_SCORE,
-};
-
-static GObjectClass *parent_class;
-
-static void parse(ECard *card, VObject *vobj, const char *default_charset);
-static void e_card_init (ECard *card);
-static void e_card_class_init (ECardClass *klass);
-
-static void e_card_dispose (GObject *object);
-static void e_card_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void e_card_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-
-static void assign_string(VObject *vobj, const char *default_charset, char **string);
-
-char *e_v_object_get_child_value(VObject *vobj, char *name, const char *default_charset);
-
-static void parse_bday(ECard *card, VObject *object, const char *default_charset);
-static void parse_full_name(ECard *card, VObject *object, const char *default_charset);
-static void parse_file_as(ECard *card, VObject *object, const char *default_charset);
-static void parse_name(ECard *card, VObject *object, const char *default_charset);
-static void parse_email(ECard *card, VObject *object, const char *default_charset);
-static void parse_phone(ECard *card, VObject *object, const char *default_charset);
-static void parse_address(ECard *card, VObject *object, const char *default_charset);
-static void parse_address_label(ECard *card, VObject *object, const char *default_charset);
-static void parse_url(ECard *card, VObject *object, const char *default_charset);
-static void parse_org(ECard *card, VObject *object, const char *default_charset);
-static void parse_office(ECard *card, VObject *object, const char *default_charset);
-static void parse_title(ECard *card, VObject *object, const char *default_charset);
-static void parse_role(ECard *card, VObject *object, const char *default_charset);
-static void parse_manager(ECard *card, VObject *object, const char *default_charset);
-static void parse_assistant(ECard *card, VObject *object, const char *default_charset);
-static void parse_nickname(ECard *card, VObject *object, const char *default_charset);
-static void parse_spouse(ECard *card, VObject *object, const char *default_charset);
-static void parse_anniversary(ECard *card, VObject *object, const char *default_charset);
-static void parse_mailer(ECard *card, VObject *object, const char *default_charset);
-static void parse_caluri(ECard *card, VObject *object, const char *default_charset);
-static void parse_fburl(ECard *card, VObject *object, const char *default_charset);
-static void parse_icscalendar(ECard *card, VObject *object, const char *default_charset);
-static void parse_note(ECard *card, VObject *object, const char *default_charset);
-static void parse_related_contacts(ECard *card, VObject *object, const char *default_charset);
-static void parse_categories(ECard *card, VObject *object, const char *default_charset);
-static void parse_wants_html(ECard *card, VObject *object, const char *default_charset);
-static void parse_list(ECard *card, VObject *object, const char *default_charset);
-static void parse_list_show_addresses(ECard *card, VObject *object, const char *default_charset);
-static void parse_arbitrary(ECard *card, VObject *object, const char *default_charset);
-static void parse_id(ECard *card, VObject *object, const char *default_charset);
-static void parse_last_use(ECard *card, VObject *object, const char *default_charset);
-static void parse_use_score(ECard *card, VObject *object, const char *default_charset);
-
-static ECardPhoneFlags get_phone_flags (VObject *vobj);
-static void set_phone_flags (VObject *vobj, ECardPhoneFlags flags);
-static ECardAddressFlags get_address_flags (VObject *vobj);
-static void set_address_flags (VObject *vobj, ECardAddressFlags flags);
-
-typedef void (* ParsePropertyFunc) (ECard *card, VObject *object, const char *default_charset);
-
-struct {
- char *key;
- ParsePropertyFunc function;
-} attribute_jump_array[] =
-{
- { VCFullNameProp, parse_full_name },
- { "X-EVOLUTION-FILE-AS", parse_file_as },
- { VCNameProp, parse_name },
- { VCBirthDateProp, parse_bday },
- { VCEmailAddressProp, parse_email },
- { VCTelephoneProp, parse_phone },
- { VCAdrProp, parse_address },
- { VCDeliveryLabelProp, parse_address_label },
- { VCURLProp, parse_url },
- { VCOrgProp, parse_org },
- { "X-EVOLUTION-OFFICE", parse_office },
- { VCTitleProp, parse_title },
- { VCBusinessRoleProp, parse_role },
- { "X-EVOLUTION-MANAGER", parse_manager },
- { "X-EVOLUTION-ASSISTANT", parse_assistant },
- { "NICKNAME", parse_nickname },
- { "X-EVOLUTION-SPOUSE", parse_spouse },
- { "X-EVOLUTION-ANNIVERSARY", parse_anniversary },
- { VCMailerProp, parse_mailer },
- { "CALURI", parse_caluri },
- { "FBURL", parse_fburl },
- { "ICSCALENDAR", parse_icscalendar },
- { VCNoteProp, parse_note },
- { XEV_RELATED_CONTACTS, parse_related_contacts },
- { "CATEGORIES", parse_categories },
- { XEV_WANTS_HTML, parse_wants_html },
- { XEV_ARBITRARY, parse_arbitrary },
- { VCUniqueStringProp, parse_id },
- { "X-EVOLUTION-LAST-USE", parse_last_use },
- { "X-EVOLUTION-USE-SCORE", parse_use_score },
- { XEV_LIST, parse_list },
- { XEV_LIST_SHOW_ADDRESSES, parse_list_show_addresses },
- { VCUniqueStringProp, parse_id }
-};
-
-/**
- * e_card_get_type:
- * @void:
- *
- * Registers the &ECard class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the &ECard class.
- **/
-GType
-e_card_get_type (void)
-{
- static GType card_type = 0;
-
- if (!card_type) {
- static const GTypeInfo card_info = {
- sizeof (ECardClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_card_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (ECard),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_card_init,
- };
-
- card_type = g_type_register_static (G_TYPE_OBJECT, "ECard", &card_info, 0);
- }
-
- return card_type;
-}
-
-ECard *
-e_card_new_with_default_charset (const char *vcard, const char *default_charset)
-{
- ECard *card = g_object_new (E_TYPE_CARD, NULL);
- VObject *vobj = Parse_MIME(vcard, strlen(vcard));
- while(vobj) {
- VObject *next;
- parse(card, vobj, default_charset);
- next = nextVObjectInList(vobj);
- cleanVObject(vobj);
- vobj = next;
- }
- if (card->name == NULL)
- card->name = e_card_name_new();
- if (card->file_as == NULL)
- card->file_as = g_strdup("");
- if (card->fname == NULL)
- card->fname = g_strdup("");
- return card;
-}
-
-/**
- * e_card_new:
- * @vcard: a string in vCard format
- *
- * Returns: a new #ECard that wraps the @vcard.
- */
-ECard *
-e_card_new (const char *vcard)
-{
- return e_card_new_with_default_charset (vcard, "UTF-8");
-}
-
-ECard *
-e_card_duplicate(ECard *card)
-{
- char *vcard = e_card_get_vcard_assume_utf8(card);
- ECard *new_card = e_card_new(vcard);
- g_free (vcard);
-
- if (card->book) {
- new_card->book = card->book;
- g_object_ref (new_card->book);
- }
-
- return new_card;
-}
-
-static void
-e_card_get_today (GDate *dt)
-{
- time_t now;
- struct tm *now_tm;
- if (dt == NULL)
- return;
-
- time (&now);
- now_tm = localtime (&now);
-
- g_date_set_dmy (dt, now_tm->tm_mday, now_tm->tm_mon + 1, now_tm->tm_year + 1900);
-}
-
-float
-e_card_get_use_score(ECard *card)
-{
- GDate today, last_use;
- gint days_since_last_use;
-
- g_return_val_if_fail (card != NULL && E_IS_CARD (card), 0);
-
- if (card->last_use == NULL)
- return 0.0;
-
- e_card_get_today (&today);
- g_date_set_dmy (&last_use, card->last_use->day, card->last_use->month, card->last_use->year);
-
- days_since_last_use = g_date_get_julian (&today) - g_date_get_julian (&last_use);
-
- /* Apply a seven-day "grace period" to the use score decay. */
- days_since_last_use -= 7;
- if (days_since_last_use < 0)
- days_since_last_use = 0;
-
- return MAX (card->raw_use_score, 0) * exp (- days_since_last_use / 30.0);
-}
-
-void
-e_card_touch(ECard *card)
-{
- GDate today;
- double use_score;
-
- g_return_if_fail (card != NULL && E_IS_CARD (card));
-
- e_card_get_today (&today);
- use_score = e_card_get_use_score (card);
-
- if (card->last_use == NULL)
- card->last_use = g_new (ECardDate, 1);
-
- card->last_use->day = g_date_get_day (&today);
- card->last_use->month = g_date_get_month (&today);
- card->last_use->year = g_date_get_year (&today);
-
- card->raw_use_score = use_score + 1.0;
-}
-
-/**
- * e_card_get_id:
- * @card: an #ECard
- *
- * Returns: a string representing the id of the card, which is unique
- * within its book.
- */
-const char *
-e_card_get_id (ECard *card)
-{
- g_return_val_if_fail (card && E_IS_CARD (card), NULL);
-
- return card->id ? card->id : "";
-}
-
-/**
- * e_card_get_id:
- * @card: an #ECard
- * @id: a id in string format
- *
- * Sets the identifier of a card, which should be unique within its
- * book.
- */
-void
-e_card_set_id (ECard *card, const char *id)
-{
- g_return_if_fail (card && E_IS_CARD (card));
-
- if ( card->id )
- g_free(card->id);
- card->id = g_strdup(id ? id : "");
-}
-
-EBook *
-e_card_get_book (ECard *card)
-{
- g_return_val_if_fail (card && E_IS_CARD (card), NULL);
-
- return card->book;
-}
-
-void
-e_card_set_book (ECard *card, EBook *book)
-{
- g_return_if_fail (card && E_IS_CARD (card));
-
- if (card->book)
- g_object_unref (card->book);
- card->book = book;
- if (card->book)
- g_object_ref (card->book);
-}
-
-gchar *
-e_card_date_to_string (ECardDate *dt)
-{
- if (dt)
- return g_strdup_printf ("%04d-%02d-%02d",
- CLAMP(dt->year, 1000, 9999),
- CLAMP(dt->month, 1, 12),
- CLAMP(dt->day, 1, 31));
- else
- return NULL;
-}
-
-static VObject *
-addPropValueUTF8(VObject *o, const char *p, const char *v)
-{
- VObject *prop = addPropValue (o, p, v);
- for (; *v; v++) {
- if ((*v) & 0x80) {
- addPropValue (prop, "CHARSET", "UTF-8");
- addProp(prop, VCQuotedPrintableProp);
-
- return prop;
- }
- if (*v == '\n') {
- addProp(prop, VCQuotedPrintableProp);
- for (; *v; v++) {
- if ((*v) & 0x80) {
- addPropValue (prop, "CHARSET", "UTF-8");
- return prop;
- }
- }
- return prop;
- }
- }
- return prop;
-}
-
-static VObject *
-addPropValueQP(VObject *o, const char *p, const char *v)
-{
- VObject *prop = addPropValue (o, p, v);
- for (; *v; v++) {
- if (*v == '\n') {
- addProp(prop, VCQuotedPrintableProp);
- break;
- }
- }
- return prop;
-}
-
-static void
-addPropValueSets (VObject *o, const char *p, const char *v, gboolean assumeUTF8, gboolean *is_ascii, gboolean *has_return)
-{
- addPropValue (o, p, v);
- if (*has_return && (assumeUTF8 || !*is_ascii))
- return;
- if (*has_return) {
- for (; *v; v++) {
- if (*v & 0x80) {
- *is_ascii = FALSE;
- return;
- }
- }
- return;
- }
- if (assumeUTF8 || !*is_ascii) {
- for (; *v; v++) {
- if (*v == '\n') {
- *has_return = TRUE;
- return;
- }
- }
- return;
- }
- for (; *v; v++) {
- if (*v & 0x80) {
- *is_ascii = FALSE;
- for (; *v; v++) {
- if (*v == '\n') {
- *has_return = TRUE;
- return;
- }
- }
- return;
- }
- if (*v == '\n') {
- *has_return = TRUE;
- for (; *v; v++) {
- if (*v & 0x80) {
- *is_ascii = FALSE;
- return;
- }
- }
- return;
- }
- }
- return;
-}
-
-#define ADD_PROP_VALUE(o, p, v) (assumeUTF8 ? (addPropValueQP ((o), (p), (v))) : addPropValueUTF8 ((o), (p), (v)))
-#define ADD_PROP_VALUE_SET_IS_ASCII(o, p, v) (addPropValueSets ((o), (p), (v), assumeUTF8, &is_ascii, &has_return))
-
-
-static VObject *
-e_card_get_vobject (const ECard *card, gboolean assumeUTF8)
-{
- VObject *vobj;
-
- vobj = newVObject (VCCardProp);
-
- ADD_PROP_VALUE(vobj, VCVersionProp, "2.1");
-
- if (card->file_as && *card->file_as)
- ADD_PROP_VALUE(vobj, "X-EVOLUTION-FILE-AS", card->file_as);
- else if (card->file_as)
- addProp(vobj, "X-EVOLUTION-FILE_AS");
-
- if (card->fname && *card->fname)
- ADD_PROP_VALUE(vobj, VCFullNameProp, card->fname);
- else if (card->fname)
- addProp(vobj, VCFullNameProp);
-
- if ( card->name && (card->name->prefix || card->name->given || card->name->additional || card->name->family || card->name->suffix) ) {
- VObject *nameprop;
- gboolean is_ascii = TRUE;
- gboolean has_return = FALSE;
- nameprop = addProp(vobj, VCNameProp);
- if ( card->name->prefix )
- ADD_PROP_VALUE_SET_IS_ASCII(nameprop, VCNamePrefixesProp, card->name->prefix);
- if ( card->name->given )
- ADD_PROP_VALUE_SET_IS_ASCII(nameprop, VCGivenNameProp, card->name->given);
- if ( card->name->additional )
- ADD_PROP_VALUE_SET_IS_ASCII(nameprop, VCAdditionalNamesProp, card->name->additional);
- if ( card->name->family )
- ADD_PROP_VALUE_SET_IS_ASCII(nameprop, VCFamilyNameProp, card->name->family);
- if ( card->name->suffix )
- ADD_PROP_VALUE_SET_IS_ASCII(nameprop, VCNameSuffixesProp, card->name->suffix);
- if (has_return)
- addProp(nameprop, VCQuotedPrintableProp);
- if (!(is_ascii || assumeUTF8))
- addPropValue (nameprop, "CHARSET", "UTF-8");
- }
- else if (card->name)
- addProp(vobj, VCNameProp);
-
-
- if ( card->address ) {
- EIterator *iterator = e_list_get_iterator(card->address);
- for ( ; e_iterator_is_valid(iterator) ;e_iterator_next(iterator) ) {
- VObject *addressprop;
- ECardDeliveryAddress *address = (ECardDeliveryAddress *) e_iterator_get(iterator);
- gboolean is_ascii = TRUE;
- gboolean has_return = FALSE;
-
- addressprop = addProp(vobj, VCAdrProp);
-
- set_address_flags (addressprop, address->flags);
- if (address->po)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCPostalBoxProp, address->po);
- if (address->ext)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCExtAddressProp, address->ext);
- if (address->street)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCStreetAddressProp, address->street);
- if (address->city)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCCityProp, address->city);
- if (address->region)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCRegionProp, address->region);
- if (address->code)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCPostalCodeProp, address->code);
- if (address->country)
- ADD_PROP_VALUE_SET_IS_ASCII(addressprop, VCCountryNameProp, address->country);
-
- if (has_return)
- addProp(addressprop, VCQuotedPrintableProp);
- if (!(is_ascii || assumeUTF8))
- addPropValue (addressprop, "CHARSET", "UTF-8");
- }
- g_object_unref(iterator);
- }
-
- if ( card->address_label ) {
- EIterator *iterator = e_list_get_iterator(card->address_label);
- for ( ; e_iterator_is_valid(iterator) ;e_iterator_next(iterator) ) {
- VObject *labelprop;
- ECardAddrLabel *address_label = (ECardAddrLabel *) e_iterator_get(iterator);
- if (address_label->data)
- labelprop = ADD_PROP_VALUE(vobj, VCDeliveryLabelProp, address_label->data);
- else
- labelprop = addProp(vobj, VCDeliveryLabelProp);
-
- set_address_flags (labelprop, address_label->flags);
- }
- g_object_unref(iterator);
- }
-
- if ( card->phone ) {
- EIterator *iterator = e_list_get_iterator(card->phone);
- for ( ; e_iterator_is_valid(iterator) ;e_iterator_next(iterator) ) {
- VObject *phoneprop;
- ECardPhone *phone = (ECardPhone *) e_iterator_get(iterator);
- phoneprop = ADD_PROP_VALUE(vobj, VCTelephoneProp, phone->number);
-
- set_phone_flags (phoneprop, phone->flags);
- }
- g_object_unref(iterator);
- }
-
- if ( card->email ) {
- EIterator *iterator = e_list_get_iterator(card->email);
- for ( ; e_iterator_is_valid(iterator) ;e_iterator_next(iterator) ) {
- VObject *emailprop;
- emailprop = ADD_PROP_VALUE(vobj, VCEmailAddressProp, (char *) e_iterator_get(iterator));
- addProp (emailprop, VCInternetProp);
- }
- g_object_unref(iterator);
- }
-
- if ( card->bday ) {
- char *value;
- value = e_card_date_to_string (card->bday);
- ADD_PROP_VALUE(vobj, VCBirthDateProp, value);
- g_free(value);
- }
-
- if (card->url)
- ADD_PROP_VALUE(vobj, VCURLProp, card->url);
-
- if (card->org || card->org_unit) {
- VObject *orgprop;
- gboolean is_ascii = TRUE;
- gboolean has_return = FALSE;
- orgprop = addProp(vobj, VCOrgProp);
-
- if (card->org)
- ADD_PROP_VALUE_SET_IS_ASCII(orgprop, VCOrgNameProp, card->org);
- if (card->org_unit)
- ADD_PROP_VALUE_SET_IS_ASCII(orgprop, VCOrgUnitProp, card->org_unit);
-
- if (has_return)
- addProp(orgprop, VCQuotedPrintableProp);
- if (!(is_ascii || assumeUTF8))
- addPropValue (orgprop, "CHARSET", "UTF-8");
- }
-
- if (card->office)
- ADD_PROP_VALUE(vobj, "X-EVOLUTION-OFFICE", card->office);
-
- if (card->title)
- ADD_PROP_VALUE(vobj, VCTitleProp, card->title);
-
- if (card->role)
- ADD_PROP_VALUE(vobj, VCBusinessRoleProp, card->role);
-
- if (card->manager)
- ADD_PROP_VALUE(vobj, "X-EVOLUTION-MANAGER", card->manager);
-
- if (card->assistant)
- ADD_PROP_VALUE(vobj, "X-EVOLUTION-ASSISTANT", card->assistant);
-
- if (card->nickname)
- ADD_PROP_VALUE(vobj, "NICKNAME", card->nickname);
-
- if (card->spouse)
- ADD_PROP_VALUE(vobj, "X-EVOLUTION-SPOUSE", card->spouse);
-
- if ( card->anniversary ) {
- char *value;
- value = e_card_date_to_string (card->anniversary);
- ADD_PROP_VALUE(vobj, "X-EVOLUTION-ANNIVERSARY", value);
- g_free(value);
- }
-
- if (card->mailer) {
- ADD_PROP_VALUE(vobj, VCMailerProp, card->mailer);
- }
-
- if (card->caluri)
- addPropValueQP(vobj, "CALURI", card->caluri);
-
- if (card->fburl)
- ADD_PROP_VALUE(vobj, "FBURL", card->fburl);
-
- if (card->icscalendar)
- ADD_PROP_VALUE(vobj, "ICSCALENDAR", card->icscalendar);
-
- if (card->note) {
- VObject *noteprop;
-
- noteprop = ADD_PROP_VALUE(vobj, VCNoteProp, card->note);
- }
-
- if (card->last_use) {
- char *value;
- value = e_card_date_to_string (card->last_use);
- ADD_PROP_VALUE (vobj, "X-EVOLUTION-LAST-USE", value);
- g_free (value);
- }
-
- if (card->raw_use_score > 0) {
- char *value;
- value = g_strdup_printf ("%f", card->raw_use_score);
- ADD_PROP_VALUE (vobj, "X-EVOLUTION-USE-SCORE", value);
- g_free (value);
- }
-
- if (card->related_contacts && *card->related_contacts) {
- ADD_PROP_VALUE(vobj, XEV_RELATED_CONTACTS, card->related_contacts);
- }
-
- if (card->categories) {
- EIterator *iterator;
- int length = 0;
- char *string;
- char *stringptr;
- for (iterator = e_list_get_iterator(card->categories); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- length += strlen(e_iterator_get(iterator)) + 1;
- }
- string = g_new(char, length + 1);
- stringptr = string;
- *stringptr = 0;
- for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- strcpy(stringptr, e_iterator_get(iterator));
- stringptr += strlen(stringptr);
- *stringptr = ',';
- stringptr++;
- *stringptr = 0;
- }
- if (stringptr > string) {
- stringptr --;
- *stringptr = 0;
- }
- ADD_PROP_VALUE (vobj, "CATEGORIES", string);
- g_free(string);
- }
-
- if (card->wants_html_set) {
- ADD_PROP_VALUE (vobj, XEV_WANTS_HTML, card->wants_html ? "TRUE" : "FALSE");
- }
-
- if (card->list) {
- ADD_PROP_VALUE (vobj, XEV_LIST, "TRUE");
- ADD_PROP_VALUE (vobj, XEV_LIST_SHOW_ADDRESSES, card->list_show_addresses ? "TRUE" : "FALSE");
- }
-
- if (card->arbitrary) {
- EIterator *iterator;
- for (iterator = e_list_get_iterator(card->arbitrary); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- const ECardArbitrary *arbitrary = e_iterator_get(iterator);
- VObject *arb_object;
- if (arbitrary->value) {
- arb_object = ADD_PROP_VALUE (vobj, XEV_ARBITRARY, arbitrary->value);
- } else {
- arb_object = addProp (vobj, XEV_ARBITRARY);
- }
- if (arbitrary->type) {
- ADD_PROP_VALUE (arb_object, "TYPE", arbitrary->type);
- }
- if (arbitrary->key) {
- addProp (arb_object, arbitrary->key);
- }
- }
- }
-
- addPropValueQP (vobj, VCUniqueStringProp, (card->id ? card->id : ""));
-
- return vobj;
-}
-
-/**
- * e_card_get_vcard:
- * @card: an #ECard
- *
- * Returns: a string in vCard format, which is wrapped by the @card.
- */
-char *
-e_card_get_vcard (ECard *card)
-{
- VObject *vobj;
- char *temp, *ret_val;
-
- vobj = e_card_get_vobject (card, FALSE);
- temp = writeMemVObject(NULL, NULL, vobj);
- ret_val = g_strdup(temp);
- free(temp);
- cleanVObject(vobj);
- return ret_val;
-}
-
-char *
-e_card_get_vcard_assume_utf8 (ECard *card)
-{
- VObject *vobj;
- char *temp, *ret_val;
-
- vobj = e_card_get_vobject (card, TRUE);
- temp = writeMemVObject(NULL, NULL, vobj);
- ret_val = g_strdup(temp);
- free(temp);
- cleanVObject(vobj);
- return ret_val;
-}
-
-/**
- * e_card_list_get_vcard:
- * @list: a list of #ECards
- *
- * Returns: a string in vCard format.
- */
-char *
-e_card_list_get_vcard (const GList *list)
-{
- VObject *vobj;
-
- char *temp, *ret_val;
-
- vobj = NULL;
-
- for (; list; list = list->next) {
- VObject *tempvobj;
- ECard *card = list->data;
-
- tempvobj = e_card_get_vobject (card, FALSE);
- addList (&vobj, tempvobj);
- }
- temp = writeMemVObjects(NULL, NULL, vobj);
- ret_val = g_strdup(temp);
- free(temp);
- cleanVObjects(vobj);
- return ret_val;
-}
-
-static void
-parse_file_as(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->file_as )
- g_free(card->file_as);
- assign_string(vobj, default_charset, &(card->file_as));
-}
-
-static void
-parse_name(ECard *card, VObject *vobj, const char *default_charset)
-{
- e_card_name_unref(card->name);
-
- card->name = e_card_name_new();
-
- card->name->family = e_v_object_get_child_value (vobj, VCFamilyNameProp, default_charset);
- card->name->given = e_v_object_get_child_value (vobj, VCGivenNameProp, default_charset);
- card->name->additional = e_v_object_get_child_value (vobj, VCAdditionalNamesProp, default_charset);
- card->name->prefix = e_v_object_get_child_value (vobj, VCNamePrefixesProp, default_charset);
- card->name->suffix = e_v_object_get_child_value (vobj, VCNameSuffixesProp, default_charset);
-}
-
-static void
-parse_full_name(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->fname )
- g_free(card->fname);
- assign_string(vobj, default_charset, &(card->fname));
-}
-
-static void
-parse_email(ECard *card, VObject *vobj, const char *default_charset)
-{
- char *next_email;
- EList *list;
-
- assign_string(vobj, default_charset, &next_email);
- g_object_get(card,
- "email", &list,
- NULL);
- e_list_append(list, next_email);
- g_free (next_email);
- g_object_unref(list);
-}
-
-/* Deal with charset */
-static void
-parse_bday(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- if ( card->bday )
- g_free(card->bday);
- card->bday = g_new(ECardDate, 1);
- *(card->bday) = e_card_date_from_string(str);
- free(str);
- }
-}
-
-static void
-parse_phone(ECard *card, VObject *vobj, const char *default_charset)
-{
- ECardPhone *next_phone = e_card_phone_new ();
- EList *list;
-
- assign_string(vobj, default_charset, &(next_phone->number));
- next_phone->flags = get_phone_flags(vobj);
-
- g_object_get(card,
- "phone", &list,
- NULL);
- e_list_append(list, next_phone);
- e_card_phone_unref (next_phone);
- g_object_unref(list);
-}
-
-static void
-parse_address(ECard *card, VObject *vobj, const char *default_charset)
-{
- ECardDeliveryAddress *next_addr = e_card_delivery_address_new ();
- EList *list;
-
- next_addr->flags = get_address_flags (vobj);
- next_addr->po = e_v_object_get_child_value (vobj, VCPostalBoxProp, default_charset);
- next_addr->ext = e_v_object_get_child_value (vobj, VCExtAddressProp, default_charset);
- next_addr->street = e_v_object_get_child_value (vobj, VCStreetAddressProp, default_charset);
- next_addr->city = e_v_object_get_child_value (vobj, VCCityProp, default_charset);
- next_addr->region = e_v_object_get_child_value (vobj, VCRegionProp, default_charset);
- next_addr->code = e_v_object_get_child_value (vobj, VCPostalCodeProp, default_charset);
- next_addr->country = e_v_object_get_child_value (vobj, VCCountryNameProp, default_charset);
-
- g_object_get(card,
- "address", &list,
- NULL);
- e_list_append(list, next_addr);
- e_card_delivery_address_unref (next_addr);
- g_object_unref(list);
-}
-
-static void
-parse_address_label(ECard *card, VObject *vobj, const char *default_charset)
-{
- ECardAddrLabel *next_addr = e_card_address_label_new ();
- EList *list;
-
- next_addr->flags = get_address_flags (vobj);
- assign_string(vobj, default_charset, &next_addr->data);
-
- g_object_get(card,
- "address_label", &list,
- NULL);
- e_list_append(list, next_addr);
- e_card_address_label_unref (next_addr);
- g_object_unref(list);
-}
-
-static void
-parse_url(ECard *card, VObject *vobj, const char *default_charset)
-{
- if (card->url)
- g_free(card->url);
- assign_string(vobj, default_charset, &(card->url));
-}
-
-static void
-parse_org(ECard *card, VObject *vobj, const char *default_charset)
-{
- char *temp;
-
- temp = e_v_object_get_child_value(vobj, VCOrgNameProp, default_charset);
- g_free(card->org);
- card->org = temp;
-
- temp = e_v_object_get_child_value(vobj, VCOrgUnitProp, default_charset);
- g_free(card->org_unit);
- card->org_unit = temp;
-}
-
-static void
-parse_office(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->office )
- g_free(card->office);
- assign_string(vobj, default_charset, &(card->office));
-}
-
-static void
-parse_title(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->title )
- g_free(card->title);
- assign_string(vobj, default_charset, &(card->title));
-}
-
-static void
-parse_role(ECard *card, VObject *vobj, const char *default_charset)
-{
- if (card->role)
- g_free(card->role);
- assign_string(vobj, default_charset, &(card->role));
-}
-
-static void
-parse_manager(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->manager )
- g_free(card->manager);
- assign_string(vobj, default_charset, &(card->manager));
-}
-
-static void
-parse_assistant(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->assistant )
- g_free(card->assistant);
- assign_string(vobj, default_charset, &(card->assistant));
-}
-
-static void
-parse_nickname(ECard *card, VObject *vobj, const char *default_charset)
-{
- if (card->nickname)
- g_free(card->nickname);
- assign_string(vobj, default_charset, &(card->nickname));
-}
-
-static void
-parse_spouse(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->spouse )
- g_free(card->spouse);
- assign_string(vobj, default_charset, &(card->spouse));
-}
-
-/* Deal with charset */
-static void
-parse_anniversary(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- if (card->anniversary)
- g_free(card->anniversary);
- card->anniversary = g_new(ECardDate, 1);
- *(card->anniversary) = e_card_date_from_string(str);
- free(str);
- }
-}
-
-static void
-parse_mailer(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( card->mailer )
- g_free(card->mailer);
- assign_string(vobj, default_charset, &(card->mailer));
-}
-
-static void
-parse_caluri(ECard *card, VObject *vobj, const char *default_charset)
-{
- g_free(card->caluri);
- assign_string(vobj, default_charset, &(card->caluri));
-}
-
-static void
-parse_fburl(ECard *card, VObject *vobj, const char *default_charset)
-{
- g_free(card->fburl);
- assign_string(vobj, default_charset, &(card->fburl));
-}
-
-static void
-parse_icscalendar(ECard *card, VObject *vobj, const char *default_charset)
-{
- g_free(card->icscalendar);
- assign_string(vobj, default_charset, &(card->icscalendar));
-}
-
-static void
-parse_note(ECard *card, VObject *vobj, const char *default_charset)
-{
- g_free(card->note);
- assign_string(vobj, default_charset, &(card->note));
-}
-
-static void
-parse_related_contacts(ECard *card, VObject *vobj, const char *default_charset)
-{
- g_free(card->related_contacts);
- assign_string(vobj, default_charset, &(card->related_contacts));
-}
-
-static void
-add_list_unique(ECard *card, EList *list, char *string)
-{
- char *temp = e_strdup_strip(string);
- EIterator *iterator;
-
- if (!*temp) {
- g_free(temp);
- return;
- }
- for ( iterator = e_list_get_iterator(list); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- if (!strcmp(e_iterator_get(iterator), temp)) {
- break;
- }
- }
- if (!e_iterator_is_valid(iterator)) {
- e_list_append(list, temp);
- }
- g_free(temp);
- g_object_unref(iterator);
-}
-
-static void
-do_parse_categories(ECard *card, char *str)
-{
- int length = strlen(str);
- char *copy = g_new(char, length + 1);
- int i, j;
- EList *list;
- g_object_get(card,
- "category_list", &list,
- NULL);
- for (i = 0, j = 0; str[i]; i++, j++) {
- switch (str[i]) {
- case '\\':
- i++;
- if (str[i]) {
- copy[j] = str[i];
- } else
- i--;
- break;
- case ',':
- copy[j] = 0;
- add_list_unique(card, list, copy);
- j = -1;
- break;
- default:
- copy[j] = str[i];
- break;
- }
- }
- copy[j] = 0;
- add_list_unique(card, list, copy);
- g_object_unref(list);
- g_free(copy);
-}
-
-/* Deal with charset */
-static void
-parse_categories(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- do_parse_categories(card, str);
- free(str);
- }
-}
-
-/* Deal with charset */
-static void
-parse_wants_html(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- if (!strcasecmp(str, "true")) {
- card->wants_html = TRUE;
- card->wants_html_set = TRUE;
- }
- if (!strcasecmp(str, "false")) {
- card->wants_html = FALSE;
- card->wants_html_set = TRUE;
- }
- free(str);
- }
-}
-
-/* Deal with charset */
-static void
-parse_list(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- if (!strcasecmp(str, "true")) {
- card->list = TRUE;
- }
- if (!strcasecmp(str, "false")) {
- card->list = FALSE;
- }
- free(str);
- }
-}
-
-/* Deal with charset */
-static void
-parse_list_show_addresses(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- if (!strcasecmp(str, "true")) {
- card->list_show_addresses = TRUE;
- }
- if (!strcasecmp(str, "false")) {
- card->list_show_addresses = FALSE;
- }
- free(str);
- }
-}
-
-typedef union ValueItem {
- const char *strs;
- const wchar_t *ustrs;
- unsigned int i;
- unsigned long l;
- void *any;
- VObject *vobj;
-} ValueItem;
-
-struct VObject {
- VObject *next;
- const char *id;
- VObject *prop;
- unsigned short valType;
- ValueItem val;
-};
-
-static void
-parse_arbitrary(ECard *card, VObject *vobj, const char *default_charset)
-{
- ECardArbitrary *arbitrary = e_card_arbitrary_new();
- VObjectIterator iterator;
- EList *list;
- for ( initPropIterator (&iterator, vobj); moreIteration(&iterator); ) {
- VObject *temp = nextVObject(&iterator);
- const char *name = vObjectName(temp);
- if (name && !strcmp(name, "TYPE")) {
- g_free(arbitrary->type);
- assign_string(temp, default_charset, &(arbitrary->type));
- } else {
- g_free(arbitrary->key);
- arbitrary->key = g_strdup(name);
- }
- }
-
- assign_string(vobj, default_charset, &(arbitrary->value));
-
- g_object_get(card,
- "arbitrary", &list,
- NULL);
- e_list_append(list, arbitrary);
- e_card_arbitrary_unref(arbitrary);
- g_object_unref(list);
-}
-
-static void
-parse_id(ECard *card, VObject *vobj, const char *default_charset)
-{
- g_free(card->id);
- assign_string(vobj, default_charset, &(card->id));
-}
-
-/* Deal with charset */
-static void
-parse_last_use(ECard *card, VObject *vobj, const char *default_charset)
-{
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- g_free(card->last_use);
- card->last_use = g_new(ECardDate, 1);
- *(card->last_use) = e_card_date_from_string(str);
- free(str);
- }
-}
-
-/* Deal with charset */
-static void
-parse_use_score(ECard *card, VObject *vobj, const char *default_charset)
-{
- card->raw_use_score = 0;
-
- if ( vObjectValueType (vobj) ) {
- char *str = fakeCString (vObjectUStringZValue (vobj));
- card->raw_use_score = MAX(0, atof (str));
- free (str);
- }
-}
-
-static void
-parse_attribute(ECard *card, VObject *vobj, const char *default_charset)
-{
- ParsePropertyFunc function = g_hash_table_lookup(E_CARD_GET_CLASS(card)->attribute_jump_table, vObjectName(vobj));
- if ( function )
- function(card, vobj, default_charset);
-}
-
-static void
-parse(ECard *card, VObject *vobj, const char *default_charset)
-{
- VObjectIterator iterator;
- initPropIterator(&iterator, vobj);
- while(moreIteration (&iterator)) {
- parse_attribute(card, nextVObject(&iterator), default_charset);
- }
- if (!card->fname) {
- card->fname = g_strdup("");
- }
- if (!card->name) {
- card->name = e_card_name_from_string(card->fname);
- }
- if (!card->file_as) {
- ECardName *name = card->name;
- char *strings[3], **stringptr;
- char *string;
- stringptr = strings;
- if (name->family && *name->family)
- *(stringptr++) = name->family;
- if (name->given && *name->given)
- *(stringptr++) = name->given;
- *stringptr = NULL;
- string = g_strjoinv(", ", strings);
- card->file_as = string;
- }
-}
-
-static void
-e_card_class_init (ECardClass *klass)
-{
- int i;
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS(klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- klass->attribute_jump_table = g_hash_table_new(g_str_hash, g_str_equal);
-
- for ( i = 0; i < sizeof(attribute_jump_array) / sizeof(attribute_jump_array[0]); i++ ) {
- g_hash_table_insert(klass->attribute_jump_table, attribute_jump_array[i].key, attribute_jump_array[i].function);
- }
-
- object_class->dispose = e_card_dispose;
- object_class->get_property = e_card_get_property;
- object_class->set_property = e_card_set_property;
-
- g_object_class_install_property (object_class, PROP_FILE_AS,
- g_param_spec_string ("file_as",
- _("File As"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_FULL_NAME,
- g_param_spec_string ("full_name",
- _("Full Name"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_NAME,
- g_param_spec_pointer ("name",
- _("Name"),
- /*_( */"XXX blurb" /*)*/,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ADDRESS,
- g_param_spec_object ("address",
- _("Address"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_LIST,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_ADDRESS_LABEL,
- g_param_spec_object ("address_label",
- _("Address Label"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_LIST,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_PHONE,
- g_param_spec_object ("phone",
- _("Phone"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_LIST,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_EMAIL,
- g_param_spec_object ("email",
- _("Email"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_LIST,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_BIRTH_DATE,
- g_param_spec_pointer ("birth_date",
- _("Birth date"),
- /*_( */"XXX blurb" /*)*/,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_URL,
- g_param_spec_string ("url",
- _("URL"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ORG,
- g_param_spec_string ("org",
- _("Organization"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ORG_UNIT,
- g_param_spec_string ("org_unit",
- _("Organizational Unit"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_OFFICE,
- g_param_spec_string ("office",
- _("Office"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_TITLE,
- g_param_spec_string ("title",
- _("Title"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ROLE,
- g_param_spec_string ("role",
- _("Role"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_MANAGER,
- g_param_spec_string ("manager",
- _("Manager"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ASSISTANT,
- g_param_spec_string ("assistant",
- _("Assistant"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_NICKNAME,
- g_param_spec_string ("nickname",
- _("Nickname"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_SPOUSE,
- g_param_spec_string ("spouse",
- _("Spouse"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ANNIVERSARY,
- g_param_spec_pointer ("anniversary",
- _("Anniversary"),
- /*_( */"XXX blurb" /*)*/,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_MAILER,
- g_param_spec_string ("mailer",
- _("Mailer"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_CALURI,
- g_param_spec_string ("caluri",
- _("Calendar URI"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_FBURL,
- g_param_spec_string ("fburl",
- _("Free/Busy URL"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ICSCALENDAR,
- g_param_spec_string ("icscalendar",
- _("ICS Calendar"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_NOTE,
- g_param_spec_string ("note",
- _("Note"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_RELATED_CONTACTS,
- g_param_spec_string ("related_contacts",
- _("Related Contacts"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_CATEGORIES,
- g_param_spec_string ("categories",
- _("Categories"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_CATEGORY_LIST,
- g_param_spec_object ("category list",
- _("Category List"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_LIST,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_WANTS_HTML,
- g_param_spec_boolean ("wants_html",
- _("Wants HTML"),
- /*_( */"XXX blurb" /*)*/,
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_WANTS_HTML_SET,
- g_param_spec_boolean ("wants_html_set",
- _("Wants HTML set"),
- /*_( */"XXX blurb" /*)*/,
- FALSE,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_EVOLUTION_LIST,
- g_param_spec_boolean ("list",
- _("List"),
- /*_( */"XXX blurb" /*)*/,
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_EVOLUTION_LIST_SHOW_ADDRESSES,
- g_param_spec_boolean ("list_show_addresses",
- _("List Show Addresses"),
- /*_( */"XXX blurb" /*)*/,
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ARBITRARY,
- g_param_spec_object ("arbitrary",
- _("Arbitrary"),
- /*_( */"XXX blurb" /*)*/,
- E_TYPE_LIST,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ID,
- g_param_spec_string ("id",
- _("ID"),
- /*_( */"XXX blurb" /*)*/,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_LAST_USE,
- g_param_spec_pointer ("last_use",
- _("Last Use"),
- /*_( */"XXX blurb" /*)*/,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_USE_SCORE,
- /* XXX at some point we
- should remove
- LAX_VALIDATION and figure
- out some hard min & max
- scores. */
- g_param_spec_float ("use_score",
- _("Use Score"),
- /*_( */"XXX blurb" /*)*/,
- 0.0,
- 0.0,
- 0.0,
- G_PARAM_READWRITE | G_PARAM_LAX_VALIDATION));
-}
-
-ECardPhone *
-e_card_phone_new (void)
-{
- ECardPhone *newphone = g_new(ECardPhone, 1);
-
- newphone->ref_count = 1;
- newphone->number = NULL;
- newphone->flags = 0;
-
- return newphone;
-}
-
-void
-e_card_phone_unref (ECardPhone *phone)
-{
- if (phone) {
- phone->ref_count --;
- if (phone->ref_count == 0) {
- g_free(phone->number);
- g_free(phone);
- }
- }
-}
-
-ECardPhone *
-e_card_phone_ref (const ECardPhone *phone)
-{
- ECardPhone *phone_mutable = (ECardPhone *) phone;
- if (phone_mutable)
- phone_mutable->ref_count ++;
- return phone_mutable;
-}
-
-ECardPhone *
-e_card_phone_copy (const ECardPhone *phone)
-{
- if ( phone ) {
- ECardPhone *phone_copy = e_card_phone_new();
- phone_copy->number = g_strdup(phone->number);
- phone_copy->flags = phone->flags;
- return phone_copy;
- } else
- return NULL;
-}
-
-ECardDeliveryAddress *
-e_card_delivery_address_new (void)
-{
- ECardDeliveryAddress *newaddr = g_new(ECardDeliveryAddress, 1);
-
- newaddr->ref_count = 1;
- newaddr->po = NULL;
- newaddr->ext = NULL;
- newaddr->street = NULL;
- newaddr->city = NULL;
- newaddr->region = NULL;
- newaddr->code = NULL;
- newaddr->country = NULL;
- newaddr->flags = 0;
-
- return newaddr;
-}
-
-void
-e_card_delivery_address_unref (ECardDeliveryAddress *addr)
-{
- if ( addr ) {
- addr->ref_count --;
- if (addr->ref_count == 0) {
- g_free(addr->po);
- g_free(addr->ext);
- g_free(addr->street);
- g_free(addr->city);
- g_free(addr->region);
- g_free(addr->code);
- g_free(addr->country);
- g_free(addr);
- }
- }
-}
-
-ECardDeliveryAddress *
-e_card_delivery_address_ref (const ECardDeliveryAddress *addr)
-{
- ECardDeliveryAddress *addr_mutable = (ECardDeliveryAddress *) addr;
- if (addr_mutable)
- addr_mutable->ref_count ++;
- return addr_mutable;
-}
-
-ECardDeliveryAddress *
-e_card_delivery_address_copy (const ECardDeliveryAddress *addr)
-{
- if ( addr ) {
- ECardDeliveryAddress *addr_copy = e_card_delivery_address_new ();
- addr_copy->po = g_strdup(addr->po );
- addr_copy->ext = g_strdup(addr->ext );
- addr_copy->street = g_strdup(addr->street );
- addr_copy->city = g_strdup(addr->city );
- addr_copy->region = g_strdup(addr->region );
- addr_copy->code = g_strdup(addr->code );
- addr_copy->country = g_strdup(addr->country);
- addr_copy->flags = addr->flags;
- return addr_copy;
- } else
- return NULL;
-}
-
-gboolean
-e_card_delivery_address_is_empty (const ECardDeliveryAddress *addr)
-{
- return (((addr->po == NULL) || (*addr->po == 0)) &&
- ((addr->ext == NULL) || (*addr->ext == 0)) &&
- ((addr->street == NULL) || (*addr->street == 0)) &&
- ((addr->city == NULL) || (*addr->city == 0)) &&
- ((addr->region == NULL) || (*addr->region == 0)) &&
- ((addr->code == NULL) || (*addr->code == 0)) &&
- ((addr->country == NULL) || (*addr->country == 0)));
-}
-
-ECardDeliveryAddress *
-e_card_delivery_address_from_label(const ECardAddrLabel *label)
-{
- ECardDeliveryAddress *addr = e_card_delivery_address_new ();
- EAddressWestern *western = e_address_western_parse (label->data);
-
- addr->po = g_strdup (western->po_box );
- addr->ext = g_strdup (western->extended );
- addr->street = g_strdup (western->street );
- addr->city = g_strdup (western->locality );
- addr->region = g_strdup (western->region );
- addr->code = g_strdup (western->postal_code);
- addr->country = g_strdup (western->country );
- addr->flags = label->flags;
-
- e_address_western_free(western);
-
- return addr;
-}
-
-char *
-e_card_delivery_address_to_string(const ECardDeliveryAddress *addr)
-{
- char *strings[5], **stringptr = strings;
- char *line1, *line22, *line2;
- char *final;
- if (addr->po && *addr->po)
- *(stringptr++) = addr->po;
- if (addr->street && *addr->street)
- *(stringptr++) = addr->street;
- *stringptr = NULL;
- line1 = g_strjoinv(" ", strings);
- stringptr = strings;
- if (addr->region && *addr->region)
- *(stringptr++) = addr->region;
- if (addr->code && *addr->code)
- *(stringptr++) = addr->code;
- *stringptr = NULL;
- line22 = g_strjoinv(" ", strings);
- stringptr = strings;
- if (addr->city && *addr->city)
- *(stringptr++) = addr->city;
- if (line22 && *line22)
- *(stringptr++) = line22;
- *stringptr = NULL;
- line2 = g_strjoinv(", ", strings);
- stringptr = strings;
- if (line1 && *line1)
- *(stringptr++) = line1;
- if (addr->ext && *addr->ext)
- *(stringptr++) = addr->ext;
- if (line2 && *line2)
- *(stringptr++) = line2;
- if (addr->country && *addr->country)
- *(stringptr++) = addr->country;
- *stringptr = NULL;
- final = g_strjoinv("\n", strings);
- g_free(line1);
- g_free(line22);
- g_free(line2);
- return final;
-}
-
-ECardAddrLabel *
-e_card_delivery_address_to_label (const ECardDeliveryAddress *addr)
-{
- ECardAddrLabel *label;
- label = e_card_address_label_new();
- label->flags = addr->flags;
- label->data = e_card_delivery_address_to_string(addr);
-
- return label;
-}
-
-ECardAddrLabel *
-e_card_address_label_new (void)
-{
- ECardAddrLabel *newaddr = g_new(ECardAddrLabel, 1);
-
- newaddr->ref_count = 1;
- newaddr->data = NULL;
- newaddr->flags = 0;
-
- return newaddr;
-}
-
-void
-e_card_address_label_unref (ECardAddrLabel *addr)
-{
- if (addr) {
- addr->ref_count --;
- if (addr->ref_count == 0) {
- g_free(addr->data);
- g_free(addr);
- }
- }
-}
-
-ECardAddrLabel *
-e_card_address_label_ref (const ECardAddrLabel *addr)
-{
- ECardAddrLabel *addr_mutable = (ECardAddrLabel *) addr;
- if (addr_mutable)
- addr_mutable->ref_count ++;
- return addr_mutable;
-}
-
-ECardAddrLabel *
-e_card_address_label_copy (const ECardAddrLabel *addr)
-{
- if ( addr ) {
- ECardAddrLabel *addr_copy = e_card_address_label_new ();
- addr_copy->data = g_strdup(addr->data);
- addr_copy->flags = addr->flags;
- return addr_copy;
- } else
- return NULL;
-}
-
-ECardName *e_card_name_new(void)
-{
- ECardName *newname = g_new(ECardName, 1);
-
- newname->ref_count = 1;
- newname->prefix = NULL;
- newname->given = NULL;
- newname->additional = NULL;
- newname->family = NULL;
- newname->suffix = NULL;
-
- return newname;
-}
-
-void
-e_card_name_unref(ECardName *name)
-{
- if (name) {
- name->ref_count --;
- if (name->ref_count == 0) {
- g_free (name->prefix);
- g_free (name->given);
- g_free (name->additional);
- g_free (name->family);
- g_free (name->suffix);
- g_free (name);
- }
- }
-}
-
-ECardName *
-e_card_name_ref(const ECardName *name)
-{
- ECardName *name_mutable = (ECardName *) name;
- if (name_mutable)
- name_mutable->ref_count ++;
- return name_mutable;
-}
-
-ECardName *
-e_card_name_copy(const ECardName *name)
-{
- if (name) {
- ECardName *newname = e_card_name_new ();
-
- newname->prefix = g_strdup(name->prefix);
- newname->given = g_strdup(name->given);
- newname->additional = g_strdup(name->additional);
- newname->family = g_strdup(name->family);
- newname->suffix = g_strdup(name->suffix);
-
- return newname;
- } else
- return NULL;
-}
-
-
-char *
-e_card_name_to_string(const ECardName *name)
-{
- char *strings[6], **stringptr = strings;
-
- g_return_val_if_fail (name != NULL, NULL);
-
- if (name->prefix && *name->prefix)
- *(stringptr++) = name->prefix;
- if (name->given && *name->given)
- *(stringptr++) = name->given;
- if (name->additional && *name->additional)
- *(stringptr++) = name->additional;
- if (name->family && *name->family)
- *(stringptr++) = name->family;
- if (name->suffix && *name->suffix)
- *(stringptr++) = name->suffix;
- *stringptr = NULL;
- return g_strjoinv(" ", strings);
-}
-
-ECardName *
-e_card_name_from_string(const char *full_name)
-{
- ECardName *name = e_card_name_new ();
- ENameWestern *western = e_name_western_parse (full_name);
-
- name->prefix = g_strdup (western->prefix);
- name->given = g_strdup (western->first );
- name->additional = g_strdup (western->middle);
- name->family = g_strdup (western->last );
- name->suffix = g_strdup (western->suffix);
-
- e_name_western_free(western);
-
- return name;
-}
-
-ECardArbitrary *
-e_card_arbitrary_new(void)
-{
- ECardArbitrary *arbitrary = g_new(ECardArbitrary, 1);
- arbitrary->ref_count = 1;
- arbitrary->key = NULL;
- arbitrary->type = NULL;
- arbitrary->value = NULL;
- return arbitrary;
-}
-
-void
-e_card_arbitrary_unref(ECardArbitrary *arbitrary)
-{
- if (arbitrary) {
- arbitrary->ref_count --;
- if (arbitrary->ref_count == 0) {
- g_free(arbitrary->key);
- g_free(arbitrary->type);
- g_free(arbitrary->value);
- g_free(arbitrary);
- }
- }
-}
-
-ECardArbitrary *
-e_card_arbitrary_copy(const ECardArbitrary *arbitrary)
-{
- if (arbitrary) {
- ECardArbitrary *arb_copy = e_card_arbitrary_new ();
- arb_copy->key = g_strdup(arbitrary->key);
- arb_copy->type = g_strdup(arbitrary->type);
- arb_copy->value = g_strdup(arbitrary->value);
- return arb_copy;
- } else
- return NULL;
-}
-
-ECardArbitrary *
-e_card_arbitrary_ref(const ECardArbitrary *arbitrary)
-{
- ECardArbitrary *arbitrary_mutable = (ECardArbitrary *) arbitrary;
- if (arbitrary_mutable)
- arbitrary_mutable->ref_count ++;
- return arbitrary_mutable;
-}
-
-/* EMail matching */
-static gboolean
-e_card_email_match_single_string (const gchar *a, const gchar *b)
-{
- const gchar *xa = NULL, *xb = NULL;
- gboolean match = TRUE;
-
- for (xa=a; *xa && *xa != '@'; ++xa);
- for (xb=b; *xb && *xb != '@'; ++xb);
-
- if (xa-a != xb-b || *xa != *xb || g_ascii_strncasecmp (a, b, xa-a))
- return FALSE;
-
- if (*xa == '\0')
- return TRUE;
-
- /* Find the end of the string, then walk through backwards comparing.
- This is so that we'll match joe@foobar.com and joe@mail.foobar.com.
- */
- while (*xa)
- ++xa;
- while (*xb)
- ++xb;
-
- while (match && *xa != '@' && *xb != '@') {
- match = (tolower (*xa) == tolower (*xb));
- --xa;
- --xb;
- }
-
- match = match && ((tolower (*xa) == tolower (*xb)) || (*xa == '.') || (*xb == '.'));
-
- return match;
-}
-
-gboolean
-e_card_email_match_string (const ECard *card, const gchar *str)
-{
- EIterator *iter;
-
- g_return_val_if_fail (card && E_IS_CARD (card), FALSE);
- g_return_val_if_fail (str != NULL, FALSE);
-
- if (!card->email)
- return FALSE;
-
- iter = e_list_get_iterator (card->email);
- for (e_iterator_reset (iter); e_iterator_is_valid (iter); e_iterator_next (iter)) {
- if (e_card_email_match_single_string (e_iterator_get (iter), str))
- return TRUE;
- }
- g_object_unref (iter);
-
- return FALSE;
-}
-
-gint
-e_card_email_find_number (const ECard *card, const gchar *email)
-{
- EIterator *iter;
- gint count = 0;
-
- g_return_val_if_fail (E_IS_CARD (card), -1);
- g_return_val_if_fail (email != NULL, -1);
-
- if (!card->email)
- return -1;
-
- iter = e_list_get_iterator (card->email);
- for (e_iterator_reset (iter); e_iterator_is_valid (iter); e_iterator_next (iter)) {
- if (!g_ascii_strcasecmp (e_iterator_get (iter), email))
- goto finished;
- ++count;
- }
- count = -1;
-
- finished:
- g_object_unref (iter);
-
- return count;
-}
-
-/*
- * ECard lifecycle management and vCard loading/saving.
- */
-
-static void
-e_card_dispose (GObject *object)
-{
- ECard *card = E_CARD(object);
-
-#define FREE_IF(x) do { if ((x)) { g_free (x); x = NULL; } } while (0)
-#define UNREF_IF(x) do { if ((x)) { g_object_unref (x); x = NULL; } } while (0)
-
- FREE_IF (card->id);
- UNREF_IF (card->book);
- FREE_IF(card->file_as);
- FREE_IF(card->fname);
- if (card->name) {
- e_card_name_unref(card->name);
- card->name = NULL;
- }
- FREE_IF(card->bday);
-
- FREE_IF(card->url);
- FREE_IF(card->org);
- FREE_IF(card->org_unit);
- FREE_IF(card->office);
- FREE_IF(card->title);
- FREE_IF(card->role);
- FREE_IF(card->manager);
- FREE_IF(card->assistant);
- FREE_IF(card->nickname);
- FREE_IF(card->spouse);
- FREE_IF(card->anniversary);
- FREE_IF(card->caluri);
- FREE_IF(card->fburl);
- FREE_IF(card->icscalendar);
- FREE_IF(card->last_use);
- FREE_IF(card->note);
- FREE_IF(card->related_contacts);
-
- UNREF_IF (card->categories);
- UNREF_IF (card->email);
- UNREF_IF (card->phone);
- UNREF_IF (card->address);
- UNREF_IF (card->address_label);
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-
-/* Set_arg handler for the card */
-static void
-e_card_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ECard *card;
-
- card = E_CARD (object);
-
- switch (prop_id) {
- case PROP_FILE_AS:
- g_free(card->file_as);
- card->file_as = g_strdup(g_value_get_string (value));
- if (card->file_as == NULL)
- card->file_as = g_strdup("");
- break;
-
- case PROP_FULL_NAME:
- g_free(card->fname);
- card->fname = g_strdup(g_value_get_string (value));
- if (card->fname == NULL)
- card->fname = g_strdup("");
-
- e_card_name_unref (card->name);
- card->name = e_card_name_from_string (card->fname);
- break;
- case PROP_NAME:
- e_card_name_unref (card->name);
- card->name = e_card_name_ref(g_value_get_pointer (value));
- if (card->name == NULL)
- card->name = e_card_name_new();
- if (card->fname == NULL) {
- card->fname = e_card_name_to_string(card->name);
- }
- if (card->file_as == NULL) {
- ECardName *name = card->name;
- char *strings[3], **stringptr;
- char *string;
- stringptr = strings;
- if (name->family && *name->family)
- *(stringptr++) = name->family;
- if (name->given && *name->given)
- *(stringptr++) = name->given;
- *stringptr = NULL;
- string = g_strjoinv(", ", strings);
- card->file_as = string;
- }
- break;
- case PROP_CATEGORIES:
- if (card->categories)
- g_object_unref(card->categories);
- card->categories = NULL;
- if (g_value_get_string (value))
- do_parse_categories(card, (char*)g_value_get_string (value));
- break;
- case PROP_CATEGORY_LIST:
- if (card->categories)
- g_object_unref(card->categories);
- card->categories = E_LIST(g_value_get_object(value));
- if (card->categories)
- g_object_ref(card->categories);
- break;
- case PROP_BIRTH_DATE:
- g_free(card->bday);
- if (g_value_get_pointer (value)) {
- card->bday = g_new (ECardDate, 1);
- memcpy (card->bday, g_value_get_pointer (value), sizeof (ECardDate));
- } else {
- card->bday = NULL;
- }
- break;
- case PROP_URL:
- g_free(card->url);
- card->url = g_strdup(g_value_get_string(value));
- break;
- case PROP_ORG:
- g_free(card->org);
- card->org = g_strdup(g_value_get_string(value));
- break;
- case PROP_ORG_UNIT:
- g_free(card->org_unit);
- card->org_unit = g_strdup(g_value_get_string(value));
- break;
- case PROP_OFFICE:
- g_free(card->office);
- card->office = g_strdup(g_value_get_string(value));
- break;
- case PROP_TITLE:
- g_free(card->title);
- card->title = g_strdup(g_value_get_string(value));
- break;
- case PROP_ROLE:
- g_free(card->role);
- card->role = g_strdup(g_value_get_string(value));
- break;
- case PROP_MANAGER:
- g_free(card->manager);
- card->manager = g_strdup(g_value_get_string(value));
- break;
- case PROP_ASSISTANT:
- g_free(card->assistant);
- card->assistant = g_strdup(g_value_get_string(value));
- break;
- case PROP_NICKNAME:
- g_free(card->nickname);
- card->nickname = g_strdup(g_value_get_string(value));
- break;
- case PROP_SPOUSE:
- g_free(card->spouse);
- card->spouse = g_strdup(g_value_get_string(value));
- break;
- case PROP_ANNIVERSARY:
- g_free(card->anniversary);
- if (g_value_get_pointer (value)) {
- card->anniversary = g_new (ECardDate, 1);
- memcpy (card->anniversary, g_value_get_pointer (value), sizeof (ECardDate));
- } else {
- card->anniversary = NULL;
- }
- break;
- case PROP_MAILER:
- g_free(card->mailer);
- card->mailer = g_strdup(g_value_get_string(value));
- break;
- case PROP_CALURI:
- g_free(card->caluri);
- card->caluri = g_strdup(g_value_get_string(value));
- break;
- case PROP_FBURL:
- g_free(card->fburl);
- card->fburl = g_strdup(g_value_get_string(value));
- break;
- case PROP_ICSCALENDAR:
- g_free(card->icscalendar);
- card->icscalendar = g_strdup(g_value_get_string(value));
- break;
- case PROP_NOTE:
- g_free (card->note);
- card->note = g_strdup(g_value_get_string(value));
- break;
- case PROP_RELATED_CONTACTS:
- g_free (card->related_contacts);
- card->related_contacts = g_strdup(g_value_get_string(value));
- break;
- case PROP_WANTS_HTML:
- card->wants_html = g_value_get_boolean (value);
- card->wants_html_set = TRUE;
- break;
- case PROP_ARBITRARY:
- if (card->arbitrary)
- g_object_unref(card->arbitrary);
- card->arbitrary = E_LIST(g_value_get_pointer(value));
- if (card->arbitrary)
- g_object_ref(card->arbitrary);
- break;
- case PROP_ID:
- g_free(card->id);
- card->id = g_strdup(g_value_get_string(value));
- if (card->id == NULL)
- card->id = g_strdup ("");
- break;
- case PROP_LAST_USE:
- g_free(card->last_use);
- if (g_value_get_pointer (value)) {
- card->last_use = g_new (ECardDate, 1);
- memcpy (card->last_use, g_value_get_pointer (value), sizeof (ECardDate));
- } else {
- card->last_use = NULL;
- }
- break;
- case PROP_USE_SCORE:
- card->raw_use_score = g_value_get_float (value);
- break;
- case PROP_EVOLUTION_LIST:
- card->list = g_value_get_boolean (value);
- break;
- case PROP_EVOLUTION_LIST_SHOW_ADDRESSES:
- card->list_show_addresses = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* Get_arg handler for the card */
-static void
-e_card_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ECard *card;
-
- card = E_CARD (object);
-
- switch (prop_id) {
- case PROP_FILE_AS:
- g_value_set_string (value, card->file_as);
- break;
- case PROP_FULL_NAME:
- g_value_set_string (value, card->fname);
- break;
- case PROP_NAME:
- g_value_set_pointer (value, card->name);
- break;
- case PROP_ADDRESS:
- if (!card->address)
- card->address = e_list_new((EListCopyFunc) e_card_delivery_address_ref,
- (EListFreeFunc) e_card_delivery_address_unref,
- NULL);
- g_value_set_object (value, card->address);
- break;
- case PROP_ADDRESS_LABEL:
- if (!card->address_label)
- card->address_label = e_list_new((EListCopyFunc) e_card_address_label_ref,
- (EListFreeFunc) e_card_address_label_unref,
- NULL);
- g_value_set_object (value, card->address_label);
- break;
- case PROP_PHONE:
- if (!card->phone)
- card->phone = e_list_new((EListCopyFunc) e_card_phone_ref,
- (EListFreeFunc) e_card_phone_unref,
- NULL);
- g_value_set_object (value, card->phone);
- break;
- case PROP_EMAIL:
- if (!card->email)
- card->email = e_list_new((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
- g_value_set_object (value, card->email);
- break;
- case PROP_CATEGORIES:
- {
- int i;
- char ** strs;
- int length;
- EIterator *iterator;
- if (!card->categories)
- card->categories = e_list_new((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
- length = e_list_length(card->categories);
- strs = g_new(char *, length + 1);
- for (iterator = e_list_get_iterator(card->categories), i = 0; e_iterator_is_valid(iterator); e_iterator_next(iterator), i++) {
- strs[i] = (char *)e_iterator_get(iterator);
- }
- strs[i] = 0;
- g_value_set_string_take_ownership(value, g_strjoinv(", ", strs));
- g_free(strs);
- }
- break;
- case PROP_CATEGORY_LIST:
- if (!card->categories)
- card->categories = e_list_new((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
- g_value_set_object (value, card->categories);
- break;
- case PROP_BIRTH_DATE:
- g_value_set_pointer (value, card->bday);
- break;
- case PROP_URL:
- g_value_set_string (value, card->url);
- break;
- case PROP_ORG:
- g_value_set_string (value, card->org);
- break;
- case PROP_ORG_UNIT:
- g_value_set_string (value, card->org_unit);
- break;
- case PROP_OFFICE:
- g_value_set_string (value, card->office);
- break;
- case PROP_TITLE:
- g_value_set_string (value, card->title);
- break;
- case PROP_ROLE:
- g_value_set_string (value, card->role);
- break;
- case PROP_MANAGER:
- g_value_set_string (value, card->manager);
- break;
- case PROP_ASSISTANT:
- g_value_set_string (value, card->assistant);
- break;
- case PROP_NICKNAME:
- g_value_set_string (value, card->nickname);
- break;
- case PROP_SPOUSE:
- g_value_set_string (value, card->spouse);
- break;
- case PROP_ANNIVERSARY:
- g_value_set_pointer (value, card->anniversary);
- break;
- case PROP_MAILER:
- g_value_set_string (value, card->mailer);
- break;
- case PROP_CALURI:
- g_value_set_string (value, card->caluri);
- break;
- case PROP_FBURL:
- g_value_set_string (value, card->fburl);
- break;
- case PROP_ICSCALENDAR:
- g_value_set_string (value, card->icscalendar);
- break;
- case PROP_NOTE:
- g_value_set_string (value, card->note);
- break;
- case PROP_RELATED_CONTACTS:
- g_value_set_string (value, card->related_contacts);
- break;
- case PROP_WANTS_HTML:
- g_value_set_boolean (value, card->wants_html);
- break;
- case PROP_WANTS_HTML_SET:
- g_value_set_boolean (value, card->wants_html_set);
- break;
- case PROP_ARBITRARY:
- if (!card->arbitrary)
- card->arbitrary = e_list_new((EListCopyFunc) e_card_arbitrary_ref,
- (EListFreeFunc) e_card_arbitrary_unref,
- NULL);
-
- g_value_set_object (value, card->arbitrary);
- break;
- case PROP_ID:
- g_value_set_string (value, card->id);
- break;
- case PROP_LAST_USE:
- g_value_set_pointer (value, card->last_use);
- break;
- case PROP_USE_SCORE:
- g_value_set_float (value, e_card_get_use_score (card));
- break;
- case PROP_EVOLUTION_LIST:
- g_value_set_boolean (value, card->list);
- break;
- case PROP_EVOLUTION_LIST_SHOW_ADDRESSES:
- g_value_set_boolean (value, card->list_show_addresses);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-/**
- * e_card_init:
- */
-static void
-e_card_init (ECard *card)
-{
- card->id = g_strdup("");
-
- card->file_as = NULL;
- card->fname = NULL;
- card->name = NULL;
- card->bday = NULL;
- card->email = NULL;
- card->phone = NULL;
- card->address = NULL;
- card->address_label = NULL;
- card->url = NULL;
- card->org = NULL;
- card->org_unit = NULL;
- card->office = NULL;
- card->title = NULL;
- card->role = NULL;
- card->manager = NULL;
- card->assistant = NULL;
- card->nickname = NULL;
- card->spouse = NULL;
- card->anniversary = NULL;
- card->mailer = NULL;
- card->caluri = NULL;
- card->fburl = NULL;
- card->icscalendar = NULL;
- card->note = NULL;
- card->related_contacts = NULL;
- card->categories = NULL;
- card->wants_html = FALSE;
- card->wants_html_set = FALSE;
- card->list = FALSE;
- card->list_show_addresses = FALSE;
- card->arbitrary = NULL;
- card->last_use = NULL;
- card->raw_use_score = 0;
-}
-
-GList *
-e_card_load_cards_from_file_with_default_charset(const char *filename, const char *default_charset)
-{
- VObject *vobj = Parse_MIME_FromFileName((char *) filename);
- GList *list = NULL;
- while(vobj) {
- VObject *next;
- ECard *card = g_object_new (E_TYPE_CARD, NULL);
- parse(card, vobj, default_charset);
- next = nextVObjectInList(vobj);
- cleanVObject(vobj);
- vobj = next;
- list = g_list_prepend(list, card);
- }
- list = g_list_reverse(list);
- return list;
-}
-
-GList *
-e_card_load_cards_from_file(const char *filename)
-{
- return e_card_load_cards_from_file_with_default_charset (filename, "UTF-8");
-}
-
-GList *
-e_card_load_cards_from_string_with_default_charset(const char *str, const char *default_charset)
-{
- VObject *vobj = Parse_MIME(str, strlen (str));
- GList *list = NULL;
- while(vobj) {
- VObject *next;
- ECard *card = g_object_new (E_TYPE_CARD, NULL);
- parse(card, vobj, default_charset);
- next = nextVObjectInList(vobj);
- cleanVObject(vobj);
- vobj = next;
- list = g_list_prepend(list, card);
- }
- list = g_list_reverse(list);
- return list;
-}
-
-GList *
-e_card_load_cards_from_string(const char *str)
-{
- return e_card_load_cards_from_string_with_default_charset (str, "UTF-8");
-}
-
-void
-e_card_free_empty_lists (ECard *card)
-{
- if (card->address && e_list_length (card->address) == 0) {
- g_object_unref (card->address);
- card->address = NULL;
- }
-
- if (card->address_label && e_list_length (card->address_label) == 0) {
- g_object_unref (card->address_label);
- card->address_label = NULL;
- }
-
- if (card->phone && e_list_length (card->phone) == 0) {
- g_object_unref (card->phone);
- card->phone = NULL;
- }
-
- if (card->email && e_list_length (card->email) == 0) {
- g_object_unref (card->email);
- card->email = NULL;
- }
-
- if (card->categories && e_list_length (card->categories) == 0) {
- g_object_unref (card->categories);
- card->categories = NULL;
- }
-
- if (card->arbitrary && e_list_length (card->arbitrary) == 0) {
- g_object_unref (card->arbitrary);
- card->arbitrary = NULL;
- }
-}
-
-static void
-assign_string(VObject *vobj, const char *default_charset, char **string)
-{
- int type = vObjectValueType(vobj);
- char *str;
- const char *charset = default_charset;
- char *charset_buf = NULL;
- VObject *charset_obj;
-
- if ((charset_obj = isAPropertyOf (vobj, "CHARSET"))) {
- switch (vObjectValueType (charset_obj)) {
- case VCVT_STRINGZ:
- charset = vObjectStringZValue(charset_obj);
- break;
- case VCVT_USTRINGZ:
- charset_buf = fakeCString (vObjectUStringZValue (charset_obj));
- charset = charset_buf;
- break;
- }
- }
-
- switch(type) {
- case VCVT_STRINGZ:
- if (strcmp (charset, "UTF-8"))
- *string = e_utf8_from_charset_string (charset, vObjectStringZValue(vobj));
- else
- *string = g_strdup(vObjectStringZValue(vobj));
- break;
- case VCVT_USTRINGZ:
- str = fakeCString (vObjectUStringZValue (vobj));
- if (strcmp (charset, "UTF-8"))
- *string = e_utf8_from_charset_string (charset, str);
- else
- *string = g_strdup(str);
- free(str);
- break;
- default:
- *string = g_strdup("");
- break;
- }
-
- if (charset_buf) {
- free (charset_buf);
- }
-}
-
-
-ECardDate
-e_card_date_from_string (const char *str)
-{
- ECardDate date;
- int length;
-
- date.year = 0;
- date.month = 0;
- date.day = 0;
-
- length = strlen(str);
-
- if (length == 10 ) {
- date.year = str[0] * 1000 + str[1] * 100 + str[2] * 10 + str[3] - '0' * 1111;
- date.month = str[5] * 10 + str[6] - '0' * 11;
- date.day = str[8] * 10 + str[9] - '0' * 11;
- } else if ( length == 8 ) {
- date.year = str[0] * 1000 + str[1] * 100 + str[2] * 10 + str[3] - '0' * 1111;
- date.month = str[4] * 10 + str[5] - '0' * 11;
- date.day = str[6] * 10 + str[7] - '0' * 11;
- }
-
- return date;
-}
-
-char *
-e_v_object_get_child_value(VObject *vobj, char *name, const char *default_charset)
-{
- char *ret_val;
- VObjectIterator iterator;
- char *charset_buf = NULL;
- VObject *charset_obj;
-
- if ((charset_obj = isAPropertyOf (vobj, "CHARSET"))) {
- switch (vObjectValueType (charset_obj)) {
- case VCVT_STRINGZ:
- default_charset = vObjectStringZValue(charset_obj);
- break;
- case VCVT_USTRINGZ:
- charset_buf = fakeCString (vObjectUStringZValue (charset_obj));
- default_charset = charset_buf;
- break;
- }
- }
-
- initPropIterator(&iterator, vobj);
- while(moreIteration (&iterator)) {
- VObject *attribute = nextVObject(&iterator);
- const char *id = vObjectName(attribute);
- if ( ! strcmp(id, name) ) {
- assign_string(attribute, default_charset, &ret_val);
- return ret_val;
- }
- }
- if (charset_buf)
- free (charset_buf);
-
- return NULL;
-}
-
-static struct {
- char *id;
- ECardPhoneFlags flag;
-} phone_pairs[] = {
- { VCPreferredProp, E_CARD_PHONE_PREF },
- { VCWorkProp, E_CARD_PHONE_WORK },
- { VCHomeProp, E_CARD_PHONE_HOME },
- { VCVoiceProp, E_CARD_PHONE_VOICE },
- { VCFaxProp, E_CARD_PHONE_FAX },
- { VCMessageProp, E_CARD_PHONE_MSG },
- { VCCellularProp, E_CARD_PHONE_CELL },
- { VCPagerProp, E_CARD_PHONE_PAGER },
- { VCBBSProp, E_CARD_PHONE_BBS },
- { VCModemProp, E_CARD_PHONE_MODEM },
- { VCCarProp, E_CARD_PHONE_CAR },
- { VCISDNProp, E_CARD_PHONE_ISDN },
- { VCVideoProp, E_CARD_PHONE_VIDEO },
- { "X-EVOLUTION-ASSISTANT", E_CARD_PHONE_ASSISTANT },
- { "X-EVOLUTION-CALLBACK", E_CARD_PHONE_CALLBACK },
- { "X-EVOLUTION-RADIO", E_CARD_PHONE_RADIO },
- { "X-EVOLUTION-TELEX", E_CARD_PHONE_TELEX },
- { "X-EVOLUTION-TTYTDD", E_CARD_PHONE_TTYTDD },
-};
-
-static ECardPhoneFlags
-get_phone_flags (VObject *vobj)
-{
- ECardPhoneFlags ret = 0;
- int i;
-
- for (i = 0; i < sizeof(phone_pairs) / sizeof(phone_pairs[0]); i++) {
- if (isAPropertyOf (vobj, phone_pairs[i].id)) {
- ret |= phone_pairs[i].flag;
- }
- }
-
- return ret;
-}
-
-static void
-set_phone_flags (VObject *vobj, ECardPhoneFlags flags)
-{
- int i;
-
- for (i = 0; i < sizeof(phone_pairs) / sizeof(phone_pairs[0]); i++) {
- if (flags & phone_pairs[i].flag) {
- addProp (vobj, phone_pairs[i].id);
- }
- }
-}
-
-static struct {
- char *id;
- ECardAddressFlags flag;
-} addr_pairs[] = {
- { VCDomesticProp, E_CARD_ADDR_DOM },
- { VCInternationalProp, E_CARD_ADDR_INTL },
- { VCPostalProp, E_CARD_ADDR_POSTAL },
- { VCParcelProp, E_CARD_ADDR_PARCEL },
- { VCHomeProp, E_CARD_ADDR_HOME },
- { VCWorkProp, E_CARD_ADDR_WORK },
- { "PREF", E_CARD_ADDR_DEFAULT },
-};
-
-static ECardAddressFlags
-get_address_flags (VObject *vobj)
-{
- ECardAddressFlags ret = 0;
- int i;
-
- for (i = 0; i < sizeof(addr_pairs) / sizeof(addr_pairs[0]); i++) {
- if (isAPropertyOf (vobj, addr_pairs[i].id)) {
- ret |= addr_pairs[i].flag;
- }
- }
-
- return ret;
-}
-
-static void
-set_address_flags (VObject *vobj, ECardAddressFlags flags)
-{
- int i;
-
- for (i = 0; i < sizeof(addr_pairs) / sizeof(addr_pairs[0]); i++) {
- if (flags & addr_pairs[i].flag) {
- addProp (vobj, addr_pairs[i].id);
- }
- }
-}
-
-gboolean
-e_card_evolution_list (ECard *card)
-{
- g_return_val_if_fail (card && E_IS_CARD (card), FALSE);
- return card->list;
-}
-
-gboolean
-e_card_evolution_list_show_addresses (ECard *card)
-{
- g_return_val_if_fail (card && E_IS_CARD (card), FALSE);
- return card->list_show_addresses;
-}
-
-typedef struct _CardLoadData CardLoadData;
-struct _CardLoadData {
- gchar *card_id;
- ECardCallback cb;
- gpointer closure;
-};
-
-static void
-get_card_cb (EBook *book, EBookStatus status, ECard *card, gpointer closure)
-{
- CardLoadData *data = (CardLoadData *) closure;
-
- if (data->cb != NULL) {
- if (status == E_BOOK_STATUS_SUCCESS)
- data->cb (card, data->closure);
- else
- data->cb (NULL, data->closure);
- }
-
- g_free (data->card_id);
- g_free (data);
-}
-
-static void
-card_load_cb (EBook *book, EBookStatus status, gpointer closure)
-{
- CardLoadData *data = (CardLoadData *) closure;
-
- if (status == E_BOOK_STATUS_SUCCESS)
- e_book_get_card (book, data->card_id, get_card_cb, closure);
- else {
- data->cb (NULL, data->closure);
- g_free (data->card_id);
- g_free (data);
- }
-}
-
-void
-e_card_load_uri (const gchar *book_uri, const gchar *uid, ECardCallback cb, gpointer closure)
-{
- CardLoadData *data;
- EBook *book;
-
- data = g_new (CardLoadData, 1);
- data->card_id = g_strdup (uid);
- data->cb = cb;
- data->closure = closure;
-
- book = e_book_new ();
- e_book_load_uri (book, book_uri, card_load_cb, data);
-}
diff --git a/addressbook/backend/ebook/e-card.h b/addressbook/backend/ebook/e-card.h
deleted file mode 100644
index 8819966d5b..0000000000
--- a/addressbook/backend/ebook/e-card.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- * Arturo Espinosa
- * Nat Friedman (nat@ximian.com)
- *
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 1999 The Free Software Foundation
- */
-
-#ifndef __E_CARD_H__
-#define __E_CARD_H__
-
-#include <time.h>
-#include <glib-object.h>
-#include <stdio.h>
-#include <ebook/e-card-types.h>
-#include <e-util/e-list.h>
-
-#define E_TYPE_CARD (e_card_get_type ())
-#define E_CARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CARD, ECard))
-#define E_CARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CARD, ECardClass))
-#define E_IS_CARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CARD))
-#define E_IS_CARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CARD))
-#define E_CARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CARD, ECardClass))
-
-typedef struct _ECard ECard;
-typedef struct _ECardClass ECardClass;
-
-struct _EBook; /* Forward reference */
-
-struct _ECard {
- GObject object;
- char *id;
-
- struct _EBook *book; /* The EBook this card is from. */
-
- char *file_as; /* The File As field. */
- char *fname; /* The full name. */
- ECardName *name; /* The structured name. */
- EList *address; /* Delivery addresses (ECardDeliveryAddress *) */
- EList *address_label; /* Delivery address labels
- * (ECardAddrLabel *) */
-
- EList *phone; /* Phone numbers (ECardPhone *) */
- EList *email; /* Email addresses (char *) */
- char *url; /* The person's web page. */
-
- ECardDate *bday; /* The person's birthday. */
-
- char *note;
-
-
- char *org; /* The person's organization. */
- char *org_unit; /* The person's organization unit. */
- char *office; /* The person's office. */
- char *role; /* The person's role w/in his org */
- char *title; /* The person's title w/in his org */
-
- char *manager;
- char *assistant;
-
- char *nickname; /* The person's nickname */
-
- char *spouse; /* The person's spouse. */
- ECardDate *anniversary; /* The person's anniversary. */
-
- char *mailer; /* Mailer */
-
- char *caluri; /* Calendar URI */
- char *fburl; /* Free Busy URL */
- char *icscalendar; /* Default server calendar */
-
- gint timezone; /* number of minutes from UTC as an int */
-
- ECardDate *last_use;
- float raw_use_score;
-
- char *related_contacts; /* EDestinationV (serialized) of related contacts. */
-
- EList *categories; /* Categories. */
-
- EList *arbitrary; /* Arbitrary fields. */
-
-
-
- guint32 wants_html : 1; /* Wants html mail. */
- guint32 wants_html_set : 1; /* Wants html mail. */
- guint32 list : 1; /* If the card corresponds to a contact list */
- guint32 list_show_addresses : 1; /* Whether to show the addresses
- in the To: or Bcc: field */
-
-#if 0
- ECardPhoto *logo; /* This person's org's logo. */
-
- ECardPhoto *photo; /* A photo of the person. */
-
- ECard *agent; /* A person who sereves as this
- guy's agent/secretary/etc. */
-
- ECardSound *sound;
-
- ECardKey *key; /* The person's public key. */
- ECardTimeZone *timezn; /* The person's time zone. */
- ECardGeoPos *geopos; /* The person's long/lat. */
-
- ECardRev *rev; /* The time this card was last
- modified. */
-
- EList xtension;
-#endif
-};
-
-struct _ECardClass {
- GObjectClass parent_class;
- GHashTable *attribute_jump_table;
-};
-
-
-/* Simple functions */
-ECard *e_card_new (const char *vcard); /* Assumes utf8 */
-ECard *e_card_new_with_default_charset (const char *vcard,
- const char *default_charset);
-const char *e_card_get_id (ECard *card);
-void e_card_set_id (ECard *card,
- const char *character);
-
-struct _EBook *e_card_get_book (ECard *card);
-void e_card_set_book (ECard *card,
- struct _EBook *book);
-char *e_card_get_vcard (ECard *card);
-char *e_card_get_vcard_assume_utf8 (ECard *card);
-char *e_card_list_get_vcard (const GList *list);
-ECard *e_card_duplicate (ECard *card);
-float e_card_get_use_score (ECard *card);
-void e_card_touch (ECard *card);
-
-/* Evolution List convenience functions */
-/* used for encoding uids in email addresses */
-gboolean e_card_evolution_list (ECard *card);
-gboolean e_card_evolution_list_show_addresses (ECard *card);
-
-/* ECardPhone manipulation */
-ECardPhone *e_card_phone_new (void);
-ECardPhone *e_card_phone_copy (const ECardPhone *phone);
-ECardPhone *e_card_phone_ref (const ECardPhone *phone);
-void e_card_phone_unref (ECardPhone *phone);
-
-/* ECardDeliveryAddress manipulation */
-ECardDeliveryAddress *e_card_delivery_address_new (void);
-ECardDeliveryAddress *e_card_delivery_address_copy (const ECardDeliveryAddress *addr);
-ECardDeliveryAddress *e_card_delivery_address_ref (const ECardDeliveryAddress *addr);
-void e_card_delivery_address_unref (ECardDeliveryAddress *addr);
-gboolean e_card_delivery_address_is_empty (const ECardDeliveryAddress *addr);
-char *e_card_delivery_address_to_string (const ECardDeliveryAddress *addr);
-ECardDeliveryAddress *e_card_delivery_address_from_label (const ECardAddrLabel *label);
-ECardAddrLabel *e_card_delivery_address_to_label (const ECardDeliveryAddress *addr);
-
-/* ECardAddrLabel manipulation */
-ECardAddrLabel *e_card_address_label_new (void);
-ECardAddrLabel *e_card_address_label_copy (const ECardAddrLabel *addr);
-ECardAddrLabel *e_card_address_label_ref (const ECardAddrLabel *addr);
-void e_card_address_label_unref (ECardAddrLabel *addr);
-
-/* ECardName manipulation */
-ECardName *e_card_name_new (void);
-ECardName *e_card_name_copy (const ECardName *name);
-ECardName *e_card_name_ref (const ECardName *name);
-void e_card_name_unref (ECardName *name);
-char *e_card_name_to_string (const ECardName *name);
-ECardName *e_card_name_from_string (const char *full_name);
-
-/* ECardDate */
-ECardDate e_card_date_from_string (const gchar *str);
-gchar *e_card_date_to_string (ECardDate *dt);
-
-/* ECardArbitrary manipulation */
-ECardArbitrary *e_card_arbitrary_new (void);
-ECardArbitrary *e_card_arbitrary_copy (const ECardArbitrary *arbitrary);
-ECardArbitrary *e_card_arbitrary_ref (const ECardArbitrary *arbitrary);
-void e_card_arbitrary_unref (ECardArbitrary *arbitrary);
-
-/* ECard email manipulation */
-gboolean e_card_email_match_string (const ECard *card,
- const gchar *str);
-gint e_card_email_find_number (const ECard *card,
- const gchar *email);
-
-/* Specialized functionality */
-GList *e_card_load_cards_from_file (const char *filename);
-GList *e_card_load_cards_from_file_with_default_charset (const char *filename,
- const char *default_charset);
-GList *e_card_load_cards_from_string (const char *str);
-GList *e_card_load_cards_from_string_with_default_charset (const char *str,
- const char *default_charset);
-void e_card_free_empty_lists (ECard *card);
-
-/* Getting ECards via their URIs */
-typedef void (*ECardCallback) (ECard *card, gpointer closure);
-void e_card_load_uri (const gchar *book_uri,
- const gchar *uid,
- ECardCallback cb,
- gpointer closure);
-
-
-GType e_card_get_type (void);
-
-#endif /* ! __E_CARD_H__ */
diff --git a/addressbook/backend/ebook/e-contact.c b/addressbook/backend/ebook/e-contact.c
new file mode 100644
index 0000000000..ce92b31f71
--- /dev/null
+++ b/addressbook/backend/ebook/e-contact.c
@@ -0,0 +1,1288 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* e-contact.c
+ *
+ * Copyright (C) 2003 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Chris Toshok (toshok@ximian.com)
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include "e-contact.h"
+#include "e-book.h"
+#include "e-util/ename/e-name-western.h"
+
+struct _EContactPrivate {
+};
+
+#define E_CONTACT_FIELD_TYPE_STRING 0x00000001 /* used for simple single valued attributes */
+/*E_CONTACT_FIELD_TYPE_FLOAT*/
+#define E_CONTACT_FIELD_TYPE_LIST 0x00000002 /* used for multivalued single attributes - the elements are of type char* */
+#define E_CONTACT_FIELD_TYPE_MULTI 0x00000004 /* used for multivalued attributes - the elements are of type EVCardAttribute */
+#define E_CONTACT_FIELD_TYPE_STRUCT 0x00000008 /* used for structured types (N and ADR properties, in particular) */
+#define E_CONTACT_FIELD_TYPE_BOOLEAN 0x00000010 /* used for boolean types (WANTS_HTML) */
+
+#define E_CONTACT_FIELD_TYPE_SYNTHETIC 0x10000000 /* used when there isn't a corresponding vcard field (such as email_1) */
+#define E_CONTACT_FIELD_TYPE_LIST_ELEM 0x20000000 /* used when a synthetic attribute is a numbered list element */
+#define E_CONTACT_FIELD_TYPE_MULTI_ELEM 0x40000000 /* used when we're looking for the nth attribute where more than 1 can be present in the vcard */
+#define E_CONTACT_FIELD_TYPE_ATTR_TYPE 0x80000000 /* used when a synthetic attribute is flagged with a TYPE= that we'll be looking for */
+
+typedef struct {
+ guint32 t;
+
+ EContactField field_id;
+ const char *vcard_field_name;
+ const char *field_name; /* non translated */
+ const char *pretty_name; /* translated */
+
+ gboolean read_only;
+
+ int list_elem;
+ const char *attr_type1;
+ const char *attr_type2;
+
+ void* (*struct_getter)(EContact *contact, EVCardAttribute *attribute);
+ void (*struct_setter)(EContact *contact, EVCardAttribute *attribute, void *data);
+
+} EContactFieldInfo;
+
+static void* photo_getter (EContact *contact, EVCardAttribute *attr);
+static void photo_setter (EContact *contact, EVCardAttribute *attr, void *data);
+static void* fn_getter (EContact *contact, EVCardAttribute *attr);
+static void fn_setter (EContact *contact, EVCardAttribute *attr, void *data);
+static void* n_getter (EContact *contact, EVCardAttribute *attr);
+static void n_setter (EContact *contact, EVCardAttribute *attr, void *data);
+static void* adr_getter (EContact *contact, EVCardAttribute *attr);
+static void adr_setter (EContact *contact, EVCardAttribute *attr, void *data);
+static void* date_getter (EContact *contact, EVCardAttribute *attr);
+static void date_setter (EContact *contact, EVCardAttribute *attr, void *data);
+
+#define STRING_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro) }
+#define BOOLEAN_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_BOOLEAN, (id), (vc), (n), (pn), (ro) }
+#define LIST_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_LIST, (id), (vc), (n), (pn), (ro) }
+#define MULTI_LIST_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_MULTI, (id), (vc), (n), (pn), (ro) }
+#define STRUCT_FIELD(id,vc,n,pn,ro,get,set) { E_CONTACT_FIELD_TYPE_STRUCT, (id), (vc), (n), (pn), (ro), -1, NULL, NULL, (get), (set) }
+#define LIST_ELEM_STR_FIELD(id,vc,n,pn,ro,nm) { E_CONTACT_FIELD_TYPE_LIST_ELEM | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nm) }
+#define MULTI_ELEM_STR_FIELD(id,vc,n,pn,ro,nm) { E_CONTACT_FIELD_TYPE_MULTI_ELEM | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nm) }
+#define ATTR_TYPE_STR_FIELD(id,vc,n,pn,ro,at1,nth) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nth), (at1), NULL }
+#define ATTR2_TYPE_STR_FIELD(id,vc,n,pn,ro,at1,at2,nth) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nth), (at1), (at2) }
+#define ATTR_TYPE_STRUCT_FIELD(id,vc,n,pn,ro,at,get,set) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRUCT, (id), (vc), (n), (pn), (ro), 0, (at), NULL, (get), (set) }
+
+static EContactFieldInfo field_info[] = {
+ STRING_FIELD (E_CONTACT_UID, EVC_UID, "id", N_("Unique ID"), FALSE),
+ STRING_FIELD (E_CONTACT_FILE_AS, EVC_X_FILE_AS, "file_as", N_("File As"), FALSE),
+
+ /* Name fields */
+ /* FN isn't really a structured field - we use a getter/setter
+ so we can set the N property (since evo 1.4 works fine with
+ vcards that don't even have a N attribute. *sigh*) */
+ STRUCT_FIELD (E_CONTACT_FULL_NAME, EVC_FN, "full_name", N_("Full Name"), FALSE, fn_getter, fn_setter),
+ STRUCT_FIELD (E_CONTACT_NAME, EVC_N, "name", N_("Name"), FALSE, n_getter, n_setter),
+ LIST_ELEM_STR_FIELD (E_CONTACT_GIVEN_NAME, EVC_N, "given_name", N_("Given Name"), FALSE, 1),
+ LIST_ELEM_STR_FIELD (E_CONTACT_FAMILY_NAME, EVC_N, "family_name", N_("Family Name"), FALSE, 0),
+ STRING_FIELD (E_CONTACT_NICKNAME, EVC_NICKNAME, "nickname", N_("Nickname"), FALSE),
+
+ /* Address fields */
+ MULTI_LIST_FIELD (E_CONTACT_ADDRESS, EVC_ADR, "address", N_("Address List"), FALSE),
+ ATTR_TYPE_STRUCT_FIELD (E_CONTACT_ADDRESS_HOME, EVC_ADR, "address_home", N_("Home Address"), FALSE, "HOME", adr_getter, adr_setter),
+ ATTR_TYPE_STRUCT_FIELD (E_CONTACT_ADDRESS_WORK, EVC_ADR, "address_work", N_("Work Address"), FALSE, "WORK", adr_getter, adr_setter),
+ ATTR_TYPE_STRUCT_FIELD (E_CONTACT_ADDRESS_OTHER, EVC_ADR, "address_other", N_("Other Address"), FALSE, "OTHER", adr_getter, adr_setter),
+
+ ATTR_TYPE_STR_FIELD (E_CONTACT_ADDRESS_LABEL_HOME, EVC_LABEL, "address_label_home", N_("Home Address Label"), FALSE, "HOME", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_ADDRESS_LABEL_WORK, EVC_LABEL, "address_label_work", N_("Work Address Label"), FALSE, "WORK", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_ADDRESS_LABEL_OTHER, EVC_LABEL, "address_label_other", N_("Other Address Label"), FALSE, "OTHER", 0),
+
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_ASSISTANT, EVC_TEL, "assistant_phone", N_("Assistant Phone"), FALSE, "X-EVOLUTION-ASSISTANT", 0),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_BUSINESS, EVC_TEL, "business_phone", N_("Business Phone"), FALSE, "WORK", "VOICE", 0),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_BUSINESS_2, EVC_TEL, "business_phone_2", N_("Business Phone 2"), FALSE, "WORK", "VOICE", 1),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_BUSINESS_FAX, EVC_TEL, "business_fax", N_("Business Fax"), FALSE, "WORK", "FAX", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_CALLBACK, EVC_TEL, "callback_phone", N_("Callback Phone"), FALSE, "X-EVOLUTION-CALLBACK", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_CAR, EVC_TEL, "car_phone", N_("Car Phone"), FALSE, "CAR", 0),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_COMPANY, EVC_TEL, "company_phone", N_("Company Phone"), FALSE, "WORK", "VOICE", 2),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_HOME, EVC_TEL, "home_phone", N_("Home Phone"), FALSE, "HOME", "VOICE", 0),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_HOME_2, EVC_TEL, "home_phone_2", N_("Home Phone 2"), FALSE, "HOME", "VOICE", 1),
+ ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_HOME_FAX, EVC_TEL, "home_fax", N_("Home Fax"), FALSE, "HOME", "FAX", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_ISDN, EVC_TEL, "isdn_phone", N_("ISDN"), FALSE, "ISDN", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_MOBILE, EVC_TEL, "mobile_phone", N_("Mobile Phone"), FALSE, "CELL", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_OTHER, EVC_TEL, "other_phone", N_("Other Phone"), FALSE, "VOICE", 0), /* XXX */
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_OTHER_FAX, EVC_TEL, "other_fax", N_("Other Fax"), FALSE, "FAX", 0), /* XXX */
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_PAGER, EVC_TEL, "pager", N_("Pager"), FALSE, "PAGER", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_PRIMARY, EVC_TEL, "primary_phone", N_("Primary Phone"), FALSE, "PREF", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_RADIO, EVC_TEL, "radio", N_("Radio"), FALSE, "X-EVOLUTION-RADIO", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_TELEX, EVC_TEL, "telex", N_("Telex"), FALSE, "X-EVOLUTION-TELEX", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_TTYTDD, EVC_TEL, "tty", N_("TTY"), FALSE, "X-EVOLUTION-TTYTDD", 0),
+
+ /* Email fields */
+ MULTI_LIST_FIELD (E_CONTACT_EMAIL, EVC_EMAIL, "email", N_("Email List"), FALSE),
+ MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_1, EVC_EMAIL, "email_1", N_("Email 1"), FALSE, 0),
+ MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_2, EVC_EMAIL, "email_2", N_("Email 2"), FALSE, 1),
+ MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_3, EVC_EMAIL, "email_3", N_("Email 3"), FALSE, 2),
+ STRING_FIELD (E_CONTACT_MAILER, EVC_MAILER, "mailer", N_("Mailer"), FALSE),
+ BOOLEAN_FIELD (E_CONTACT_WANTS_HTML, EVC_X_WANTS_HTML, "wants_html", N_("Wants HTML Mail"), FALSE),
+
+ /* Instant messaging fields */
+ LIST_FIELD (E_CONTACT_IM_AIM, EVC_X_AIM, "im_aim", N_("AIM Screen Name List"), FALSE),
+ LIST_FIELD (E_CONTACT_IM_JABBER, EVC_X_JABBER, "im_jabber", N_("Jabber Id List"), FALSE),
+ LIST_FIELD (E_CONTACT_IM_YAHOO, EVC_X_YAHOO, "im_yahoo", N_("Yahoo! Screen Name List"), FALSE),
+ LIST_FIELD (E_CONTACT_IM_MSN, EVC_X_MSN, "im_msn", N_("MSN Screen Name List"), FALSE),
+ LIST_FIELD (E_CONTACT_IM_ICQ, EVC_X_ICQ, "im_icq", N_("ICQ Id List"), FALSE),
+
+ /* Organizational fields */
+ LIST_ELEM_STR_FIELD (E_CONTACT_ORG, EVC_ORG, "org", N_("Organization"), FALSE, 0),
+ LIST_ELEM_STR_FIELD (E_CONTACT_ORG_UNIT, EVC_ORG, "org_unit", N_("Organizational Unit"), FALSE, 1),
+ LIST_ELEM_STR_FIELD (E_CONTACT_OFFICE, EVC_ORG, "office", N_("Office"), FALSE, 2),
+
+ STRING_FIELD (E_CONTACT_TITLE, EVC_TITLE, "title", N_("Title"), FALSE),
+ STRING_FIELD (E_CONTACT_ROLE, EVC_ROLE, "role", N_("Role"), FALSE),
+ STRING_FIELD (E_CONTACT_MANAGER, EVC_X_MANAGER, "manager", N_("Manager"), FALSE),
+ STRING_FIELD (E_CONTACT_ASSISTANT, EVC_X_ASSISTANT, "assistant", N_("Assistant"), FALSE),
+
+ /* Web fields */
+ STRING_FIELD (E_CONTACT_HOMEPAGE_URL, EVC_URL, "homepage_url", N_("Homepage URL"), FALSE),
+ STRING_FIELD (E_CONTACT_BLOG_URL, EVC_X_BLOG_URL, "blog_url", N_("Weblog URL"), FALSE),
+
+ /* Photo/Logo */
+ STRUCT_FIELD (E_CONTACT_PHOTO, EVC_PHOTO, "photo", N_("Photo"), FALSE, photo_getter, photo_setter),
+ STRUCT_FIELD (E_CONTACT_LOGO, EVC_LOGO, "logo", N_("Logo"), FALSE, photo_getter, photo_setter),
+
+ /* Contact categories */
+#if notyet
+ LIST_FIELD (E_CONTACT_CATEGORY_LIST, EVC_CATEGORIES, "category_list", N_("Category List"), FALSE),
+ SYNTH_STR_FIELD (E_CONTACT_CATEGORIES, "categories", N_("Categories"), FALSE),
+#else
+ STRING_FIELD (E_CONTACT_CATEGORIES, EVC_CATEGORIES, "categories", N_("Categories"), FALSE),
+#endif
+
+ /* Collaboration fields */
+ STRING_FIELD (E_CONTACT_CALENDAR_URI, EVC_CALURI, "caluri", N_("Calendar URI"), FALSE),
+ STRING_FIELD (E_CONTACT_FREEBUSY_URL, EVC_FBURL, "fburl", N_("Free/Busy URL"), FALSE),
+ STRING_FIELD (E_CONTACT_ICS_CALENDAR, EVC_ICSCALENDAR, "icscalendar", N_("ICS Calendar"), FALSE),
+
+ /* Misc fields */
+ STRING_FIELD (E_CONTACT_SPOUSE, EVC_X_SPOUSE, "spouse", N_("Spouse's Name"), FALSE),
+ STRING_FIELD (E_CONTACT_NOTE, EVC_NOTE, "note", N_("Note"), FALSE),
+
+ STRUCT_FIELD (E_CONTACT_BIRTH_DATE, EVC_BDAY, "birth_date", N_("Birth Date"), FALSE, date_getter, date_setter),
+ STRUCT_FIELD (E_CONTACT_ANNIVERSARY, EVC_BDAY, "anniversary", N_("Anniversary"), FALSE, date_getter, date_setter),
+
+ BOOLEAN_FIELD (E_CONTACT_IS_LIST, EVC_X_LIST, "list", N_("List"), FALSE),
+ BOOLEAN_FIELD (E_CONTACT_LIST_SHOW_ADDRESSES, EVC_X_LIST_SHOW_ADDRESSES, "list_show_addresses", N_("List Show Addresses"), FALSE)
+};
+
+#undef LIST_ELEM_STR_FIELD
+#undef STRING_FIELD
+#undef SYNTH_STR_FIELD
+#undef LIST_FIELD
+#undef STRUCT_FIELD
+
+static GObjectClass *parent_class;
+
+static void e_contact_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void e_contact_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static void
+e_contact_dispose (GObject *object)
+{
+ EContact *ec = E_CONTACT (object);
+
+ if (!ec->priv)
+ return;
+
+ /* XXX free instance specific stuff */
+
+ g_free (ec->priv);
+ ec->priv = NULL;
+
+ if (G_OBJECT_CLASS (parent_class)->dispose)
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+e_contact_class_init (EContactClass *klass)
+{
+ GObjectClass *object_class;
+ int i;
+
+ object_class = G_OBJECT_CLASS(klass);
+
+ parent_class = g_type_class_ref (E_TYPE_VCARD);
+
+ object_class->dispose = e_contact_dispose;
+ object_class->set_property = e_contact_set_property;
+ object_class->get_property = e_contact_get_property;
+
+ for (i = 0; i < G_N_ELEMENTS (field_info); i ++) {
+ GParamSpec *pspec = NULL;
+ if (field_info[i].t & E_CONTACT_FIELD_TYPE_STRING)
+ pspec = g_param_spec_string (field_info[i].field_name,
+ _(field_info[i].pretty_name),
+ "" /* XXX blurb */,
+ NULL,
+ field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE);
+ else if (field_info[i].t & E_CONTACT_FIELD_TYPE_BOOLEAN)
+ pspec = g_param_spec_boolean (field_info[i].field_name,
+ _(field_info[i].pretty_name),
+ "" /* XXX blurb */,
+ FALSE,
+ field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE);
+ else
+ pspec = g_param_spec_pointer (field_info[i].field_name,
+ _(field_info[i].pretty_name),
+ "" /* XXX blurb */,
+ field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE);
+
+ g_object_class_install_property (object_class, field_info[i].field_id,
+ pspec);
+ }
+}
+
+static void
+e_contact_init (EContact *ec)
+{
+ ec->priv = g_new0 (EContactPrivate, 1);
+}
+
+GType
+e_contact_get_type (void)
+{
+ static GType contact_type = 0;
+
+ if (!contact_type) {
+ static const GTypeInfo contact_info = {
+ sizeof (EContactClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) e_contact_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EContact),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_contact_init,
+ };
+
+ contact_type = g_type_register_static (E_TYPE_VCARD, "EContact", &contact_info, 0);
+ }
+
+ return contact_type;
+}
+
+static EVCardAttribute*
+e_contact_get_first_attr (EContact *contact, const char *attr_name)
+{
+ GList *attrs, *l;
+
+ attrs = e_vcard_get_attributes (E_VCARD (contact));
+
+ for (l = attrs; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ const char *name, *group;
+
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, attr_name))
+ return attr;
+ }
+
+ return NULL;
+}
+
+
+
+static void*
+photo_getter (EContact *contact, EVCardAttribute *attr)
+{
+ if (attr) {
+ GList *values = e_vcard_attribute_get_values_decoded (attr);
+
+ if (values && values->data) {
+ GString *s = values->data;
+ EContactPhoto *photo = g_new (EContactPhoto, 1);
+
+ photo->length = s->len;
+ photo->data = g_malloc (photo->length);
+ memcpy (photo->data, s->str, photo->length);
+
+ return photo;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+photo_setter (EContact *contact, EVCardAttribute *attr, void *data)
+{
+ EContactPhoto *photo = data;
+ const char *mime_type;
+ char *image_type = "X-EVOLUTION-UNKNOWN";
+
+ e_vcard_attribute_add_param_with_value (attr,
+ e_vcard_attribute_param_new (EVC_ENCODING),
+ "b");
+
+ mime_type = gnome_vfs_get_mime_type_for_data (photo->data, photo->length);
+ if (!strcmp (mime_type, "image/gif"))
+ image_type = "GIF";
+ else if (!strcmp (mime_type, "image/jpeg"))
+ image_type = "JPEG";
+ else if (!strcmp (mime_type, "image/png"))
+ image_type = "PNG";
+ else if (!strcmp (mime_type, "image/tiff"))
+ image_type = "TIFF";
+ /* i have no idea what these last 2 are.. :) */
+ else if (!strcmp (mime_type, "image/ief"))
+ image_type = "IEF";
+ else if (!strcmp (mime_type, "image/cgm"))
+ image_type = "CGM";
+
+ e_vcard_attribute_add_param_with_value (attr,
+ e_vcard_attribute_param_new (EVC_TYPE),
+ image_type);
+
+ printf ("adding photo of type `%s' of length %d\n", image_type, photo->length);
+ e_vcard_attribute_add_value_decoded (attr, photo->data, photo->length);
+}
+
+
+static void*
+fn_getter (EContact *contact, EVCardAttribute *attr)
+{
+ if (attr) {
+ GList *p = e_vcard_attribute_get_values (attr);
+
+ return g_strdup (p && p->data ? p->data : "");
+ }
+ else
+ return NULL;
+}
+
+static void
+fn_setter (EContact *contact, EVCardAttribute *attr, void *data)
+{
+ e_vcard_attribute_add_value (attr, (char*)data);
+
+ attr = e_contact_get_first_attr (contact, EVC_N);
+ if (!attr) {
+ EContactName *name = e_contact_name_from_string ((char*)data);
+
+ attr = e_vcard_attribute_new (NULL, EVC_N);
+ e_vcard_add_attribute (E_VCARD (contact), attr);
+
+ /* call the setter directly */
+ n_setter (contact, attr, name);
+
+ e_contact_name_free (name);
+ }
+}
+
+
+
+static void*
+n_getter (EContact *contact, EVCardAttribute *attr)
+{
+ EContactName *name = g_new0 (EContactName, 1);
+ if (attr) {
+ GList *p = e_vcard_attribute_get_values (attr);
+
+ name->family = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ name->given = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ name->additional = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ name->prefixes = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ name->suffixes = g_strdup (p && p->data ? p->data : "");
+ }
+
+ return name;
+}
+
+static void
+n_setter (EContact *contact, EVCardAttribute *attr, void *data)
+{
+ EContactName *name = data;
+
+ e_vcard_attribute_add_value (attr, name->family);
+ e_vcard_attribute_add_value (attr, name->given);
+ e_vcard_attribute_add_value (attr, name->additional);
+ e_vcard_attribute_add_value (attr, name->prefixes);
+ e_vcard_attribute_add_value (attr, name->suffixes);
+
+ /* now find the attribute for FileAs. if it's not present, fill it in */
+ attr = e_contact_get_first_attr (contact, EVC_X_FILE_AS);
+ if (!attr) {
+ char *strings[3], **stringptr;
+ char *string;
+ attr = e_vcard_attribute_new (NULL, EVC_X_FILE_AS);
+ e_vcard_add_attribute (E_VCARD (contact), attr);
+
+ stringptr = strings;
+ if (name->family && *name->family)
+ *(stringptr++) = name->family;
+ if (name->given && *name->given)
+ *(stringptr++) = name->given;
+ *stringptr = NULL;
+ string = g_strjoinv(", ", strings);
+
+ e_vcard_attribute_add_value (attr, string);
+ g_free (string);
+ }
+
+}
+
+
+
+static void*
+adr_getter (EContact *contact, EVCardAttribute *attr)
+{
+ if (attr) {
+ GList *p = e_vcard_attribute_get_values (attr);
+ EContactAddress *addr = g_new (EContactAddress, 1);
+
+ addr->po = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ addr->ext = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ addr->street = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ addr->locality = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ addr->region = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ addr->code = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+ addr->country = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
+
+ return addr;
+ }
+
+ return NULL;
+}
+
+static void
+adr_setter (EContact *contact, EVCardAttribute *attr, void *data)
+{
+ /* XXX */
+ g_assert_not_reached ();
+}
+
+
+
+static void*
+date_getter (EContact *contact, EVCardAttribute *attr)
+{
+ if (attr) {
+ GList *p = e_vcard_attribute_get_values (attr);
+ EContactDate *date = e_contact_date_from_string (p && p->data ? (char*)p->data : "");
+
+ return date;
+ }
+
+ return NULL;
+}
+
+static void
+date_setter (EContact *contact, EVCardAttribute *attr, void *data)
+{
+ EContactDate *date = data;
+ char *str = e_contact_date_to_string (date);
+
+ e_vcard_attribute_add_value (attr, str);
+ g_free (str);
+}
+
+
+
+/* Set_arg handler for the contact */
+static void
+e_contact_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EContact *contact = E_CONTACT (object);
+ int i;
+ EContactFieldInfo *info = NULL;
+
+ if (prop_id < 1 || prop_id >= E_CONTACT_FIELD_LAST) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ return;
+ }
+
+
+ for (i = 0; i < G_N_ELEMENTS (field_info); i++) {
+ if (field_info[i].field_id == prop_id) {
+ info = &field_info[i];
+ break;
+ }
+ }
+
+ if (!info) {
+ g_warning ("unknown field %d", prop_id);
+ return;
+ }
+
+ if (info->t & E_CONTACT_FIELD_TYPE_MULTI) {
+ GList *new_values = g_value_get_pointer (value);
+ GList *l;
+
+ /* first we remove all attributes of the type we're
+ adding, then add new ones based on the values that
+ are passed in */
+ e_vcard_remove_attributes (E_VCARD (contact), NULL, info->vcard_field_name);
+
+ for (l = new_values; l; l = l->next)
+ e_vcard_add_attribute_with_value (E_VCARD (contact),
+ e_vcard_attribute_new (NULL, info->vcard_field_name),
+ (char*)l->data);
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_SYNTHETIC) {
+ if (info->t & E_CONTACT_FIELD_TYPE_MULTI_ELEM) {
+ /* XXX this is kinda broken - we don't insert
+ insert padding elements if, e.g. the user
+ sets email 3 when email 1 and 2 don't
+ exist. But, if we *did* pad the lists we'd
+ end up with empty items in the vcard. I
+ dunno which is worse. */
+ EVCardAttribute *attr = NULL;
+ gboolean found = FALSE;
+ int num_left = info->list_elem;
+ GList *attrs = e_vcard_get_attributes (E_VCARD (contact));
+ GList *l;
+
+ for (l = attrs; l; l = l->next) {
+ const char *name, *group;
+
+ attr = l->data;
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, info->vcard_field_name)) {
+ if (num_left-- == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ /* we found it, overwrite it */
+ e_vcard_attribute_remove_values (attr);
+ }
+ else {
+ /* we didn't find it - add a new attribute */
+ attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
+ e_vcard_add_attribute (E_VCARD (contact), attr);
+ }
+
+ e_vcard_attribute_add_value (attr, g_value_get_string (value));
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_ATTR_TYPE) {
+ /* XXX this is kinda broken - we don't insert
+ insert padding elements if, e.g. the user
+ sets email 3 when email 1 and 2 don't
+ exist. But, if we *did* pad the lists we'd
+ end up with empty items in the vcard. I
+ dunno which is worse. */
+ EVCardAttribute *attr = NULL;
+ gboolean found = FALSE;
+ int num_left = info->list_elem;
+ GList *attrs = e_vcard_get_attributes (E_VCARD (contact));
+ GList *l;
+ const char *sval = g_value_get_string (value);
+
+ for (l = attrs; l && !found; l = l->next) {
+ const char *name, *group;
+ gboolean found_needed1, found_needed2;
+
+ if (!info->attr_type1)
+ found_needed1 = TRUE;
+ else
+ found_needed1 = FALSE;
+
+ if (!info->attr_type2)
+ found_needed2 = TRUE;
+ else
+ found_needed2 = FALSE;
+
+ attr = l->data;
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, info->vcard_field_name)) {
+ GList *params;
+
+ for (params = e_vcard_attribute_get_params (attr); params; params = params->next) {
+ EVCardAttributeParam *param = params->data;
+ const char *name = e_vcard_attribute_param_get_name (param);
+
+ if (!strcasecmp (name, EVC_TYPE)) {
+ GList *values = e_vcard_attribute_param_get_values (param);
+ if (values && values->data) {
+ if (!found_needed1 && !strcasecmp ((char*)values->data, info->attr_type1))
+ found_needed1 = TRUE;
+ else if (!found_needed2 && !strcasecmp ((char*)values->data, info->attr_type2))
+ found_needed2 = TRUE;
+ }
+ }
+
+ if (found_needed1 && found_needed2) {
+ if (num_left-- == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (found) {
+ /* we found it, overwrite it */
+ e_vcard_attribute_remove_values (attr);
+ }
+ else {
+ /* we didn't find it - add a new attribute */
+ attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
+ e_vcard_add_attribute (E_VCARD (contact), attr);
+ if (info->attr_type1)
+ e_vcard_attribute_add_param_with_value (attr, e_vcard_attribute_param_new (EVC_TYPE),
+ info->attr_type1);
+ if (info->attr_type2)
+ e_vcard_attribute_add_param_with_value (attr, e_vcard_attribute_param_new (EVC_TYPE),
+ info->attr_type2);
+ }
+
+ if (sval && *sval)
+ e_vcard_attribute_add_value (attr, sval);
+ else
+ e_vcard_remove_attribute (E_VCARD (contact), attr);
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_LIST_ELEM) {
+ EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+ GList *values;
+ GList *p;
+ const char *sval = g_value_get_string (value);
+
+ if (!attr) {
+ if (!sval || !*sval)
+ return;
+
+ printf ("adding new %s\n", info->vcard_field_name);
+
+ attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
+ e_vcard_add_attribute (E_VCARD (contact), attr);
+ }
+
+ values = e_vcard_attribute_get_values (attr);
+ p = g_list_nth (values, info->list_elem);
+
+ if (p) {
+ g_free (p->data);
+ p->data = g_strdup (g_value_get_string (value));
+ }
+ else {
+ /* there weren't enough elements in the list, pad it */
+ int count = info->list_elem - g_list_length (values);
+
+ while (count--)
+ e_vcard_attribute_add_value (attr, "");
+
+ e_vcard_attribute_add_value (attr, g_value_get_string (value));
+ }
+
+ }
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
+ EVCardAttribute *attr;
+
+ /* first we search for an attribute we can overwrite */
+ attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+ if (attr) {
+ printf ("setting %s to `%s'\n", info->vcard_field_name, g_value_get_string (value));
+ e_vcard_attribute_remove_values (attr);
+ e_vcard_attribute_add_value (attr, g_value_get_boolean (value) ? "TRUE" : "FALSE");
+ }
+ else {
+ /* and if we don't find one we create a new attribute */
+ e_vcard_add_attribute_with_value (E_VCARD (contact),
+ e_vcard_attribute_new (NULL, info->vcard_field_name),
+ g_value_get_boolean (value) ? "TRUE" : "FALSE");
+ }
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
+ EVCardAttribute *attr;
+ const char *sval = g_value_get_string (value);
+
+ /* first we search for an attribute we can overwrite */
+ attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+ if (attr) {
+ printf ("setting %s to `%s'\n", info->vcard_field_name, sval);
+ e_vcard_attribute_remove_values (attr);
+ if (sval)
+ e_vcard_attribute_add_value (attr, sval);
+ }
+ else if (sval) {
+ /* and if we don't find one we create a new attribute */
+ e_vcard_add_attribute_with_value (E_VCARD (contact),
+ e_vcard_attribute_new (NULL, info->vcard_field_name),
+ g_value_get_string (value));
+ }
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_STRUCT) {
+ EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+ void *data = g_value_get_pointer (value);
+
+ if (attr) {
+ printf ("overwriting existing %s\n", info->vcard_field_name);
+ /* remove all existing values and parameters.
+ the setter will add the correct ones */
+ e_vcard_attribute_remove_values (attr);
+ e_vcard_attribute_remove_params (attr);
+ }
+ else {
+ printf ("adding new %s\n", info->vcard_field_name);
+ attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
+
+ e_vcard_add_attribute (E_VCARD (contact), attr);
+ }
+
+ info->struct_setter (contact, attr, data);
+ }
+ else {
+ g_warning ("unhandled attribute `%s'", info->vcard_field_name);
+ }
+}
+
+static GList *
+e_contact_get_email_list (EContact *contact)
+{
+ GList *rv = NULL;
+ GList *attrs, *l;
+
+ attrs = e_vcard_get_attributes (E_VCARD (contact));
+
+ for (l = attrs; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ const char *name, *group;
+
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, EVC_EMAIL)) {
+ GList *v = e_vcard_attribute_get_values (attr);
+
+ rv = g_list_append (rv, v ? g_strdup (v->data) : NULL);
+ }
+ }
+
+ return rv;
+}
+
+static EVCardAttribute *
+e_contact_find_attribute_with_types (EContact *contact, const char *attr_name, const char *type_needed1, const char *type_needed2, int nth)
+{
+ GList *l, *attrs;
+ gboolean found_needed1, found_needed2;
+
+ attrs = e_vcard_get_attributes (E_VCARD (contact));
+
+ for (l = attrs; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ const char *name, *group;
+
+ if (!type_needed1)
+ found_needed1 = TRUE;
+ else
+ found_needed1 = FALSE;
+
+ if (!type_needed2)
+ found_needed2 = TRUE;
+ else
+ found_needed2 = FALSE;
+
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, attr_name)) {
+ GList *params;
+
+ for (params = e_vcard_attribute_get_params (attr); params; params = params->next) {
+ EVCardAttributeParam *param = params->data;
+ const char *name = e_vcard_attribute_param_get_name (param);
+
+ if (!strcasecmp (name, EVC_TYPE)) {
+ GList *values = e_vcard_attribute_param_get_values (param);
+ if (values && values->data) {
+ if (!found_needed1 && !strcasecmp ((char*)values->data, type_needed1))
+ found_needed1 = TRUE;
+ else if (!found_needed2 && !strcasecmp ((char*)values->data, type_needed2))
+ found_needed2 = TRUE;
+ }
+ }
+
+ if (found_needed1 && found_needed2) {
+ if (nth-- == 0)
+ return attr;
+ else
+ break;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void
+e_contact_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EContact *contact = E_CONTACT (object);
+ int i;
+ EContactFieldInfo *info = NULL;
+
+ if (prop_id < 1 || prop_id >= E_CONTACT_FIELD_LAST) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ return;
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (field_info); i++) {
+ if (field_info[i].field_id == prop_id) {
+ info = &field_info[i];
+ break;
+ }
+ }
+
+ if (!info) {
+ g_warning ("unknown field %d", prop_id);
+ return;
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
+ EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+ gboolean rv = FALSE;
+
+ if (attr) {
+ GList *v = e_vcard_attribute_get_values (attr);
+ rv = v && v->data && !strcasecmp ((char*)v->data, "true");
+ }
+
+ g_value_set_boolean (value, rv);
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_LIST) {
+ EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+
+ if (attr)
+ g_value_set_pointer (value, e_vcard_attribute_get_values (attr));
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_LIST_ELEM) {
+ if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
+ GList *attrs, *l;
+
+ attrs = e_vcard_get_attributes (E_VCARD (contact));
+
+ for (l = attrs; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ const char *name, *group;
+
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, info->vcard_field_name)) {
+ GList *v;
+ int count;
+
+ v = e_vcard_attribute_get_values (attr);
+ count = info->list_elem;
+
+ v = g_list_nth (v, info->list_elem);
+
+ g_value_set_string (value, v ? v->data : NULL);
+ }
+ }
+ }
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_MULTI_ELEM) {
+ if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
+ GList *attrs, *l;
+
+ attrs = e_vcard_get_attributes (E_VCARD (contact));
+
+ for (l = attrs; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ const char *name, *group;
+
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, info->vcard_field_name)) {
+ GList *v;
+ int count;
+
+ v = e_vcard_attribute_get_values (attr);
+ count = info->list_elem;
+
+ v = g_list_nth (v, info->list_elem);
+
+ g_value_set_string (value, v ? v->data : NULL);
+ }
+ }
+ }
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_ATTR_TYPE) {
+ EVCardAttribute *attr = e_contact_find_attribute_with_types (contact, info->vcard_field_name, info->attr_type1, info->attr_type2, info->list_elem);
+
+ if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
+ if (attr) {
+ GList *p = e_vcard_attribute_get_values (attr);
+ char *rv = p->data;
+
+ g_value_set_string (value, rv);
+ }
+ else {
+ g_value_set_string (value, NULL);
+ }
+ }
+ else { /* struct */
+ gpointer rv = info->struct_getter (contact, attr);
+
+ g_value_set_pointer (value, rv);
+ }
+
+ }
+ else if (info->t & E_CONTACT_FIELD_TYPE_STRUCT) {
+ EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
+ void *rv = NULL;
+
+ if (attr)
+ rv = info->struct_getter (contact, attr);
+
+ g_value_set_pointer (value, rv);
+ }
+
+ else if (info->t & E_CONTACT_FIELD_TYPE_SYNTHETIC) {
+ switch (info->field_id) {
+ default:
+ g_warning ("unhandled synthetic field 0x%02x", info->field_id);
+ }
+ }
+ else {
+ GList *attrs, *l;
+ GList *rv = NULL; /* used for multi attribute lists */
+
+ attrs = e_vcard_get_attributes (E_VCARD (contact));
+
+ for (l = attrs; l; l = l->next) {
+ EVCardAttribute *attr = l->data;
+ const char *name, *group;
+
+ group = e_vcard_attribute_get_group (attr);
+ name = e_vcard_attribute_get_name (attr);
+
+ /* all the attributes we care about should be in group "" */
+ if ((!group || !*group) && !strcasecmp (name, info->vcard_field_name)) {
+ GList *v;
+ v = e_vcard_attribute_get_values (attr);
+
+ if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
+ g_value_set_string (value, v ? v->data : NULL);
+ }
+ else {
+ rv = g_list_append (rv, v ? g_strdup (v->data) : NULL);
+
+ g_value_set_pointer (value, rv);
+ }
+ }
+ }
+ }
+}
+
+
+
+EContact*
+e_contact_new (void)
+{
+ return e_contact_new_from_vcard ("");
+}
+
+EContact*
+e_contact_new_from_vcard (const char *vcard)
+{
+ EContact *contact = g_object_new (E_TYPE_CONTACT, NULL);
+
+ e_vcard_construct (E_VCARD (contact), vcard);
+
+ return contact;
+}
+
+EContact*
+e_contact_duplicate (EContact *contact)
+{
+ char *vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+ EContact *c = e_contact_new_from_vcard (vcard);
+
+ g_free (vcard);
+
+ return c;
+}
+
+const char *
+e_contact_field_name (EContactField field_id)
+{
+ int i;
+
+ g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, "");
+
+ for (i = 0; i < G_N_ELEMENTS (field_info); i ++) {
+ if (field_id == field_info[i].field_id)
+ return field_info[i].field_name;
+ }
+
+ g_warning ("unknown field id %d", field_id);
+ return "";
+}
+
+const char *
+e_contact_pretty_name (EContactField field_id)
+{
+ int i;
+
+ g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, "");
+
+ for (i = 0; i < G_N_ELEMENTS (field_info); i ++) {
+ if (field_id == field_info[i].field_id)
+ return _(field_info[i].pretty_name);
+ }
+
+ g_warning ("unknown field id %d", field_id);
+ return "";
+}
+
+EContactField
+e_contact_field_id (const char *field_name)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (field_info); i ++) {
+ if (!strcmp (field_info[i].field_name, field_name))
+ return field_info[i].field_id;
+ }
+
+ g_warning ("unknown field name `%s'", field_name);
+ return 0;
+}
+
+gpointer
+e_contact_get (EContact *contact, EContactField field_id)
+{
+ gpointer value;
+
+ g_return_val_if_fail (contact && E_IS_CONTACT (contact), NULL);
+ g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, NULL);
+
+ g_object_get (contact,
+ e_contact_field_name (field_id), &value,
+ NULL);
+
+ return value;
+}
+
+/* XXX this won't work for structure/list types... */
+static void
+free_const_data (gpointer data, GObject *where_object_was)
+{
+ g_free (data);
+}
+
+const gpointer
+e_contact_get_const (EContact *contact, EContactField field_id)
+{
+ gpointer value;
+
+ g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
+ g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, NULL);
+
+ value = e_contact_get (contact, field_id);
+
+ g_object_weak_ref (G_OBJECT (contact), free_const_data, value);
+
+ return value;
+}
+
+void
+e_contact_set (EContact *contact, EContactField field_id, gpointer value)
+{
+ printf ("e_contact_set (%p, %d, %p)\n", contact, field_id, value);
+
+ g_return_if_fail (contact && E_IS_CONTACT (contact));
+ g_return_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST);
+
+ g_object_set (contact,
+ e_contact_field_name (field_id), value,
+ NULL);
+}
+
+EContactName*
+e_contact_name_new ()
+{
+ return g_new0 (EContactName, 1);
+}
+
+char *
+e_contact_name_to_string(const EContactName *name)
+{
+ char *strings[6], **stringptr = strings;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ if (name->prefixes && *name->prefixes)
+ *(stringptr++) = name->prefixes;
+ if (name->given && *name->given)
+ *(stringptr++) = name->given;
+ if (name->additional && *name->additional)
+ *(stringptr++) = name->additional;
+ if (name->family && *name->family)
+ *(stringptr++) = name->family;
+ if (name->suffixes && *name->suffixes)
+ *(stringptr++) = name->suffixes;
+ *stringptr = NULL;
+ return g_strjoinv(" ", strings);
+}
+
+EContactName*
+e_contact_name_from_string (const char *name_str)
+{
+ EContactName *name = e_contact_name_new();
+ ENameWestern *western = e_name_western_parse (name_str);
+
+ name->prefixes = g_strdup (western->prefix);
+ name->given = g_strdup (western->first );
+ name->additional = g_strdup (western->middle);
+ name->family = g_strdup (western->last );
+ name->suffixes = g_strdup (western->suffix);
+
+ e_name_western_free(western);
+
+ return name;
+}
+
+EContactName*
+e_contact_name_copy (EContactName *n)
+{
+ EContactName *name = e_contact_name_new();
+
+ name->prefixes = g_strdup (n->prefixes);
+ name->given = g_strdup (n->given);
+ name->additional = g_strdup (n->additional);
+ name->family = g_strdup (n->family);
+ name->suffixes = g_strdup (n->suffixes);
+
+ return name;
+}
+
+void
+e_contact_name_free (EContactName *name)
+{
+ if (!name)
+ return;
+
+ g_free (name->family);
+ g_free (name->given);
+ g_free (name->additional);
+ g_free (name->prefixes);
+ g_free (name->suffixes);
+
+ g_free (name);
+}
+
+EContactDate*
+e_contact_date_new (void)
+{
+ return g_new0 (EContactDate, 1);
+}
+
+EContactDate*
+e_contact_date_from_string (const char *str)
+{
+ EContactDate* date = e_contact_date_new();
+ int length;
+
+ length = strlen(str);
+
+ if (length == 10 ) {
+ date->year = str[0] * 1000 + str[1] * 100 + str[2] * 10 + str[3] - '0' * 1111;
+ date->month = str[5] * 10 + str[6] - '0' * 11;
+ date->day = str[8] * 10 + str[9] - '0' * 11;
+ } else if ( length == 8 ) {
+ date->year = str[0] * 1000 + str[1] * 100 + str[2] * 10 + str[3] - '0' * 1111;
+ date->month = str[4] * 10 + str[5] - '0' * 11;
+ date->day = str[6] * 10 + str[7] - '0' * 11;
+ }
+
+ return date;
+}
+
+char *
+e_contact_date_to_string (EContactDate *dt)
+{
+ if (dt)
+ return g_strdup_printf ("%04d-%02d-%02d",
+ CLAMP(dt->year, 1000, 9999),
+ CLAMP(dt->month, 1, 12),
+ CLAMP(dt->day, 1, 31));
+ else
+ return NULL;
+}
+
+void
+e_contact_date_free (EContactDate *dt)
+{
+ g_free (dt);
+}
+
+
+void
+e_contact_photo_free (EContactPhoto *photo)
+{
+ if (!photo)
+ return;
+
+ g_free (photo->data);
+ g_free (photo);
+}
+
+void
+e_contact_address_free (EContactAddress *address)
+{
+ if (!address)
+ return;
+
+ g_free (address->address_format);
+ g_free (address->po);
+ g_free (address->ext);
+ g_free (address->street);
+ g_free (address->locality);
+ g_free (address->region);
+ g_free (address->code);
+ g_free (address->country);
+
+ g_free (address);
+}
diff --git a/addressbook/backend/ebook/e-contact.h b/addressbook/backend/ebook/e-contact.h
new file mode 100644
index 0000000000..8de02caa5f
--- /dev/null
+++ b/addressbook/backend/ebook/e-contact.h
@@ -0,0 +1,227 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Chris Toshok <toshok@ximian.com>
+ *
+ * Copyright (C) 2003 Ximian, Inc.
+ */
+
+#ifndef __E_CONTACT_H__
+#define __E_CONTACT_H__
+
+#include <time.h>
+#include <glib-object.h>
+#include <stdio.h>
+#include <ebook/e-vcard.h>
+
+#define E_TYPE_CONTACT (e_contact_get_type ())
+#define E_CONTACT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CONTACT, EContact))
+#define E_CONTACT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CONTACT, EContactClass))
+#define E_IS_CONTACT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CONTACT))
+#define E_IS_CONTACT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CONTACT))
+#define E_CONTACT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CONTACT, EContactClass))
+
+typedef struct _EContact EContact;
+typedef struct _EContactClass EContactClass;
+typedef struct _EContactPrivate EContactPrivate;
+
+typedef enum {
+
+ E_CONTACT_UID = 1, /* string field */
+ E_CONTACT_FILE_AS, /* string field */
+
+ /* Name fields */
+ E_CONTACT_FULL_NAME, /* string field */
+ E_CONTACT_GIVEN_NAME, /* synthetic string field */
+ E_CONTACT_FAMILY_NAME, /* synthetic string field */
+ E_CONTACT_NICKNAME, /* string field */
+
+ /* Email fields */
+ E_CONTACT_EMAIL_1, /* synthetic string field */
+ E_CONTACT_EMAIL_2, /* synthetic string field */
+ E_CONTACT_EMAIL_3, /* synthetic string field */
+
+ E_CONTACT_MAILER, /* string field */
+
+ /* Address Labels */
+ E_CONTACT_ADDRESS_LABEL_HOME, /* synthetic string field */
+ E_CONTACT_ADDRESS_LABEL_WORK, /* synthetic string field */
+ E_CONTACT_ADDRESS_LABEL_OTHER, /* synthetic string field */
+
+ /* Phone fields */
+ E_CONTACT_PHONE_ASSISTANT,
+ E_CONTACT_PHONE_BUSINESS,
+ E_CONTACT_PHONE_BUSINESS_2,
+ E_CONTACT_PHONE_BUSINESS_FAX,
+ E_CONTACT_PHONE_CALLBACK,
+ E_CONTACT_PHONE_CAR,
+ E_CONTACT_PHONE_COMPANY,
+ E_CONTACT_PHONE_HOME,
+ E_CONTACT_PHONE_HOME_2,
+ E_CONTACT_PHONE_HOME_FAX,
+ E_CONTACT_PHONE_ISDN,
+ E_CONTACT_PHONE_MOBILE,
+ E_CONTACT_PHONE_OTHER,
+ E_CONTACT_PHONE_OTHER_FAX,
+ E_CONTACT_PHONE_PAGER,
+ E_CONTACT_PHONE_PRIMARY,
+ E_CONTACT_PHONE_RADIO,
+ E_CONTACT_PHONE_TELEX,
+ E_CONTACT_PHONE_TTYTDD,
+
+ /* Organizational fields */
+ E_CONTACT_ORG, /* string field */
+ E_CONTACT_ORG_UNIT, /* string field */
+ E_CONTACT_OFFICE, /* string field */
+ E_CONTACT_TITLE, /* string field */
+ E_CONTACT_ROLE, /* string field */
+ E_CONTACT_MANAGER, /* string field */
+ E_CONTACT_ASSISTANT, /* string field */
+
+ /* Web fields */
+ E_CONTACT_HOMEPAGE_URL, /* string field */
+ E_CONTACT_BLOG_URL, /* string field */
+
+ /* Contact categories */
+ E_CONTACT_CATEGORIES, /* string field */
+
+ /* Collaboration fields */
+ E_CONTACT_CALENDAR_URI, /* string field */
+ E_CONTACT_FREEBUSY_URL, /* string field */
+ E_CONTACT_ICS_CALENDAR, /* string field */
+
+ /* misc fields */
+ E_CONTACT_SPOUSE, /* string field */
+ E_CONTACT_NOTE, /* string field */
+
+ /* fields used for describing contact lists. a contact list
+ is just a contact with _IS_LIST set to true. the members
+ are listed in the _EMAIL field. */
+ E_CONTACT_IS_LIST, /* boolean field */
+ E_CONTACT_LIST_SHOW_ADDRESSES, /* boolean field */
+
+ /* Instant Messaging fields */
+ E_CONTACT_IM_AIM, /* Multi-valued */
+ E_CONTACT_IM_JABBER, /* Multi-valued */
+ E_CONTACT_IM_YAHOO, /* Multi-valued */
+ E_CONTACT_IM_MSN, /* Multi-valued */
+ E_CONTACT_IM_ICQ, /* Multi-valued */
+
+ /* Address fields */
+ E_CONTACT_ADDRESS, /* Multi-valued structured (EContactAddress) */
+ E_CONTACT_ADDRESS_HOME, /* synthetic structured field (EContactAddress) */
+ E_CONTACT_ADDRESS_WORK, /* synthetic structured field (EContactAddress) */
+ E_CONTACT_ADDRESS_OTHER, /* synthetic structured field (EContactAddress) */
+
+ E_CONTACT_CATEGORY_LIST, /* multi-valued */
+
+ /* Photo/Logo */
+ E_CONTACT_PHOTO, /* structured field (EContactPhoto) */
+ E_CONTACT_LOGO, /* structured field (EContactPhoto) */
+
+ E_CONTACT_NAME, /* structured field (EContactName) */
+ E_CONTACT_EMAIL, /* Multi-valued */
+
+ E_CONTACT_WANTS_HTML, /* boolean field */
+
+ E_CONTACT_BIRTH_DATE, /* structured field (EContactDate) */
+ E_CONTACT_ANNIVERSARY, /* structured field (EContactDate) */
+
+ E_CONTACT_FIELD_LAST,
+
+ /* useful constants */
+ E_CONTACT_LAST_SIMPLE_STRING = E_CONTACT_NOTE,
+ E_CONTACT_FIRST_PHONE_ID = E_CONTACT_PHONE_ASSISTANT,
+ E_CONTACT_LAST_PHONE_ID = E_CONTACT_PHONE_TTYTDD,
+ E_CONTACT_FIRST_EMAIL_ID = E_CONTACT_EMAIL_1,
+ E_CONTACT_LAST_EMAIL_ID = E_CONTACT_EMAIL_3,
+ E_CONTACT_FIRST_ADDRESS_ID = E_CONTACT_ADDRESS_HOME,
+ E_CONTACT_LAST_ADDRESS_ID = E_CONTACT_ADDRESS_OTHER,
+ E_CONTACT_FIRST_LABEL_ID = E_CONTACT_ADDRESS_LABEL_HOME,
+ E_CONTACT_LAST_LABEL_ID = E_CONTACT_ADDRESS_LABEL_OTHER
+
+} EContactField;
+
+typedef struct {
+ char *family;
+ char *given;
+ char *additional;
+ char *prefixes;
+ char *suffixes;
+} EContactName;
+
+typedef struct {
+ int length;
+ char *data;
+} EContactPhoto;
+
+typedef struct {
+ char *address_format; /* the two letter country code that
+ determines the format/meaning of the
+ following fields */
+ char *po;
+ char *ext;
+ char *street;
+ char *locality;
+ char *region;
+ char *code;
+ char *country;
+} EContactAddress;
+
+typedef struct {
+ int year;
+ int month;
+ int day;
+} EContactDate;
+
+struct _EContact {
+ EVCard parent;
+
+ EContactPrivate *priv;
+};
+
+struct _EContactClass {
+ EVCardClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_ebook_reserved0) (void);
+ void (*_ebook_reserved1) (void);
+ void (*_ebook_reserved2) (void);
+ void (*_ebook_reserved3) (void);
+ void (*_ebook_reserved4) (void);
+};
+
+GType e_contact_get_type (void);
+
+EContact* e_contact_new (void);
+EContact* e_contact_new_from_vcard (const char *vcard);
+
+EContact* e_contact_duplicate (EContact *contact);
+
+gpointer e_contact_get (EContact *contact, EContactField field_id);
+const gpointer e_contact_get_const (EContact *contact, EContactField field_id);
+void e_contact_set (EContact *contact, EContactField field_id, gpointer value);
+
+/* misc functions for structured values */
+EContactDate *e_contact_date_new (void);
+EContactDate *e_contact_date_from_string (const char *str);
+char *e_contact_date_to_string (EContactDate *dt);
+
+EContactName *e_contact_name_new (void);
+char *e_contact_name_to_string (const EContactName *name);
+EContactName *e_contact_name_from_string (const char *name_str);
+EContactName *e_contact_name_copy (EContactName *name);
+
+
+/* destructors for structured values */
+void e_contact_date_free (EContactDate *date);
+void e_contact_name_free (EContactName *name);
+void e_contact_photo_free (EContactPhoto *photo);
+void e_contact_address_free (EContactAddress *address);
+
+
+const char* e_contact_field_name (EContactField field_id);
+const char* e_contact_pretty_name (EContactField field_id);
+EContactField e_contact_field_id (const char *field_name);
+
+#endif /* __E_CONTACT_H__ */
diff --git a/addressbook/backend/ebook/e-destination.h b/addressbook/backend/ebook/e-destination.h
deleted file mode 100644
index acd6af1bc4..0000000000
--- a/addressbook/backend/ebook/e-destination.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-destination.h
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Developed by Jon Trowbridge <trow@ximian.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA.
- */
-
-#ifndef __E_DESTINATION_H__
-#define __E_DESTINATION_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <ebook/e-card.h>
-#include <ebook/e-book.h>
-#include <libxml/tree.h>
-
-#define E_TYPE_DESTINATION (e_destination_get_type ())
-#define E_DESTINATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_DESTINATION, EDestination))
-#define E_DESTINATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_DESTINATION, EDestinationClass))
-#define E_IS_DESTINATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_DESTINATION))
-#define E_IS_DESTINATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_DESTINATION))
-#define E_DESTINATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DESTINATION, EDestinationClass))
-
-typedef struct _EDestination EDestination;
-typedef struct _EDestinationClass EDestinationClass;
-
-typedef void (*EDestinationCardCallback) (EDestination *dest, ECard *card, gpointer closure);
-
-struct _EDestinationPrivate;
-
-struct _EDestination {
- GObject object;
-
- struct _EDestinationPrivate *priv;
-};
-
-struct _EDestinationClass {
- GObjectClass parent_class;
-
- void (*changed) (EDestination *dest);
- void (*cardified) (EDestination *dest);
-};
-
-GType e_destination_get_type (void);
-
-
-EDestination *e_destination_new (void);
-void e_destination_changed (EDestination *);
-EDestination *e_destination_copy (const EDestination *);
-void e_destination_clear (EDestination *);
-
-gboolean e_destination_is_empty (const EDestination *);
-gboolean e_destination_is_valid (const EDestination *);
-gboolean e_destination_equal (const EDestination *a, const EDestination *b);
-
-void e_destination_set_card (EDestination *, ECard *card, gint email_num);
-void e_destination_set_book_uri (EDestination *, const gchar *uri);
-void e_destination_set_card_uid (EDestination *, const gchar *uid, gint email_num);
-
-void e_destination_set_name (EDestination *, const gchar *name);
-void e_destination_set_email (EDestination *, const gchar *email);
-
-void e_destination_set_html_mail_pref (EDestination *, gboolean);
-
-gboolean e_destination_contains_card (const EDestination *);
-gboolean e_destination_from_card (const EDestination *);
-
-gboolean e_destination_is_auto_recipient (const EDestination *);
-void e_destination_set_auto_recipient (EDestination *, gboolean value);
-
-void e_destination_use_card (EDestination *, EDestinationCardCallback cb, gpointer closure);
-
-ECard *e_destination_get_card (const EDestination *);
-const gchar *e_destination_get_book_uri (const EDestination *);
-const gchar *e_destination_get_card_uid (const EDestination *);
-gint e_destination_get_email_num (const EDestination *);
-
-const gchar *e_destination_get_name (const EDestination *); /* "Jane Smith" */
-const gchar *e_destination_get_email (const EDestination *); /* "jane@assbarn.com" */
-const gchar *e_destination_get_address (const EDestination *);; /* "Jane Smith <jane@assbarn.com>" (or a comma-sep set of such for a list) */
-
-void e_destination_set_raw (EDestination *, const gchar *free_form_string);
-const gchar *e_destination_get_textrep (const EDestination *, gboolean include_email); /* "Jane Smith" or "jane@assbarn.com" */
-
-gboolean e_destination_is_evolution_list (const EDestination *);
-gboolean e_destination_list_show_addresses (const EDestination *);
-
-/* If true, they want HTML mail. */
-gboolean e_destination_get_html_mail_pref (const EDestination *);
-
-gboolean e_destination_allow_cardification (const EDestination *);
-void e_destination_set_allow_cardification (EDestination *, gboolean);
-void e_destination_cardify (EDestination *, EBook *);
-void e_destination_cardify_delayed (EDestination *, EBook *, gint delay); /* delay < 0: "default" */
-void e_destination_cancel_cardify (EDestination *);
-gboolean e_destination_uncardify (EDestination *);
-
-gboolean e_destination_revert (EDestination *);
-
-gchar *e_destination_get_address_textv (EDestination **);
-
-xmlNodePtr e_destination_xml_encode (const EDestination *dest);
-gboolean e_destination_xml_decode (EDestination *dest, xmlNodePtr node);
-
-gchar *e_destination_export (const EDestination *);
-EDestination *e_destination_import (const gchar *str);
-
-gchar *e_destination_exportv (EDestination **);
-EDestination **e_destination_importv (const gchar *str);
-
-EDestination **e_destination_list_to_vector_sized (GList *, int n);
-EDestination **e_destination_list_to_vector (GList *);
-
-void e_destination_freev (EDestination **);
-
-void e_destination_touch (EDestination *);
-void e_destination_touchv (EDestination **);
-
-
-#endif /* __E_DESTINATION_H__ */
-
diff --git a/addressbook/backend/ebook/e-vcard.c b/addressbook/backend/ebook/e-vcard.c
index 62ebda9349..7ea1d9da84 100644
--- a/addressbook/backend/ebook/e-vcard.c
+++ b/addressbook/backend/ebook/e-vcard.c
@@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* evcard.h
+/* e-vcard.c
*
* Copyright (C) 2003 Ximian, Inc.
*
@@ -22,11 +22,18 @@
#include <glib.h>
#include <stdio.h>
+#include <string.h>
#include <ctype.h>
#include "e-vcard.h"
#define CRLF "\r\n"
+typedef enum {
+ EVC_ENCODING_RAW, /* no encoding */
+ EVC_ENCODING_BASE64, /* base64 */
+ EVC_ENCODING_QP /* quoted-printable */
+} EVCardEncoding;
+
struct _EVCardPrivate {
GList *attributes;
};
@@ -36,6 +43,9 @@ struct _EVCardAttribute {
char *name;
GList *params; /* EVCardParam */
GList *values;
+ GList *decoded_values;
+ EVCardEncoding encoding;
+ gboolean encoding_set;
};
struct _EVCardAttributeParam {
@@ -45,6 +55,12 @@ struct _EVCardAttributeParam {
static GObjectClass *parent_class;
+static void _evc_base64_init(void);
+static size_t _evc_base64_encode_step(unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save);
+static size_t _evc_base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save);
+size_t _evc_base64_decode_simple (char *data, size_t len);
+char *_evc_base64_encode_simple (const char *data, size_t len);
+
static void
e_vcard_dispose (GObject *object)
{
@@ -73,6 +89,8 @@ e_vcard_class_init (EVCardClass *klass)
parent_class = g_type_class_ref (G_TYPE_OBJECT);
object_class->dispose = e_vcard_dispose;
+
+ _evc_base64_init();
}
static void
@@ -229,9 +247,9 @@ read_attribute_value (EVCardAttribute *attr, char **p, gboolean quoted_printable
g_warning ("invalid escape, passing it through");
str = g_string_append_c (str, '\\');
str = g_string_append_unichar (str, g_utf8_get_char(lp));
- lp = g_utf8_next_char(lp);
break;
}
+ lp = g_utf8_next_char(lp);
}
else if (*lp == ';') {
e_vcard_attribute_add_value (attr, g_string_free (str, FALSE));
@@ -480,14 +498,16 @@ parse (EVCard *evc, const char *str)
*end = '\0';
}
+#if DEBUG_FOLDING
printf ("BEFORE FOLDING:\n");
printf (str);
-
+#endif
buf = fold_lines (buf);
+#if DEBUG_FOLDING
printf ("\n\nAFTER FOLDING:\n");
printf (buf);
-
+#endif
p = buf;
attr = read_attribute (&p);
@@ -508,6 +528,8 @@ parse (EVCard *evc, const char *str)
if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "end")) {
g_warning ("vcard ended without END:VCARD\n");
}
+
+ g_free (buf);
}
static char*
@@ -517,7 +539,7 @@ escape_string (const char *s)
const char *p;
/* Escape a string as described in RFC2426, section 5 */
- for (p = s; *p; p++) {
+ for (p = s; p && *p; p++) {
switch (*p) {
case '\n':
str = g_string_append (str, "\\n");
@@ -579,24 +601,42 @@ unescape_string (const char *s)
}
#endif
+void
+e_vcard_construct (EVCard *evc, const char *str)
+{
+ if (*str)
+ parse (evc, str);
+}
+
EVCard *
e_vcard_new ()
{
- return g_object_new (E_TYPE_VCARD, NULL);
+ return e_vcard_new_from_string ("");
}
EVCard *
e_vcard_new_from_string (const char *str)
{
- EVCard *evc = e_vcard_new ();
+ EVCard *evc;
- parse (evc, str);
+ g_return_val_if_fail (str, NULL);
+
+ evc = g_object_new (E_TYPE_VCARD, NULL);
+
+ e_vcard_construct (evc, str);
return evc;
}
-char*
-e_vcard_to_string (EVCard *evc)
+static char*
+e_vcard_to_string_vcard_21 (EVCard *evc)
+{
+ g_warning ("need to implement e_vcard_to_string_vcard_21");
+ return g_strdup ("");
+}
+
+static char*
+e_vcard_to_string_vcard_30 (EVCard *evc)
{
GList *l;
GList *v;
@@ -680,6 +720,20 @@ e_vcard_to_string (EVCard *evc)
return g_string_free (str, FALSE);
}
+char*
+e_vcard_to_string (EVCard *evc, EVCardFormat format)
+{
+ switch (format) {
+ case EVC_FORMAT_VCARD_21:
+ return e_vcard_to_string_vcard_21 (evc);
+ case EVC_FORMAT_VCARD_30:
+ return e_vcard_to_string_vcard_30 (evc);
+ default:
+ g_warning ("invalid format specifier passed to e_vcard_to_string");
+ return g_strdup ("");
+ }
+}
+
void
e_vcard_dump_structure (EVCard *evc)
{
@@ -732,24 +786,62 @@ e_vcard_attribute_new (const char *attr_group, const char *attr_name)
void
e_vcard_attribute_free (EVCardAttribute *attr)
{
- GList *p;
-
g_free (attr->group);
g_free (attr->name);
- g_list_foreach (attr->values, (GFunc)g_free, NULL);
- g_list_free (attr->values);
+ e_vcard_attribute_remove_values (attr);
+
+ e_vcard_attribute_remove_params (attr);
+
+ g_free (attr);
+}
+
+EVCardAttribute*
+e_vcard_attribute_copy (EVCardAttribute *attr)
+{
+ EVCardAttribute *a = e_vcard_attribute_new (e_vcard_attribute_get_group (attr),
+ e_vcard_attribute_get_name (attr));
+ GList *p;
+
+ for (p = attr->values; p; p = p->next)
+ e_vcard_attribute_add_value (a, p->data);
+
+ for (p = attr->params; p; p = p->next)
+ e_vcard_attribute_add_param (a, e_vcard_attribute_param_copy (p->data));
+
+ return a;
+}
+
+void
+e_vcard_remove_attributes (EVCard *evc, const char *attr_group, const char *attr_name)
+{
+ GList *attr;
+
+ attr = evc->priv->attributes;
+ while (attr) {
+ GList *next_attr;
+ EVCardAttribute *a = attr->data;
+
+ next_attr = attr->next;
+
+ if (((!attr_group && !a->group) || !g_ascii_strcasecmp (attr_group, a->group)) &&
+ ((!attr_name && !a->name) || !g_ascii_strcasecmp (attr_name, a->name))) {
+
+ /* matches, remove/delete the attribute */
+ evc->priv->attributes = g_list_remove_link (evc->priv->attributes, attr);
- for (p = attr->params; p; p = p->next) {
- EVCardAttributeParam *param = p->data;
+ e_vcard_attribute_free (a);
+ }
- g_free (param->name);
- g_list_foreach (param->values, (GFunc)g_free, NULL);
- g_list_free (param->values);
- g_free (param);
+ attr = next_attr;
}
+}
- g_free (attr);
+void
+e_vcard_remove_attribute (EVCard *evc, EVCardAttribute *attr)
+{
+ evc->priv->attributes = g_list_remove (evc->priv->attributes, attr);
+ e_vcard_attribute_free (attr);
}
void
@@ -791,6 +883,33 @@ e_vcard_attribute_add_value (EVCardAttribute *attr, const char *value)
}
void
+e_vcard_attribute_add_value_decoded (EVCardAttribute *attr, const char *value, int len)
+{
+ switch (attr->encoding) {
+ case EVC_ENCODING_RAW:
+ g_warning ("can't add_value_decoded with an attribute using RAW encoding. you must set the ENCODING parameter first");
+ break;
+ case EVC_ENCODING_BASE64: {
+ char *b64_data = _evc_base64_encode_simple (value, len);
+ GString *decoded = g_string_new_len (value, len);
+
+ /* make sure the decoded list is up to date */
+ e_vcard_attribute_get_values_decoded (attr);
+
+ printf ("base64 encoded value: %s\n", b64_data);
+ printf ("original length: %d\n", len);
+
+ attr->values = g_list_append (attr->values, b64_data);
+ attr->decoded_values = g_list_append (attr->decoded_values, decoded);
+ break;
+ }
+ case EVC_ENCODING_QP:
+ g_warning ("need to implement quoted printable decoding");
+ break;
+ }
+}
+
+void
e_vcard_attribute_add_values (EVCardAttribute *attr,
...)
{
@@ -806,6 +925,21 @@ e_vcard_attribute_add_values (EVCardAttribute *attr,
va_end (ap);
}
+void
+e_vcard_attribute_remove_values (EVCardAttribute *attr)
+{
+ g_list_foreach (attr->values, (GFunc)g_free, NULL);
+ g_list_free (attr->values);
+ attr->values = NULL;
+}
+
+void
+e_vcard_attribute_remove_params (EVCardAttribute *attr)
+{
+ g_list_foreach (attr->params, (GFunc)e_vcard_attribute_param_free, NULL);
+ g_list_free (attr->params);
+ attr->params = NULL;
+}
EVCardAttributeParam*
e_vcard_attribute_param_new (const char *name)
@@ -820,16 +954,55 @@ void
e_vcard_attribute_param_free (EVCardAttributeParam *param)
{
g_free (param->name);
- g_list_foreach (param->values, (GFunc)g_free, NULL);
- g_list_free (param->values);
+
+ e_vcard_attribute_param_remove_values (param);
+
g_free (param);
}
+EVCardAttributeParam*
+e_vcard_attribute_param_copy (EVCardAttributeParam *param)
+{
+ EVCardAttributeParam *p = e_vcard_attribute_param_new (e_vcard_attribute_param_get_name (param));
+ GList *l;
+
+ for (l = param->values; l; l = l->next) {
+ e_vcard_attribute_param_add_value (p, l->data);
+ }
+
+ return p;
+}
+
void
e_vcard_attribute_add_param (EVCardAttribute *attr,
EVCardAttributeParam *param)
{
attr->params = g_list_append (attr->params, param);
+
+ /* we handle our special encoding stuff here */
+
+ if (!g_ascii_strcasecmp (param->name, EVC_ENCODING)) {
+ if (attr->encoding_set) {
+ g_warning ("ENCODING specified twice");
+ return;
+ }
+
+ if (param->values && param->values->data) {
+ if (!g_ascii_strcasecmp ((char*)param->values->data, "b"))
+ attr->encoding = EVC_ENCODING_BASE64;
+ else if (!g_ascii_strcasecmp ((char*)param->values->data, EVC_QUOTEDPRINTABLE))
+ attr->encoding = EVC_ENCODING_QP;
+ else {
+ g_warning ("Unknown value `%s' for ENCODING parameter. values will be treated as raw",
+ (char*)param->values->data);
+ }
+
+ attr->encoding_set = TRUE;
+ }
+ else {
+ g_warning ("ENCODING parameter added with no value");
+ }
+ }
}
void
@@ -882,6 +1055,14 @@ e_vcard_attribute_add_param_with_values (EVCardAttribute *attr,
e_vcard_attribute_add_param (attr, param);
}
+void
+e_vcard_attribute_param_remove_values (EVCardAttributeParam *param)
+{
+ g_list_foreach (param->values, (GFunc)g_free, NULL);
+ g_list_free (param->values);
+ param->values = NULL;
+}
+
GList*
e_vcard_get_attributes (EVCard *evcard)
{
@@ -907,6 +1088,33 @@ e_vcard_attribute_get_values (EVCardAttribute *attr)
}
GList*
+e_vcard_attribute_get_values_decoded (EVCardAttribute *attr)
+{
+ if (!attr->decoded_values) {
+ GList *l;
+ switch (attr->encoding) {
+ case EVC_ENCODING_RAW:
+ for (l = attr->values; l; l = l->next)
+ attr->decoded_values = g_list_append (attr->decoded_values, g_string_new ((char*)l->data));
+ break;
+ case EVC_ENCODING_BASE64:
+ for (l = attr->values; l; l = l->next) {
+ char *decoded = g_strdup ((char*)l->data);
+ int len = _evc_base64_decode_simple (decoded, strlen (decoded));
+ attr->decoded_values = g_list_append (attr->decoded_values, g_string_new_len (decoded, len));
+ g_free (decoded);
+ }
+ break;
+ case EVC_ENCODING_QP:
+ g_warning ("need to implement quoted printable decoding");
+ break;
+ }
+ }
+
+ return attr->decoded_values;
+}
+
+GList*
e_vcard_attribute_get_params (EVCardAttribute *attr)
{
return attr->params;
@@ -923,3 +1131,237 @@ e_vcard_attribute_param_get_values (EVCardAttributeParam *param)
{
return param->values;
}
+
+
+
+/* encoding/decoding stuff ripped from camel-mime-utils.c */
+
+static char *_evc_base64_alphabet =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static unsigned char _evc_base64_rank[256];
+
+static void
+_evc_base64_init(void)
+{
+ int i;
+
+ memset(_evc_base64_rank, 0xff, sizeof(_evc_base64_rank));
+ for (i=0;i<64;i++) {
+ _evc_base64_rank[(unsigned int)_evc_base64_alphabet[i]] = i;
+ }
+ _evc_base64_rank['='] = 0;
+}
+
+/* call this when finished encoding everything, to
+ flush off the last little bit */
+static size_t
+_evc_base64_encode_close(unsigned char *in, size_t inlen, gboolean break_lines, unsigned char *out, int *state, int *save)
+{
+ int c1, c2;
+ unsigned char *outptr = out;
+
+ if (inlen>0)
+ outptr += _evc_base64_encode_step(in, inlen, break_lines, outptr, state, save);
+
+ c1 = ((unsigned char *)save)[1];
+ c2 = ((unsigned char *)save)[2];
+
+#if 0
+ d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
+ (int)((char *)save)[0],
+ (int)((char *)save)[1],
+ (int)((char *)save)[2]));
+#endif
+
+ switch (((char *)save)[0]) {
+ case 2:
+ outptr[2] = _evc_base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
+ g_assert(outptr[2] != 0);
+ goto skip;
+ case 1:
+ outptr[2] = '=';
+ skip:
+ outptr[0] = _evc_base64_alphabet[ c1 >> 2 ];
+ outptr[1] = _evc_base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
+ outptr[3] = '=';
+ outptr += 4;
+ break;
+ }
+ if (break_lines)
+ *outptr++ = '\n';
+
+ *save = 0;
+ *state = 0;
+
+ return outptr-out;
+}
+
+/*
+ performs an 'encode step', only encodes blocks of 3 characters to the
+ output at a time, saves left-over state in state and save (initialise to
+ 0 on first invocation).
+*/
+static size_t
+_evc_base64_encode_step(unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save)
+{
+ register unsigned char *inptr, *outptr;
+
+ if (len<=0)
+ return 0;
+
+ inptr = in;
+ outptr = out;
+
+#if 0
+ d(printf("we have %d chars, and %d saved chars\n", len, ((char *)save)[0]));
+#endif
+
+ if (len + ((char *)save)[0] > 2) {
+ unsigned char *inend = in+len-2;
+ register int c1, c2, c3;
+ register int already;
+
+ already = *state;
+
+ switch (((char *)save)[0]) {
+ case 1: c1 = ((unsigned char *)save)[1]; goto skip1;
+ case 2: c1 = ((unsigned char *)save)[1];
+ c2 = ((unsigned char *)save)[2]; goto skip2;
+ }
+
+ /* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
+ while (inptr < inend) {
+ c1 = *inptr++;
+ skip1:
+ c2 = *inptr++;
+ skip2:
+ c3 = *inptr++;
+ *outptr++ = _evc_base64_alphabet[ c1 >> 2 ];
+ *outptr++ = _evc_base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
+ *outptr++ = _evc_base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
+ *outptr++ = _evc_base64_alphabet[ c3 & 0x3f ];
+ /* this is a bit ugly ... */
+ if (break_lines && (++already)>=19) {
+ *outptr++='\n';
+ already = 0;
+ }
+ }
+
+ ((char *)save)[0] = 0;
+ len = 2-(inptr-inend);
+ *state = already;
+ }
+
+#if 0
+ d(printf("state = %d, len = %d\n",
+ (int)((char *)save)[0],
+ len));
+#endif
+
+ if (len>0) {
+ register char *saveout;
+
+ /* points to the slot for the next char to save */
+ saveout = & (((char *)save)[1]) + ((char *)save)[0];
+
+ /* len can only be 0 1 or 2 */
+ switch(len) {
+ case 2: *saveout++ = *inptr++;
+ case 1: *saveout++ = *inptr++;
+ }
+ ((char *)save)[0]+=len;
+ }
+
+#if 0
+ d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
+ (int)((char *)save)[0],
+ (int)((char *)save)[1],
+ (int)((char *)save)[2]));
+#endif
+
+ return outptr-out;
+}
+
+
+/**
+ * base64_decode_step: decode a chunk of base64 encoded data
+ * @in: input stream
+ * @len: max length of data to decode
+ * @out: output stream
+ * @state: holds the number of bits that are stored in @save
+ * @save: leftover bits that have not yet been decoded
+ *
+ * Decodes a chunk of base64 encoded data
+ **/
+static size_t
+_evc_base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save)
+{
+ register unsigned char *inptr, *outptr;
+ unsigned char *inend, c;
+ register unsigned int v;
+ int i;
+
+ inend = in+len;
+ outptr = out;
+
+ /* convert 4 base64 bytes to 3 normal bytes */
+ v=*save;
+ i=*state;
+ inptr = in;
+ while (inptr<inend) {
+ c = _evc_base64_rank[*inptr++];
+ if (c != 0xff) {
+ v = (v<<6) | c;
+ i++;
+ if (i==4) {
+ *outptr++ = v>>16;
+ *outptr++ = v>>8;
+ *outptr++ = v;
+ i=0;
+ }
+ }
+ }
+
+ *save = v;
+ *state = i;
+
+ /* quick scan back for '=' on the end somewhere */
+ /* fortunately we can drop 1 output char for each trailing = (upto 2) */
+ i=2;
+ while (inptr>in && i) {
+ inptr--;
+ if (_evc_base64_rank[*inptr] != 0xff) {
+ if (*inptr == '=' && outptr>out)
+ outptr--;
+ i--;
+ }
+ }
+
+ /* if i!= 0 then there is a truncation error! */
+ return outptr-out;
+}
+
+char *
+_evc_base64_encode_simple (const char *data, size_t len)
+{
+ unsigned char *out;
+ int state = 0, outlen;
+ unsigned int save = 0;
+
+ out = g_malloc (len * 4 / 3 + 5);
+ outlen = _evc_base64_encode_close ((unsigned char *)data, len, FALSE,
+ out, &state, &save);
+ out[outlen] = '\0';
+ return (char *)out;
+}
+
+size_t
+_evc_base64_decode_simple (char *data, size_t len)
+{
+ int state = 0;
+ unsigned int save = 0;
+
+ return _evc_base64_decode_step ((unsigned char *)data, len,
+ (unsigned char *)data, &state, &save);
+}
diff --git a/addressbook/backend/ebook/e-vcard.h b/addressbook/backend/ebook/e-vcard.h
index 69e0a3e10b..cedc2b4c70 100644
--- a/addressbook/backend/ebook/e-vcard.h
+++ b/addressbook/backend/ebook/e-vcard.h
@@ -26,18 +26,56 @@
#include <glib.h>
#include <glib-object.h>
-#define EVC_FN "FN"
-#define EVC_ORG "ORG"
-#define EVC_URL "URL"
-#define EVC_VERSION "VERSION"
-#define EVC_REV "REV"
-#define EVC_PRODID "PRODID"
-#define EVC_TYPE "TYPE"
-#define EVC_ADR "ADR"
-#define EVC_TEL "TEL"
-
-#define EVC_ENCODING "ENCODING"
+#define EVC_ADR "ADR"
+#define EVC_BDAY "BDAY"
+#define EVC_CALURI "CALURI"
+#define EVC_CATEGORIES "CATEGORIES"
+#define EVC_EMAIL "EMAIL"
+#define EVC_ENCODING "ENCODING"
+#define EVC_FBURL "FBURL"
+#define EVC_FN "FN"
+#define EVC_ICSCALENDAR "ICSCALENDAR" /* XXX should this be X-EVOLUTION-ICSCALENDAR? */
+#define EVC_LABEL "LABEL"
+#define EVC_LOGO "LOGO"
+#define EVC_MAILER "MAILER"
+#define EVC_NICKNAME "NICKNAME"
+#define EVC_N "N"
+#define EVC_NOTE "NOTE"
+#define EVC_ORG "ORG"
+#define EVC_PHOTO "PHOTO"
+#define EVC_PRODID "PRODID"
#define EVC_QUOTEDPRINTABLE "QUOTED-PRINTABLE"
+#define EVC_REV "REV"
+#define EVC_ROLE "ROLE"
+#define EVC_TEL "TEL"
+#define EVC_TITLE "TITLE"
+#define EVC_TYPE "TYPE"
+#define EVC_UID "UID"
+#define EVC_URL "URL"
+#define EVC_VALUE "VALUE"
+#define EVC_VERSION "VERSION"
+
+#define EVC_X_AIM "X-AIM"
+#define EVC_X_ANNIVERSARY "X-EVOLUTION-ANNIVERSARY"
+#define EVC_X_ASSISTANT "X-EVOLUTION-ASSISTANT"
+#define EVC_X_BIRTHDAY "X-EVOLUTION-BIRTHDAY"
+#define EVC_X_BLOG_URL "X-EVOLUTION-BLOG-URL"
+#define EVC_X_FILE_AS "X-EVOLUTION-FILE-AS"
+#define EVC_X_ICQ "X-ICQ"
+#define EVC_X_JABBER "X-JABBER"
+#define EVC_X_LIST_SHOW_ADDRESSES "X-EVOLUTION-LIST-SHOW_ADDRESSES"
+#define EVC_X_LIST "X-EVOLUTION-LIST"
+#define EVC_X_MANAGER "X-EVOLUTION-MANAGER"
+#define EVC_X_MSN "X-MSN"
+#define EVC_X_SPOUSE "X-EVOLUTION-SPOUSE"
+#define EVC_X_WANTS_HTML "X-MOZILLA-HTML"
+#define EVC_X_WANTS_HTML "X-MOZILLA-HTML"
+#define EVC_X_YAHOO "X-YAHOO"
+
+typedef enum {
+ EVC_FORMAT_VCARD_21,
+ EVC_FORMAT_VCARD_30
+} EVCardFormat;
#define E_TYPE_VCARD (e_vcard_get_type ())
#define E_VCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_VCARD, EVCard))
@@ -60,28 +98,46 @@ struct _EVCard {
struct _EVCardClass {
GObjectClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_ebook_reserved0) (void);
+ void (*_ebook_reserved1) (void);
+ void (*_ebook_reserved2) (void);
+ void (*_ebook_reserved3) (void);
+ void (*_ebook_reserved4) (void);
};
GType e_vcard_get_type (void);
+
+void e_vcard_construct (EVCard *evc, const char *str);
EVCard* e_vcard_new (void);
EVCard* e_vcard_new_from_string (const char *str);
-char* e_vcard_to_string (EVCard *evcard);
+
+char* e_vcard_to_string (EVCard *evc, EVCardFormat format);
+
/* mostly for debugging */
void e_vcard_dump_structure (EVCard *evc);
/* attributes */
-EVCardAttribute *e_vcard_attribute_new (const char *attr_group, const char *attr_name);
-void e_vcard_attribute_free (EVCardAttribute *attr);
-void e_vcard_add_attribute (EVCard *evcard, EVCardAttribute *attr);
-void e_vcard_add_attribute_with_value (EVCard *evcard, EVCardAttribute *attr, const char *value);
-void e_vcard_add_attribute_with_values (EVCard *evcard, EVCardAttribute *attr, ...);
-void e_vcard_attribute_add_value (EVCardAttribute *attr, const char *value);
-void e_vcard_attribute_add_values (EVCardAttribute *attr, ...);
+EVCardAttribute *e_vcard_attribute_new (const char *attr_group, const char *attr_name);
+void e_vcard_attribute_free (EVCardAttribute *attr);
+EVCardAttribute *e_vcard_attribute_copy (EVCardAttribute *attr);
+void e_vcard_remove_attributes (EVCard *evcard, const char *attr_group, const char *attr_name);
+void e_vcard_remove_attribute (EVCard *evcard, EVCardAttribute *attr);
+void e_vcard_add_attribute (EVCard *evcard, EVCardAttribute *attr);
+void e_vcard_add_attribute_with_value (EVCard *evcard, EVCardAttribute *attr, const char *value);
+void e_vcard_add_attribute_with_values (EVCard *evcard, EVCardAttribute *attr, ...);
+void e_vcard_attribute_add_value (EVCardAttribute *attr, const char *value);
+void e_vcard_attribute_add_value_decoded (EVCardAttribute *attr, const char *value, int len);
+void e_vcard_attribute_add_values (EVCardAttribute *attr, ...);
+void e_vcard_attribute_remove_values (EVCardAttribute *attr);
+void e_vcard_attribute_remove_params (EVCardAttribute *attr);
/* attribute parameters */
EVCardAttributeParam* e_vcard_attribute_param_new (const char *param_name);
void e_vcard_attribute_param_free (EVCardAttributeParam *param);
+EVCardAttributeParam* e_vcard_attribute_param_copy (EVCardAttributeParam *param);
void e_vcard_attribute_add_param (EVCardAttribute *attr, EVCardAttributeParam *param);
void e_vcard_attribute_add_param_with_value (EVCardAttribute *attr,
EVCardAttributeParam *param, const char *value);
@@ -92,17 +148,18 @@ void e_vcard_attribute_param_add_value (EVCardAttributePa
const char *value);
void e_vcard_attribute_param_add_values (EVCardAttributeParam *param,
...);
+void e_vcard_attribute_param_remove_values (EVCardAttributeParam *param);
/* EVCard* accessors. nothing returned from these functions should be
freed by the caller. */
GList* e_vcard_get_attributes (EVCard *evcard);
const char* e_vcard_attribute_get_group (EVCardAttribute *attr);
const char* e_vcard_attribute_get_name (EVCardAttribute *attr);
-GList* e_vcard_attribute_get_values (EVCardAttribute *attr);
+GList* e_vcard_attribute_get_values (EVCardAttribute *attr); /* GList elements are of type char* */
+GList* e_vcard_attribute_get_values_decoded (EVCardAttribute *attr); /* GList elements are of type GString* */
GList* e_vcard_attribute_get_params (EVCardAttribute *attr);
const char* e_vcard_attribute_param_get_name (EVCardAttributeParam *param);
GList* e_vcard_attribute_param_get_values (EVCardAttributeParam *param);
-
#endif /* _EVCARD_H */
diff --git a/addressbook/backend/ebook/test-client-list.c b/addressbook/backend/ebook/test-client-list.c
deleted file mode 100644
index 6fa3d6b094..0000000000
--- a/addressbook/backend/ebook/test-client-list.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-#include <config.h>
-
-#include <glib.h>
-#include <bonobo/bonobo-i18n.h>
-#include <bonobo/bonobo-main.h>
-#include <libgnome/gnome-init.h>
-
-#include "e-book.h"
-
-static void
-init_bonobo (int *argc, char **argv)
-{
- if (bonobo_init (argc, argv) == FALSE)
- g_error (_("Could not initialize Bonobo"));
-}
-
-static void
-get_cursor_cb (EBook *book, EBookStatus status, ECardCursor *cursor, gpointer closure)
-{
- long length = e_card_cursor_get_length(cursor);
- long i;
-
- printf ("Length: %d\n", (int) length);
- for ( i = 0; i < length; i++ ) {
- ECard *card = e_card_cursor_get_nth(cursor, i);
- char *vcard = e_card_get_vcard_assume_utf8(card);
- printf("[%s]\n", vcard);
- g_free(vcard);
- g_object_unref(card);
- }
-}
-
-static void
-book_open_cb (EBook *book, EBookStatus status, gpointer closure)
-{
- printf ("Book opened.\n");
- e_book_get_cursor(book, "", get_cursor_cb, NULL);
-}
-
-static gboolean
-ebook_create (gpointer data)
-{
- EBook *book;
-
- book = e_book_new ();
-
- e_book_load_uri (book, "file:/tmp/test.db", book_open_cb, NULL);
-
- return FALSE;
-}
-
-int
-main (int argc, char **argv)
-{
- gnome_program_init("test-client-list", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
-
- init_bonobo (&argc, argv);
-
- g_idle_add (ebook_create, NULL);
-
- bonobo_main ();
-
- return 0;
-}
diff --git a/addressbook/backend/ebook/test-client.c b/addressbook/backend/ebook/test-client.c
deleted file mode 100644
index 63461fb671..0000000000
--- a/addressbook/backend/ebook/test-client.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-#include <config.h>
-#include <glib.h>
-#include <bonobo/bonobo-i18n.h>
-#include <bonobo/bonobo-main.h>
-#include <libgnome/gnome-init.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "e-book.h"
-#include "e-book-util.h"
-
-#define TEST_VCARD \
-"BEGIN:VCARD\r\n" \
-"FN:Nat\r\n" \
-"N:Friedman;Nat;D;Mr.\r\n" \
-"BDAY:1977-08-06\r\n" \
-"TEL;WORK:617 679 1984\r\n" \
-"TEL;CELL:123 456 7890\r\n" \
-"EMAIL;INTERNET:nat@nat.org\r\n" \
-"EMAIL;INTERNET:nat@ximian.com\r\n" \
-"ADR;WORK;POSTAL:P.O. Box 101;;;Any Town;CA;91921-1234;\r\n" \
-"END:VCARD\r\n" \
-"\r\n"
-
-static CORBA_Environment ev;
-static char *cardstr;
-
-static void
-init_bonobo (int *argc, char **argv)
-{
- if (bonobo_init (argc, argv) == FALSE)
- g_error (_("Could not initialize Bonobo"));
-}
-
-static void
-get_cursor_cb (EBook *book, EBookStatus status, ECardCursor *cursor, gpointer closure)
-{
- long length = e_card_cursor_get_length(cursor);
- long i;
-
- /* we just added a card, so the length should be >1 */
- printf ("\n%s: %s(): Number of cards is %ld\n",
- __FILE__, G_GNUC_FUNCTION, length);
- if (length < 1)
- printf ("*** Why isn't this above zero?? ***\n\n");
-
- for ( i = 0; i < length; i++ ) {
- ECard *card = e_card_cursor_get_nth(cursor, i);
- char *vcard = e_card_get_vcard_assume_utf8(card);
- printf("Get all cards callback: [%s]\n", vcard);
- g_free(vcard);
- g_object_unref(card);
- }
-
- g_object_unref (book);
- exit(0);
-}
-
-static void
-get_card_cb (EBook *book, EBookStatus status, ECard *card, gpointer closure)
-{
- char *vcard;
-
- vcard = e_card_get_vcard_assume_utf8(card);
- printf ("Card added: [%s]\n", vcard);
- g_free(vcard);
-
- printf ("Getting cards..\n");
- e_book_get_cursor(book, "(contains \"x-evolution-any-field\" \"\")", get_cursor_cb, NULL);
- printf ("Done getting all cards.\n");
-}
-
-static void
-add_card_cb (EBook *book, EBookStatus status, const gchar *id, gpointer closure)
-{
- GTimer *timer;
-
- printf ("Status: %d\n", status);
-
- printf ("Id: %s\n", id);
-
- timer = g_timer_new ();
- g_timer_start (timer);
- e_book_get_card (book, id, get_card_cb, closure);
- g_timer_stop (timer);
- printf ("%g\n", g_timer_elapsed (timer, NULL));
-}
-
-static void
-get_fields_cb (EBook *book, EBookStatus status, EList *fields, gpointer closure)
-{
- if (fields) {
- EIterator *iter = e_list_get_iterator (fields);
-
- printf ("Supported fields:\n");
-
- for (; e_iterator_is_valid (iter); e_iterator_next (iter)) {
- printf (" %s\n", (char*)e_iterator_get (iter));
- }
-
- g_object_unref(fields);
- }
- else {
- printf ("No supported fields?\n");
- }
-
- e_book_add_vcard(book, cardstr, add_card_cb, NULL);
-}
-
-
-static void
-auth_user_cb (EBook *book, EBookStatus status, gpointer closure)
-{
- printf ("user authenticated\n");
- e_book_get_supported_fields (book, get_fields_cb, closure);
-}
-
-static void
-book_open_cb (EBook *book, EBookStatus status, gpointer closure)
-{
- e_book_authenticate_user (book, "username", "password", "auth_method", auth_user_cb, NULL);
-}
-
-static gboolean
-ebook_create (gpointer data)
-{
- EBook *book;
-
- book = e_book_new ();
-
- if (!book) {
- printf ("%s: %s(): Couldn't create EBook, bailing.\n",
- __FILE__,
- G_GNUC_FUNCTION);
- return FALSE;
- }
-
-
- e_book_load_default_book (book, book_open_cb, NULL);
-
- return FALSE;
-}
-
-static char *
-read_file (char *name)
-{
- int len;
- char buff[65536];
- char line[1024];
- FILE *f;
-
- f = fopen (name, "r");
- if (f == NULL)
- g_error ("Unable to open %s!\n", name);
-
- len = 0;
- while (fgets (line, sizeof (line), f) != NULL) {
- strcpy (buff + len, line);
- len += strlen (line);
- }
-
- fclose (f);
-
- return g_strdup (buff);
-}
-
-
-int
-main (int argc, char **argv)
-{
-
- CORBA_exception_init (&ev);
-
- gnome_program_init("test-client", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
-
- init_bonobo (&argc, argv);
-
- cardstr = NULL;
- if (argc == 2)
- cardstr = read_file (argv [1]);
-
- if (cardstr == NULL)
- cardstr = TEST_VCARD;
-
- g_idle_add (ebook_create, NULL);
-
- bonobo_main ();
-
- return 0;
-}
diff --git a/addressbook/backend/ebook/tests/Makefile.am b/addressbook/backend/ebook/tests/Makefile.am
index f17f979485..444d692e22 100644
--- a/addressbook/backend/ebook/tests/Makefile.am
+++ b/addressbook/backend/ebook/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS=vcard \ No newline at end of file
+SUBDIRS=vcard ebook
diff --git a/addressbook/backend/ebook/tests/ebook/.cvsignore b/addressbook/backend/ebook/tests/ebook/.cvsignore
new file mode 100644
index 0000000000..8dbec11b01
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/.cvsignore
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+test-date
+test-ebook
+test-changes
+test-photo
+test-string
diff --git a/addressbook/backend/ebook/tests/ebook/Makefile.am b/addressbook/backend/ebook/tests/ebook/Makefile.am
new file mode 100644
index 0000000000..7147690482
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/Makefile.am
@@ -0,0 +1,12 @@
+
+TEST_LIBS=$(top_builddir)/addressbook/backend/ebook/libebook.la
+
+INCLUDES=-I$(srcdir)/../../.. @EVOLUTION_ADDRESSBOOK_CFLAGS@
+
+noinst_PROGRAMS= test-changes test-date test-ebook test-photo test-string
+
+test_date_LDFLAGS=$(TEST_LIBS)
+test_ebook_LDFLAGS=$(TEST_LIBS)
+test_changes_LDFLAGS=$(TEST_LIBS)
+test_photo_LDFLAGS=$(TEST_LIBS)
+test_string_LDFLAGS=$(TEST_LIBS)
diff --git a/addressbook/backend/ebook/tests/ebook/test-changes.c b/addressbook/backend/ebook/tests/ebook/test-changes.c
new file mode 100644
index 0000000000..0c91f30cf4
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/test-changes.c
@@ -0,0 +1,89 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include "ebook/e-book.h"
+#include <libgnome/gnome-init.h>
+#include <bonobo/bonobo-main.h>
+#include <stdlib.h>
+
+#define NEW_VCARD "BEGIN:VCARD\n\
+X-EVOLUTION-FILE-AS:Toshok, Chris\n\
+FN:Chris Toshok\n\
+EMAIL;INTERNET:toshok@ximian.com\n\
+ORG:Ximian, Inc.;\n\
+END:VCARD"
+
+static char file_template[]="file:///tmp/change-test-XXXXXX";
+
+int
+main (int argc, char **argv)
+{
+ EBook *book;
+ gboolean status;
+ EContact *contact;
+ GList *changes;
+ GError *error = NULL;
+ EBookChange *change;
+
+ gnome_program_init("test-changes", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
+
+ if (bonobo_init (&argc, argv) == FALSE)
+ g_error ("Could not initialize Bonobo");
+
+ mktemp (file_template);
+
+ /* create a temp addressbook in /tmp */
+ book = e_book_new ();
+
+ printf ("loading addressbook\n");
+ if (!e_book_load_uri (book, file_template, FALSE, &error)) {
+ printf ("failed to open addressbook: `%s': %s\n", file_template, error->message);
+ exit(0);
+ }
+
+ /* get an initial change set */
+ if (!e_book_get_changes (book, "changeidtest", &changes, &error)) {
+ printf ("failed to get changes: %s\n", error->message);
+ exit(0);
+ }
+
+ /* make a change to the book */
+ contact = e_contact_new_from_vcard (NEW_VCARD);
+ if (!e_book_add_contact (book, contact, &error)) {
+ printf ("failed to add new contact: %s\n", error->message);
+ exit(0);
+ }
+
+ /* get another change set */
+ if (!e_book_get_changes (book, "changeidtest", &changes, &error)) {
+ printf ("failed to get second set of changes: %s\n", error->message);
+ exit(0);
+ }
+
+ /* make sure that 1 change has occurred */
+ if (g_list_length (changes) != 1) {
+ printf ("got back %d changes, was expecting 1\n", g_list_length (changes));
+ exit(0);
+ }
+
+ change = changes->data;
+ if (change->change_type != E_BOOK_CHANGE_CARD_ADDED) {
+ printf ("was expecting a CARD_ADDED change, but didn't get it.\n");
+ exit(0);
+ }
+
+ printf ("got changed vcard back: %s\n", change->vcard);
+
+ e_book_free_change_list (changes);
+
+
+ if (!e_book_remove (book, &error)) {
+ printf ("failed to remove book; %s\n", error->message);
+ exit(0);
+ }
+
+ g_object_unref (book);
+
+ bonobo_main_quit();
+
+ return 0;
+}
diff --git a/addressbook/backend/ebook/tests/ebook/test-date.c b/addressbook/backend/ebook/tests/ebook/test-date.c
new file mode 100644
index 0000000000..afe37cf224
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/test-date.c
@@ -0,0 +1,36 @@
+
+#include "ebook/e-book.h"
+#include <libgnome/gnome-init.h>
+#include <bonobo/bonobo-main.h>
+#include <stdlib.h>
+
+int
+main (int argc, char **argv)
+{
+ EContact *contact;
+ EContactDate date, *dp;
+
+ gnome_program_init("test-string", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
+
+ if (bonobo_init (&argc, argv) == FALSE)
+ g_error ("Could not initialize Bonobo");
+
+ contact = e_contact_new ();
+
+ date.year = 1999;
+ date.month = 3;
+ date.day = 3;
+
+ e_contact_set (contact, E_CONTACT_BIRTH_DATE, &date);
+
+ printf ("vcard = \n%s\n", e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30));
+
+ dp = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
+
+ if (dp->year != date.year
+ || dp->month != date.month
+ || dp->day != date.day)
+ printf ("failed\n");
+ else
+ printf ("passed\n");
+}
diff --git a/addressbook/backend/ebook/tests/ebook/test-ebook.c b/addressbook/backend/ebook/tests/ebook/test-ebook.c
new file mode 100644
index 0000000000..d78d9f3b6a
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/test-ebook.c
@@ -0,0 +1,110 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include "ebook/e-book.h"
+#include <libgnome/gnome-init.h>
+#include <bonobo/bonobo-main.h>
+#include <stdlib.h>
+
+static void
+print_email (EContact *contact)
+{
+ char *file_as = e_contact_get (contact, E_CONTACT_FILE_AS);
+ GList *emails, *e;
+
+ printf ("Contact: %s\n", file_as);
+ printf ("Email addresses:\n");
+ emails = e_contact_get (contact, E_CONTACT_EMAIL);
+ for (e = emails; e; e = e->next) {
+ EVCardAttribute *attr = e->data;
+ GList *values = e_vcard_attribute_get_values (attr);
+ printf ("\t%s\n", values && values->data ? (char*)values->data : "");
+ e_vcard_attribute_free (attr);
+ }
+ g_list_free (emails);
+
+ g_free (file_as);
+
+ printf ("\n");
+}
+
+static void
+print_all_emails (EBook *book)
+{
+ EBookQuery *query;
+ gboolean status;
+ GList *cards, *c;
+
+ query = e_book_query_field_exists (E_CONTACT_FULL_NAME);
+
+ status = e_book_get_contacts (book, query, &cards, NULL);
+
+ e_book_query_unref (query);
+
+ if (status == FALSE) {
+ printf ("error %d getting card list\n", status);
+ exit(0);
+ }
+
+ for (c = cards; c; c = c->next) {
+ EContact *contact = E_CONTACT (c->data);
+
+ print_email (contact);
+
+ g_object_unref (contact);
+ }
+ g_list_free (cards);
+}
+
+static void
+print_one_email (EBook *book)
+{
+ EContact *contact;
+ GError *error = NULL;
+
+ if (!e_book_get_contact (book, "pas-id-0002023", &contact, &error)) {
+ printf ("error %d getting card: %s\n", error->code, error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ print_email (contact);
+
+ g_object_unref (contact);
+}
+
+int
+main (int argc, char **argv)
+{
+ EBook *book;
+ gboolean status;
+
+ gnome_program_init("test-ebook", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
+
+ if (bonobo_init (&argc, argv) == FALSE)
+ g_error ("Could not initialize Bonobo");
+
+ /*
+ ** the actual ebook foo
+ */
+
+ book = e_book_new ();
+
+ printf ("loading addressbook\n");
+ status = e_book_load_local_addressbook (book, NULL);
+ if (status == FALSE) {
+ printf ("failed to open local addressbook\n");
+ exit(0);
+ }
+
+ printf ("printing one contact\n");
+ print_one_email (book);
+
+ printf ("printing all contacts\n");
+ print_all_emails (book);
+
+ g_object_unref (book);
+
+ bonobo_main_quit();
+
+ return 0;
+}
diff --git a/addressbook/backend/ebook/tests/ebook/test-photo.c b/addressbook/backend/ebook/tests/ebook/test-photo.c
new file mode 100644
index 0000000000..cbd6817b37
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/test-photo.c
@@ -0,0 +1,59 @@
+
+#include "ebook/e-book.h"
+#include <libgnome/gnome-init.h>
+#include <bonobo/bonobo-main.h>
+#include <stdlib.h>
+
+const char *photo_data = "/9j/4AAQSkZJRgABAQEARwBHAAD//gAXQ3JlYXRlZCB3aXRo\
+IFRoZSBHSU1Q/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLC\
+McHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIy\
+MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgAMgAyAwEiAAIRAQMRAf\
+/EABsAAQACAwEBAAAAAAAAAAAAAAAHCAQFBgID/8QAMBAAAgEDAQYEBQQDAAAAAAAAAQIDAAQR\
+BQYSEyExQQdhcYEiI0JRkRQVMqFiguH/xAAaAQADAQEBAQAAAAAAAAAAAAAABAUCBgED/8QAIx\
+EAAgICAQQCAwAAAAAAAAAAAAECAwQRQRITITEUYQUiUf/aAAwDAQACEQMRAD8An+sHUtWtNKjV\
+rmQ7754cajLvjrgfbzPIdzWdVfds9pJb3XdQkMrcFZGj+HqY0bdVV9Tz/wBia+N9vbjvkaxMb5\
+E9N6SJB1HxLEEjJaWsUjD6QzSMPXdGB7E1zV74t63HINy1s4F7CWCTn77wrA0TY86jY3N1qsUk\
+6wxBxBDvYjLHkoUH4j3JP/a0V3s1CvF/QM9tKpw0THeU+TLkj8VLnmzT8y0n9FujBx5bioba/r\
+ZLWx3iPZ7RzLp95GtnqRGVTezHNjruH7/4n+67iqpq7Qi3uYWMMsNynfnE6sM8/Lr6VamFi0KM\
+epUE1Sx7XZHbI+fjxos1H0z3SlKYEjzISI2I64OKqsyu8sck2QYrmPjBvpIYg598Vauoh8VtlY\
+7JW2isoBwpPl6hGByZTyD+o6E+h7UtlVOcPHA/+PyI1Wal6Zp7vaC/06wnTTLtEeUDiKwzu4H8\
+vI9AM9Tiuctkng1Nnk1G5cOoYifB4nI/jB7VjWuoT21qPmwXUCHKlphHKvqG5N6g0/cLi/Rg88\
+FhbkbxlaUSu3kqpnn6kDzqGqbNdPB0XyK4/svZr9RVntL50GePdcKEDqzhVBx7sKtPpayppNos\
+xzKIlDHzxUFeG2zo2n2kivWhK6PpHwwoTnfk65J7kZyT9z5VYADAwKuYtfRA5zPv7tnjgUpSmR\
+EV8bq1hvbWW1uY1khlUo6MMhgeor7UoAje18FtmLe9eeQT3EXPcglkJRPbv71EWu7Dajp2o3MG\
+mlRCkjKQ30jPUe1WlrlNW0RptTleNB84DnjkD0P9VlxT4Nqck9pmn8JuFp2zo0cgCWFi2e7555\
+/NSHXLadso2m3sU0NxlV65HM+VdTW3rgwvsUpSvAFKUoAUxSlAClKUAKUpQB//2Q==";
+
+
+int
+main (int argc, char **argv)
+{
+ EContact *contact;
+ EContactPhoto *photo, *new_photo;
+
+ gnome_program_init("test-photo", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
+
+ if (bonobo_init (&argc, argv) == FALSE)
+ g_error ("Could not initialize Bonobo");
+
+ contact = e_contact_new ();
+
+ photo = g_new (EContactPhoto, 1);
+ photo->data = g_strdup (photo_data);
+ photo->length = _evc_base64_decode_simple (photo->data, strlen (photo_data));
+
+ /* set the photo */
+ e_contact_set (contact, E_CONTACT_PHOTO, photo);
+
+ /* then get the photo */
+ new_photo = e_contact_get (contact, E_CONTACT_PHOTO);
+
+ /* and compare */
+ if (new_photo->length != photo->length)
+ g_error ("photo lengths differ");
+
+ if (memcmp (new_photo->data, photo->data, photo->length))
+ g_error ("photo data differs");
+
+ printf ("photo test passed\n");
+}
diff --git a/addressbook/backend/ebook/tests/ebook/test-string.c b/addressbook/backend/ebook/tests/ebook/test-string.c
new file mode 100644
index 0000000000..b7cdbb3720
--- /dev/null
+++ b/addressbook/backend/ebook/tests/ebook/test-string.c
@@ -0,0 +1,27 @@
+
+#include "ebook/e-book.h"
+#include <libgnome/gnome-init.h>
+#include <bonobo/bonobo-main.h>
+#include <stdlib.h>
+
+#define TEST_ID "test-uid"
+
+int
+main (int argc, char **argv)
+{
+ EContact *contact;
+
+ gnome_program_init("test-string", "0.0", LIBGNOME_MODULE, argc, argv, NULL);
+
+ if (bonobo_init (&argc, argv) == FALSE)
+ g_error ("Could not initialize Bonobo");
+
+ contact = e_contact_new ();
+
+ e_contact_set (contact, E_CONTACT_UID, TEST_ID);
+
+ if (!strcmp (e_contact_get_const (contact, E_CONTACT_UID), TEST_ID))
+ printf ("passed\n");
+ else
+ printf ("failed\n");
+}
diff --git a/addressbook/backend/ebook/tests/vcard/Makefile.am b/addressbook/backend/ebook/tests/vcard/Makefile.am
index ae16780095..7e57329e1d 100644
--- a/addressbook/backend/ebook/tests/vcard/Makefile.am
+++ b/addressbook/backend/ebook/tests/vcard/Makefile.am
@@ -1,6 +1,8 @@
-CFLAGS=-I$(srcdir)/../.. `pkg-config --cflags gobject-2.0`
+TEST_LIBS=$(top_builddir)/addressbook/backend/ebook/libebook.la
+
+INCLUDES=-I$(srcdir)/../../.. @EVOLUTION_ADDRESSBOOK_CFLAGS@
noinst_PROGRAMS=dump-vcard
-dump_vcard_LDFLAGS=$(top_builddir)/addressbook/backend/ebook/libevcard.la `pkg-config --libs gobject-2.0`
+dump_vcard_LDFLAGS=$(TEST_LIBS)
diff --git a/addressbook/backend/ebook/tests/vcard/dump-vcard.c b/addressbook/backend/ebook/tests/vcard/dump-vcard.c
index 52dbf8a957..907a00efa7 100644
--- a/addressbook/backend/ebook/tests/vcard/dump-vcard.c
+++ b/addressbook/backend/ebook/tests/vcard/dump-vcard.c
@@ -1,7 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#include <stdio.h>
-#include "e-vcard.h"
+#include "ebook/e-vcard.h"
FILE *fp;