summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Ramendik <mr@ramendik.ru>2006-10-27 17:09:15 +0000
committerMikhail Ramendik <mr@ramendik.ru>2006-10-27 17:09:15 +0000
commitef52fcf4f4aad39947dab7d232ddaeee7177ca6f (patch)
treec80559547e8b0a0e52ffe6c335d7197ac648b39a
Added dapi-dbus from Imendio repository to Portland repository
-rw-r--r--AUTHORS2
-rw-r--r--COPYING340
-rw-r--r--ChangeLog0
-rw-r--r--ChangeLog-pre-0.2165
-rw-r--r--INSTALL236
-rw-r--r--Makefile.am2
-rw-r--r--NEWS0
-rw-r--r--README53
-rw-r--r--TODO3
-rw-r--r--acinclude.m4418
-rwxr-xr-xautogen.sh191
-rw-r--r--configure.ac170
-rw-r--r--data/Makefile.am18
-rw-r--r--data/dapi-command.xml96
-rw-r--r--data/dapi-common.h45
-rw-r--r--data/org.freedesktop.dapi.service.in3
-rw-r--r--doc/status-report-20060714.txt29
-rw-r--r--src/Makefile.am34
-rw-r--r--src/dapi-command.c833
-rw-r--r--src/dapi-command.h131
-rw-r--r--src/dapi-daemon.c195
-rw-r--r--src/dapi-debug.c92
-rw-r--r--src/dapi-debug.h51
-rw-r--r--src/dapi-gnome.c1710
-rw-r--r--src/dapi-gnome.h114
-rw-r--r--tests/Makefile.am40
-rw-r--r--tests/README3
-rw-r--r--tests/test-addressbook.c380
-rw-r--r--tests/test-api.c380
-rw-r--r--tests/test-client.c1015
-rw-r--r--tests/test-ebook-async-get-contact.c318
-rw-r--r--tests/tests.h43
32 files changed, 7110 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..fa05488
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Martyn Russell <martyn@imendio.com>
+Mikael Hallendal <micke@imendio.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..623b625
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/ChangeLog-pre-0.2 b/ChangeLog-pre-0.2
new file mode 100644
index 0000000..cc52b8d
--- /dev/null
+++ b/ChangeLog-pre-0.2
@@ -0,0 +1,165 @@
+2006-10-27 Mikael Hallendal <micke@imendio.com>
+
+ * configure.ac: Updated to 0.2
+
+2006-10-27 Martyn Russell <martyn@imendio.com>
+
+ * tests/test-api.c: Added tests for the local_file() and
+ remove_temporary_local_file() APIs.
+
+2006-10-27 Mikael Hallendal <micke@imendio.com>
+
+ * README: Updated to org.freedesktop.dapi namespace
+
+2006-10-27 Martyn Russell <martyn@imendio.com>
+
+ * tests/test-addressbook.c:
+ * tests/test-api.c:
+ * tests/tests.h: Added tests for the addressbook API.
+
+2006-10-27 Mikael Hallendal <micke@imendio.com>
+
+ * tests/Makefile.am: Made it possible to run "make check"
+ * tests/test-addressbook.c: Added file for the addressbook calls
+ * tests/tests.h: Added a common h-file for the test suite.
+ * tests/test-api.c: (main): Hooked in the addressbook tests.
+
+2006-10-27 Martyn Russell <martyn@imendio.com>
+
+ * data/Makefile.am:
+ * data/dapi-command.xml:
+ * data/org.freedesktop.dapi.service.in:
+ * data/org.gnome.dapi.service.in:
+ * src/dapi-command.h:
+ * tests/test-api.c:
+ * tests/test-client.c: Renamed service to org.freedesktop.dapi
+ from org.gnome.dapi.
+
+2006-10-27 Martyn Russell <martyn@imendio.com>
+
+ * data/dapi-command.xml:
+ * src/dapi-command.[ch]:
+ * tests/test-api.c:
+ * tests/test-client.c: Re-added 'windowinfo' parameter now we know
+ that DBus doesn't NULL check variants either (of type GValue*).
+
+ * src/Makefile.am:
+ * tests/Makefile.am: Use CLEANFILES not CLEAN_FILES so we actually
+ do clean up the bindings generated source files.
+
+2006-10-26 Martyn Russell <martyn@imendio.com>
+
+ * acinclude.m4:
+ * configure.ac:
+ * data/Makefile.am:
+ * data/org.gnome.dapi.service.in: Added service files needed to
+ start dbus daemon if it is not already started.
+
+2006-10-26 Martyn Russell <martyn@imendio.com>
+
+ * src/dapi-command.c:
+ * src/dapi-gnome.[ch]: Added additional checks in dapi-command.c
+ for the incoming variables from dbus, since NULL parameters are
+ passed as "" for G_TYPE_STR, this means checking for NULL is not
+ sufficient, we also need to check for empty strings.
+
+ * tests/test-api.c: Comment out the run_as_user failure check
+ because we know that it won't return FALSE due to the way gksu
+ works and there is no point in checking something we know is going
+ to fail.
+
+2006-10-26 Mikael Hallendal <micke@imendio.com>
+
+ * src/dapi-command.c: (dbus_finalize):
+ - Use dapi_command_parent_class instead of parent_class.
+
+2006-10-26 Martyn Russell <martyn@imendio.com>
+
+ * ChangeLog-pre-1.0: Removed.
+
+2006-10-24 Martyn Russell <martyn@imendio.com>
+
+ * src/dapi-command.c:
+ * tests/test-api.c:
+ * tests/test-client.c: Fixed the const gchar ** attachments
+ crashers that were occuring in the tests, dbus doesn't NULL check
+ G_TYPE_STRV before doing something with it and it crashes in dbus
+ somewhere.
+
+2006-10-23 Martyn Russell <martyn@imendio.com>
+
+ * configure.ac:
+ * tests/Makefile.am:
+ * tests/test-api.c: Added to test the API with Check, the test
+ suite tool.
+
+2006-10-23 Martyn Russell <martyn@imendio.com>
+
+ * README:
+ * TODO:
+ * src/dapi-command.[ch]:
+ * src/dapi-gnome.[ch]:
+ * tests/test-daemon.c: Finished implementing the last few
+ asynchronous functions and now the dapi-gnome.[ch] later fully
+ uses GError. Plus fixed some memory leaks.
+
+2006-10-20 Martyn Russell <martyn@imendio.com>
+
+ * README: Comments from Tim Janik added.
+
+ * src/dapi-command.[ch]:
+ * src/dapi-gnome.[ch]:
+ * tests/test-daemon.c: Implemented most of the asynchronous functions.
+
+2006-10-19 Martyn Russell <martyn@imendio.com>
+
+ * README: Added questions/API changes.
+
+ * src/dapi-command.c:
+ * src/dapi-listener.c: Updated to use# new dapi-gnome API.
+
+ * src/dapi-dbus.[ch]:
+ * src/dapi-dbus.xml:
+ * src/dapi-gnome.[ch]: New API updates.
+
+ * tests/Makefile.am:
+ * tests/test-daemon.c: Start to use dbus calls instead of old IPC
+ to talk to the daemon.
+
+2006-10-16 Martyn Russell <martyn@imendio.com>
+
+ * TODO:
+ * README:
+ * src/dapi-dbus.c: Add checks on all functions to make sure they
+ are NULL safe and also hook up the OpenURL, ExecuteURL and
+ Capabilities functions so they work over dbus with dbus-send.
+
+2006-10-16 Martyn Russell <martyn@imendio.com>
+
+ * src/dapi-daemon.c: (main):
+ * src/dapi-dbus.[ch]:
+ * src/dapi-gnome.[ch]:
+ * src/dapi-listener.[ch]: Improve debugging a little.
+
+2006-10-16 Martyn Russell <martyn@imendio.com>
+
+ * Makefile.am:
+ * configure.ac:
+ * test-program/Makefile.am:
+ * test-program/README:
+ * test-program/test-daemon.c:
+ * test-program/test-ebook-async-get-contact.c: Renamed the tests
+ directory to tests.
+
+2006-10-16 Martyn Russell <martyn@imendio.com>
+
+ * configure.ac:
+ * src/Makefile.am:
+ * src/dapi-dbus.c:
+ * src/dapi-dbus.h:
+ * src/dapi-dbus.xml: Added the initial dbus interface for the daemon.
+
+2006-07-28 Mikael Hallendal <micke@imendio.com>
+
+ * Release 0.1
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..23e5f25
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,236 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script). Here is a another example:
+
+ /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..139965a
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = data src tests
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..aa175ff
--- /dev/null
+++ b/README
@@ -0,0 +1,53 @@
+About Dapi-GNOME:
+=================
+Dapi-GNOME is a daemon that implements the Dapi commands for GNOME.
+
+Requirements:
+=============
+
+* GLib2 >= 2.10.0
+* Gtk+ >= 2.8.0
+* GnomeVFS >= 2.0.0
+* GConf >= 1.2.0
+* EBook >= 1.6.1
+* D-BUS >= 0.60
+* D-BUS Glib >= 0.71
+
+For unit tests Check 0.9.0 is required.
+
+D-Bus:
+======
+You can use the D-Bus interface in the dapi-daemon with the dbus-send command.
+
+For example:
+
+ $ dbus-send --print-reply --dest=org.freedesktop.dapi /org/freedesktop/dapi \
+ org.freedesktop.dapi.OpenUrl string:'http://www.imendio.com' \
+ variant:string:''
+
+ method return sender=:1.49 -> dest=:1.55
+
+D-BUS Protocol:
+===============
+The protocol XML file can be found in data/dapi-command.xml
+
+Activation:
+===========
+We currently install a service file to activate the daemon. This isn't feasible
+when we have more than one implementation of the Dapi Daemon, instead the
+desktop should be responsible for starting the correct daemon which will
+register under the org.freedesktop.dapi namespace.
+
+Running Tests:
+==============
+When running the tests/test-api application (which makes use of the
+Check test suite) to extensively test the API over DBus, one of the address book
+tests may fail on a cleanly built machine. This happens because the
+"About Me" dialog in Gnome which is used to configure your personal
+information will add the contact needed in Evolution Data Server for
+all tests to succeed.
+
+The upload-file API in DBus is not covered by these tests because it
+doesn't test anything locally and so making a test case for that is
+difficult.
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..1fa39c2
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+TODO:
+=====
+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..4f736e9
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,418 @@
+dnl Turn on the additional warnings last, so -Werror doesn't affect other tests.
+
+AC_DEFUN([IDT_COMPILE_WARNINGS],[
+ if test -f $srcdir/autogen.sh; then
+ default_compile_warnings="error"
+ else
+ default_compile_warnings="no"
+ fi
+
+ AC_ARG_WITH(compile-warnings, [ --with-compile-warnings=[no/yes/error] Compiler warnings ], [enable_compile_warnings="$withval"], [enable_compile_warnings="$default_compile_warnings"])
+
+ warnCFLAGS=
+ if test "x$GCC" != xyes; then
+ enable_compile_warnings=no
+ fi
+
+ warning_flags=
+ realsave_CFLAGS="$CFLAGS"
+
+ case "$enable_compile_warnings" in
+ no)
+ warning_flags=
+ ;;
+ yes)
+ warning_flags="-Wall -Wunused -Wmissing-prototypes -Wmissing-declarations"
+ ;;
+ maximum|error)
+ warning_flags="-Wall -Wunused -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith"
+ CFLAGS="$warning_flags $CFLAGS"
+ for option in -Wno-sign-compare; do
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $option"
+ AC_MSG_CHECKING([whether gcc understands $option])
+ AC_TRY_COMPILE([], [],
+ has_option=yes,
+ has_option=no,)
+ CFLAGS="$SAVE_CFLAGS"
+ AC_MSG_RESULT($has_option)
+ if test $has_option = yes; then
+ warning_flags="$warning_flags $option"
+ fi
+ unset has_option
+ unset SAVE_CFLAGS
+ done
+ unset option
+ if test "$enable_compile_warnings" = "error" ; then
+ warning_flags="$warning_flags -Werror"
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings)
+ ;;
+ esac
+ CFLAGS="$realsave_CFLAGS"
+ AC_MSG_CHECKING(what warning flags to pass to the C compiler)
+ AC_MSG_RESULT($warning_flags)
+
+ WARN_CFLAGS="$warning_flags"
+ AC_SUBST(WARN_CFLAGS)
+])
+
+AC_DEFUN([IDT_PATH_CHECK],
+[
+ AC_ARG_WITH(check,
+ [ --with-check=PATH prefix where check is installed [default=auto]])
+
+ min_check_version=ifelse([$1], ,0.8.2,$1)
+
+ AC_MSG_CHECKING(for check - version >= $min_check_version)
+
+ if test x$with_check = xno; then
+ AC_MSG_RESULT(disabled)
+ ifelse([$3], , AC_MSG_ERROR([disabling check is not supported]), [$3])
+ else
+ if test "x$with_check" != x; then
+ CHECK_CFLAGS="-I$with_check/include"
+ CHECK_LIBS="-L$with_check/lib -lcheck"
+ else
+ CHECK_CFLAGS=""
+ CHECK_LIBS="-lcheck"
+ fi
+
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $CHECK_CFLAGS"
+ LIBS="$CHECK_LIBS $LIBS"
+
+ rm -f conf.check-test
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <check.h>
+
+int main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.check-test");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = strdup("$min_check_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_check_version");
+ return 1;
+ }
+
+ if ((CHECK_MAJOR_VERSION != check_major_version) ||
+ (CHECK_MINOR_VERSION != check_minor_version) ||
+ (CHECK_MICRO_VERSION != check_micro_version))
+ {
+ printf("\n*** The check header file (version %d.%d.%d) does not match\n",
+ CHECK_MAJOR_VERSION, CHECK_MINOR_VERSION, CHECK_MICRO_VERSION);
+ printf("*** the check library (version %d.%d.%d).\n",
+ check_major_version, check_minor_version, check_micro_version);
+ return 1;
+ }
+
+ if ((check_major_version > major) ||
+ ((check_major_version == major) && (check_minor_version > minor)) ||
+ ((check_major_version == major) && (check_minor_version == minor) && (check_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of check (%d.%d.%d) was found.\n",
+ check_major_version, check_minor_version, check_micro_version);
+ printf("*** You need a version of check being at least %d.%d.%d.\n", major, minor, micro);
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the check library and header\n");
+ printf("*** file is being found. Rerun configure with the --with-check=PATH option\n");
+ printf("*** to specify the prefix where the correct version was installed.\n");
+ }
+
+ return 1;
+}
+],, no_check=yes, [echo $ac_n "cross compiling; assumed OK... $ac_c"])
+
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ if test "x$no_check" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test -f conf.check-test ; then
+ :
+ else
+ echo "*** Could not run check test program, checking why..."
+ CFLAGS="$CFLAGS $CHECK_CFLAGS"
+ LIBS="$CHECK_LIBS $LIBS"
+ AC_TRY_LINK([
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <check.h>
+], , [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding check. You'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+ [ echo "*** The test program failed to compile or link. See the file config.log for"
+ echo "*** the exact error that occured." ])
+
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+
+ CHECK_CFLAGS=""
+ CHECK_LIBS=""
+
+ rm -f conf.check-test
+ ifelse([$3], , AC_MSG_ERROR([check not found]), [$3])
+ fi
+
+ AC_SUBST(CHECK_CFLAGS)
+ AC_SUBST(CHECK_LIBS)
+
+ rm -f conf.check-test
+
+ fi
+])
+
+dnl Autoconf macros for libgnutls
+dnl $id$
+
+dnl AM_PATH_LIBGNUTLS([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND
+]]])
+dnl Test for libgnutls, and define LIBGNUTLS_CFLAGS and LIBGNUTLS_LIBS
+dnl
+AC_DEFUN(AM_PATH_LM_LIBGNUTLS,
+[dnl
+dnl Get the cflags and libraries from the libgnutls-config script
+dnl
+AC_ARG_WITH(libgnutls-prefix,
+ [ --with-libgnutls-prefix=PFX Prefix where libgnutls is installed (optional)],
+ libgnutls_config_prefix="$withval", libgnutls_config_prefix="")
+
+ if test x$libgnutls_config_prefix != x ; then
+ libgnutls_config_args="$libgnutls_config_args --prefix=$libgnutls_config_prefix"
+ if test x${LIBGNUTLS_CONFIG+set} != xset ; then
+ LIBGNUTLS_CONFIG=$libgnutls_config_prefix/bin/libgnutls-config
+ fi
+ fi
+
+ AC_PATH_PROG(LIBGNUTLS_CONFIG, libgnutls-config, no)
+ min_libgnutls_version=ifelse([$1], ,0.1.0,$1)
+ AC_MSG_CHECKING(for libgnutls - version >= $min_libgnutls_version)
+ no_libgnutls=""
+ if test "$LIBGNUTLS_CONFIG" = "no" ; then
+ no_libgnutls=yes
+ else
+ LIBGNUTLS_CFLAGS=`$LIBGNUTLS_CONFIG $libgnutls_config_args --cflags`
+ LIBGNUTLS_LIBS=`$LIBGNUTLS_CONFIG $libgnutls_config_args --libs`
+ libgnutls_config_version=`$LIBGNUTLS_CONFIG $libgnutls_config_args --version`
+
+
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
+ LIBS="$LIBS $LIBGNUTLS_LIBS"
+dnl
+dnl Now check if the installed libgnutls is sufficiently new. Also sanity
+dnl checks the results of libgnutls-config to some extent
+dnl
+ rm -f conf.libgnutlstest
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnutls/gnutls.h>
+int
+main ()
+{
+ system ("touch conf.libgnutlstest");
+
+ if( strcmp( gnutls_check_version(NULL), "$libgnutls_config_version" ) )
+ {
+ printf("\n*** 'libgnutls-config --version' returned %s, but LIBGNUTLS (%s)\n",
+ "$libgnutls_config_version", gnutls_check_version(NULL) );
+ printf("*** was found! If libgnutls-config was correct, then it is best\n");
+ printf("*** to remove the old version of LIBGNUTLS. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If libgnutls-config was wrong, set the environment variable LIBGNUTLS_CONFIG\n");
+ printf("*** to point to the correct copy of libgnutls-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+ else if ( strcmp(gnutls_check_version(NULL), LIBGNUTLS_VERSION ) )
+ {
+ printf("\n*** LIBGNUTLS header file (version %s) does not match\n", LIBGNUTLS_VERSION);
+ printf("*** library (version %s)\n", gnutls_check_version(NULL) );
+ }
+ else
+ {
+ if ( gnutls_check_version( "$min_libgnutls_version" ) )
+ {
+ return 0;
+ }
+ else
+ {
+ printf("no\n*** An old version of LIBGNUTLS (%s) was found.\n",
+ gnutls_check_version(NULL) );
+ printf("*** You need a version of LIBGNUTLS newer than %s. The latest version of\n",
+ "$min_libgnutls_version" );
+ printf("*** LIBGNUTLS is always available from ftp://gnutls.hellug.gr/pub/gnutls.\n");
+ printf("*** \n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the libgnutls-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of LIBGNUTLS, but you can also set the LIBGNUTLS_CONFIG environment to point to the\n");
+ printf("*** correct copy of libgnutls-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_libgnutls=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+
+ if test "x$no_libgnutls" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ if test -f conf.libgnutlstest ; then
+ :
+ else
+ AC_MSG_RESULT(no)
+ fi
+ if test "$LIBGNUTLS_CONFIG" = "no" ; then
+ echo "*** The libgnutls-config script installed by LIBGNUTLS could not be found"
+ echo "*** If LIBGNUTLS was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the LIBGNUTLS_CONFIG environment variable to
+the"
+ echo "*** full path to libgnutls-config."
+ else
+ if test -f conf.libgnutlstest ; then
+ :
+ else
+ echo "*** Could not run libgnutls test program, checking why..."
+ CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
+ LIBS="$LIBS $LIBGNUTLS_LIBS"
+ AC_TRY_LINK([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnutls/gnutls.h>
+], [ return !!gnutls_check_version(NULL); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding LIBGNUTLS or finding the wrong"
+ echo "*** version of LIBGNUTLS. If it is not finding LIBGNUTLS, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means LIBGNUTLS was incorrectly installed"
+ echo "*** or that you have moved LIBGNUTLS since it was installed. In
+the latter case, you"
+ echo "*** may want to edit the libgnutls-config script: $LIBGNUTLS_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ LIBGNUTLS_CFLAGS=""
+ LIBGNUTLS_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ rm -f conf.libgnutlstest
+ AC_SUBST(LIBGNUTLS_CFLAGS)
+ AC_SUBST(LIBGNUTLS_LIBS)
+])
+
+
+dnl
+dnl Timezone checks
+dnl
+AC_DEFUN([LM_CHECK_TIMEZONE],[
+AC_CACHE_CHECK(for tm_gmtoff in struct tm, ac_cv_struct_tm_gmtoff,
+ AC_TRY_COMPILE([
+ #include <time.h>
+ ], [
+ struct tm tm;
+ tm.tm_gmtoff = 1;
+ ], ac_cv_struct_tm_gmtoff=yes, ac_cv_struct_tm_gmtoff=no))
+if test $ac_cv_struct_tm_gmtoff = yes; then
+ AC_DEFINE(HAVE_TM_GMTOFF, 1, [Define if struct tm has a tm_gmtoff member])
+else
+ AC_CACHE_CHECK(for timezone variable, ac_cv_var_timezone,
+ AC_TRY_COMPILE([
+ #include <time.h>
+ ], [
+ timezone = 1;
+ ], ac_cv_var_timezone=yes, ac_cv_var_timezone=no))
+ if test $ac_cv_var_timezone = yes; then
+ AC_DEFINE(HAVE_TIMEZONE, 1, [Define if libc defines a timezone variable])
+ else
+ AC_ERROR(unable to find a way to determine timezone)
+ fi
+fi
+])
+
+dnl
+dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
+dnl
+dnl Example:
+dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
+dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
+dnl
+AC_DEFUN([AS_AC_EXPAND],
+[
+ EXP_VAR=[$1]
+ FROM_VAR=[$2]
+
+ dnl First expand prefix and exec_prefix if necessary
+ prefix_save=$prefix
+ exec_prefix_save=$exec_prefix
+
+ dnl If no prefix given, then use /usr/local, the default prefix
+ if test "x$prefix" = "xNONE"; then
+ prefix=$ac_default_prefix
+ fi
+ dnl If no exec_prefix given, then use prefix
+ if test "x$exec_prefix" = "xNONE"; then
+ exec_prefix=$prefix
+ fi
+
+ full_var="$FROM_VAR"
+ dnl Loop until it doesn't change anymore
+ while true; do
+ new_full_var="`eval echo $full_var`"
+ if test "x$new_full_var"="x$full_var"; then break; fi
+ full_var=$new_full_var
+ done
+
+ dnl Clean up
+ full_var=$new_full_var
+ AC_SUBST([$1], "$full_var")
+
+ dnl Restore prefix and exec_prefix
+ prefix=$prefix_save
+ exec_prefix=$exec_prefix_save
+])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..9593d55
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,191 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+: ${AUTOCONF=autoconf}
+: ${AUTOHEADER=autoheader}
+: ${AUTOMAKE=automake-1.9}
+: ${ACLOCAL=aclocal-1.9}
+: ${LIBTOOLIZE=libtoolize}
+: ${INTLTOOLIZE=intltoolize}
+: ${LIBTOOL=libtool}
+: ${GNOME_DOC_PREPARE=gnome-doc-prepare}
+: ${GTKDOCIZE=gtkdocize}
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+PROJECT="dapi_gnome"
+TEST_TYPE=-f
+FILE=src/dapi-daemon.c
+CONFIGURE=configure.ac
+
+DIE=0
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(grep "^AC_PROG_INTLTOOL" $srcdir/$CONFIGURE >/dev/null) && {
+ ($INTLTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have \`intltoolize' installed to compile $PROJECT."
+ echo "Get ftp://ftp.gnome.org/pub/GNOME/stable/sources/intltool/intltool-0.22.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+(grep "^GNOME_DOC_INIT" $srcdir/$CONFIGURE >/dev/null) && {
+ ($GNOME_DOC_PREPARE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have \`gnome-doc-prepare' installed to compile $PROJECT."
+ #echo "Get ftp://ftp.gnome.org/pub/GNOME/stable/sources/intltool/intltool-0.22.tar.gz"
+ #echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+if grep "^GTK_DOC_CHECK" $srcdir/$CONFIGURE; then
+ ($GTKDOCIZE --version) < /dev/null > /dev/null 2>&1 || {
+ echo;
+ echo "You need gtk-doc to build $PACKAGE";
+ echo;
+ }
+fi
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake installed to compile $PROJECT."
+ echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.9.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+(grep "^AM_PROG_LIBTOOL" $CONFIGURE >/dev/null) && {
+ ($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`libtool' installed to compile $PROJECT."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.4.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+if grep "^AM_[A-Z0-9_]\{1,\}_GETTEXT" "$CONFIGURE" >/dev/null; then
+ if grep "sed.*POTFILES" "$CONFIGURE" >/dev/null; then
+ GETTEXTIZE=""
+ else
+ if grep "^AM_GLIB_GNU_GETTEXT" "$CONFIGURE" >/dev/null; then
+ GETTEXTIZE="glib-gettextize"
+ GETTEXTIZE_URL="ftp://ftp.gtk.org/pub/gtk/v2.0/glib-2.0.0.tar.gz"
+ else
+ GETTEXTIZE="gettextize"
+ GETTEXTIZE_URL="ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
+ fi
+
+ $GETTEXTIZE --version < /dev/null > /dev/null 2>&1
+ if test $? -ne 0; then
+ echo
+ echo "**Error**: You must have \`$GETTEXTIZE' installed to compile $PKG_NAME."
+ echo "Get $GETTEXTIZE_URL"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ fi
+ fi
+fi
+
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+#if test -z "$*"; then
+# echo "I am going to run ./configure with no arguments - if you wish "
+# echo "to pass any to it, please specify them on the $0 command line."
+#fi
+
+case $CC in
+*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
+esac
+
+for coin in .
+do
+ dr=`dirname $coin`
+ if test -f $dr/NO-AUTO-GEN; then
+ echo skipping $dr -- flagged as no auto-gen
+ else
+ echo processing $dr
+ macrodirs= #`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
+ ( cd $dr
+ aclocalinclude="$ACLOCAL_FLAGS"
+ for k in $macrodirs; do
+ if test -d $k; then
+ aclocalinclude="$aclocalinclude -I $k"
+ ##else
+ ## echo "**Warning**: No such directory \`$k'. Ignored."
+ fi
+ done
+ if grep "^AM_GLIB_GNU_GETTEXT" $CONFIGURE >/dev/null; then
+ if grep "sed.*POTFILES" $CONFIGURE >/dev/null; then
+ : do nothing -- we still have an old unmodified $CONFIGURE
+ else
+ echo "Creating $dr/aclocal.m4 ..."
+ test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+ echo "Running glib-gettextize... Ignore non-fatal messages."
+ echo "no" | glib-gettextize --force --copy
+ echo "Making $dr/aclocal.m4 writable ..."
+ test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+ fi
+ fi
+ if grep "^AC_PROG_INTLTOOL" $CONFIGURE >/dev/null; then
+ echo "Running intltoolize..."
+ intltoolize --copy --force --automake
+ fi
+ if grep "^GNOME_DOC_INIT" $CONFIGURE >/dev/null; then
+ echo "Running $GNOME_DOC_PREPARE..."
+ $GNOME_DOC_PREPARE --force --copy || exit 1
+ fi
+ if grep "^AM_PROG_LIBTOOL" $CONFIGURE >/dev/null; then
+ echo "Running $LIBTOOLIZE..."
+ $LIBTOOLIZE --force --copy
+ fi
+ echo "Running $ACLOCAL $aclocalinclude ..."
+ $ACLOCAL $aclocalinclude
+ if grep "^GTK_DOC_CHECK" $CONFIGURE > /dev/null; then
+ echo "Running $GTKDOCIZE..."
+ $GTKDOCIZE
+ fi
+ if grep "^AM_CONFIG_HEADER" $CONFIGURE >/dev/null; then
+ echo "Running $AUTOHEADER..."
+ $AUTOHEADER
+ fi
+ echo "Running $AUTOMAKE --gnu $am_opt ..."
+ $AUTOMAKE --add-missing --gnu $am_opt
+ echo "Running $AUTOCONF ..."
+ $AUTOCONF
+ )
+ fi
+done
+
+conf_flags="--enable-maintainer-mode"
+
+cd "$ORIGDIR"
+
+if test x$NOCONFIGURE = x; then
+ echo Running $srcdir/configure $conf_flags "$@" ...
+ $srcdir/configure $conf_flags "$@" \
+ && echo Now type \`make\' to compile $PROJECT || exit 1
+else
+ echo Skipping configure process.
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..aa698ea
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,170 @@
+AC_INIT(DAPI GNOME Daemon, 0.2, dapi_gnome)
+AC_PREREQ(2.59)
+AC_COPYRIGHT([Copyright (C) 2003-2006 Imendio AB])
+
+AC_CONFIG_SRCDIR(src/dapi-daemon.c)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(1.9 dist-bzip2 no-define)
+
+AM_MAINTAINER_MODE
+
+AC_CANONICAL_HOST
+
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+AC_ISC_POSIX
+AC_HEADER_STDC
+AC_LIBTOOL_WIN32_DLL
+AM_PROG_LIBTOOL
+
+AM_PATH_GLIB_2_0
+
+IDT_COMPILE_WARNINGS
+
+changequote(,)dnl
+if test "x$GCC" = "xyes"; then
+ case " $CFLAGS " in
+ *[\ \ ]-Wall[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wall" ;;
+ esac
+fi
+changequote([,])dnl
+
+AC_SUBST(CFLAGS)
+AC_SUBST(LDFLAGS)
+
+LM_CHECK_TIMEZONE
+
+# Checks for header files.
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_SELECT_ARGTYPES
+AC_CHECK_FUNCS([gethostname select socket strrchr])
+
+
+# Check for sudo command.
+#
+# We could do this ourself, but it is easier to use an external
+# command since they blank the screen and handle it much nicer.
+#
+AC_PATH_PROG(have_gksu, gksu, "no")
+
+if test x$have_gksu != xno; then
+ AC_DEFINE_UNQUOTED(HAVE_GKSU, "$have_gksu", [Define path to gksu if you have support])
+fi
+
+
+# Check for gnome-screensaver
+AC_PATH_PROG(have_gnome_screensaver, gnome-screensaver-command, "no")
+
+if test x$have_gnome_screensaver != xno; then
+ AC_DEFINE_UNQUOTED(HAVE_GNOME_SCREENSAVER, "$have_gnome_screensaver", [Define path to gnome-screensaver-command if you have it])
+fi
+
+
+# Dependencies
+AC_SUBST(GLIB2_REQUIRED, 2.10.0)
+AC_SUBST(GTK_REQUIRED, 2.8.0)
+AC_SUBST(GNOMEVFS_REQUIRED, 2.0.0)
+AC_SUBST(GCONF_REQUIRED, 1.2.0)
+AC_SUBST(EBOOK_REQUIRED, 1.6.1)
+AC_SUBST(DBUS_REQUIRED, 0.60)
+AC_SUBST(DBUS_GLIB_REQUIRED, 0.71)
+
+PKG_CHECK_MODULES(DAPI_GNOME,
+[
+ glib-2.0 >= $GLIB2_REQUIRED
+ gtk+-2.0 >= $GTK_REQUIRED
+ gnome-vfs-2.0 >= $GNOMEVFS_REQUIRED
+ gconf-2.0 >= $GCONF_REQUIRED
+ libebook-1.2 >= $EBOOK_REQUIRED
+ dbus-1 >= $DBUS_REQUIRED
+ dbus-glib-1 >= $DBUS_GLIB_REQUIRED
+])
+
+# Check we have the DBUS binding tool we need
+AC_PATH_PROG(DBUSBINDINGTOOL, dbus-binding-tool)
+if test -z $DBUSBINDINGTOOL; then
+ AC_MSG_ERROR([Could not find 'dbus-binding-tool'])
+fi
+
+
+# Check that we have test suite
+m4_ifdef([AM_PATH_CHECK],[AM_PATH_CHECK(0.9.0, have_check=yes, have_check=no)],[have_check=no])
+
+
+# Define a MAINT-like variable REBUILD which is set if Perl
+# and awk are found, so autogenerated sources can be rebuilt
+AC_ARG_ENABLE(rebuilds,
+ AS_HELP_STRING([--enable-rebuilds=@<:@no/yes/auto@:>@],
+ [Enable source autogeneration rules [[default=yes]]]), ,
+ enable_rebuilds=yes)
+
+REBUILD=\#
+if test "x$enable_rebuilds" = "xyes" && \
+ test -n "$PERL" && \
+ $PERL -e 'exit !($] >= 5.002)' > /dev/null 2>&1 && \
+ test -n "$AWK" ; then
+ REBUILD=
+fi
+AC_SUBST(REBUILD)
+
+
+# Build flags
+DOC_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS $WARN_CFLAGS"
+AC_SUBST(DOC_CFLAGS)
+AC_SUBST(CFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+
+
+# Debugging
+AC_ARG_ENABLE(debug,
+ AS_HELP_STRING([--enable-debug=@<:@no/yes/auto@:>@],
+ [Enable debugging [[default=yes]]]), ,
+ enable_debug=yes)
+
+if test x$enable_debug = xno ; then
+ DAPI_GNOME_CFLAGS="$DAPI_GNOME_CFLAGS -DDAPI_GNOME_NO_DEBUG"
+fi
+
+
+# Finish
+AC_SUBST(DAPI_GNOME_CFLAGS)
+AC_SUBST(DAPI_GNOME_LIBS)
+
+AC_OUTPUT([
+Makefile
+data/Makefile
+src/Makefile
+tests/Makefile])
+
+echo "
+
+ DAPI-Gnome $VERSION
+ ===================
+
+ Prefix: ${prefix}
+ Compiler: ${CC}
+ Debugging: ${enable_debug}
+ Check test suite: ${have_check}
+
+ Gksu: ${have_gksu}
+ Gnome Screensaver: ${have_gnome_screensaver}
+
+ Now type 'make' to build DAPI Gnome
+"
+
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..7ead8bb
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,18 @@
+#
+# DBUS
+#
+
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.freedesktop.dapi.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@bindir\@|$(bindir)|" $< > $@
+
+EXTRA_DIST = \
+ dapi-command.xml \
+ dapi-common.h \
+ $(service_in_files)
+
+CLEANFILES = \
+ $(service_DATA)
diff --git a/data/dapi-command.xml b/data/dapi-command.xml
new file mode 100644
index 0000000..2a5a42f
--- /dev/null
+++ b/data/dapi-command.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+ <interface name="org.freedesktop.dapi">
+ <method name="Capabilities">
+ <arg name="capabilities" type="i" direction="out"/>
+ </method>
+
+ <!-- URL API -->
+ <method name="OpenUrl">
+ <arg name="url" type="s" direction="in"/>
+ <arg name="windowinfo" type="v" direction="in"/>
+ </method>
+ <method name="ExecuteUrl">
+ <arg name="url" type="s" direction="in"/>
+ <arg name="windowinfo" type="v" direction="in"/>
+ </method>
+
+ <!-- Misc API -->
+ <method name="ButtonOrder">
+ <arg name="order" type="i" direction="out"/>
+ </method>
+ <method name="RunAsUser">
+ <arg name="user" type="s" direction="in"/>
+ <arg name="command" type="s" direction="in"/>
+ <arg name="windowinfo" type="v" direction="in"/>
+ </method>
+ <method name="SuspendScreenSaving">
+ <arg name="client_id" type="u" direction="in"/>
+ <arg name="suspend" type="b" direction="in"/>
+ </method>
+
+ <!-- Mail API -->
+ <method name="MailTo">
+ <arg name="subject" type="s" direction="in"/>
+ <arg name="body" type="s" direction="in"/>
+ <arg name="to" type="s" direction="in"/>
+ <arg name="cc" type="s" direction="in"/>
+ <arg name="bcc" type="s" direction="in"/>
+ <arg name="attachments" type="as" direction="in"/>
+ <arg name="windowinfo" type="v" direction="in"/>
+ </method>
+
+ <!-- File API -->
+ <method name="LocalFile">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="url" type="s" direction="in"/>
+ <arg name="local" type="s" direction="in"/>
+ <arg name="allow_download" type="b" direction="in"/>
+ <arg name="filename" type="s" direction="out"/>
+ <arg name="windowinfo" type="v" direction="in"/>
+ </method>
+ <method name="UploadFile">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="local" type="s" direction="in"/>
+ <arg name="url" type="s" direction="in"/>
+ <arg name="remove_local" type="b" direction="in"/>
+ <arg name="windowinfo" type="v" direction="in"/>
+ </method>
+ <method name="RemoveTemporaryLocalFile">
+ <arg name="local" type="s" direction="in"/>
+ </method>
+
+ <!-- Address Book API -->
+ <method name="AddressBookList">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="contact_ids" type="as" direction="out"/>
+ </method>
+ <method name="AddressBookOwner">
+ <arg name="contact_id" type="s" direction="out"/>
+ </method>
+ <method name="AddressBookFindByName">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="name" type="s" direction="in"/>
+ <arg name="contact_ids" type="as" direction="out"/>
+ </method>
+ <method name="AddressBookGetName">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="contact_id" type="s" direction="in"/>
+ <arg name="given_name" type="s" direction="out"/>
+ <arg name="family_name" type="s" direction="out"/>
+ <arg name="full_name" type="s" direction="out"/>
+ </method>
+ <method name="AddressBookGetEmails">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="contact_id" type="s" direction="in"/>
+ <arg name="email_addresses" type="as" direction="out"/>
+ </method>
+ <method name="AddressBookGetVCard30">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="contact_id" type="s" direction="in"/>
+ <arg name="vcard" type="s" direction="out"/>
+ </method>
+ </interface>
+</node>
+
diff --git a/data/dapi-common.h b/data/dapi-common.h
new file mode 100644
index 0000000..b6d547d
--- /dev/null
+++ b/data/dapi-common.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __DAPI_COMMON_H__
+#define __DAPI_COMMON_H__
+
+typedef enum {
+ DAPI_CAP_OPENURL = 1 << 0,
+ DAPI_CAP_EXECUTEURL = 1 << 1,
+ DAPI_CAP_BUTTONORDER = 1 << 2,
+ DAPI_CAP_RUNASUSER = 1 << 3,
+ DAPI_CAP_SUSPENDSCREENSAVING = 1 << 4,
+ DAPI_CAP_MAILTO = 1 << 5,
+ DAPI_CAP_LOCALFILE = 1 << 6,
+ DAPI_CAP_UPLOADFILE = 1 << 7,
+ DAPI_CAP_REMOVETEMPORARYLOCALFILE = 1 << 8,
+ DAPI_CAP_ADDRESSBOOKLIST = 1 << 9,
+ DAPI_CAP_ADDRESSBOOKGETNAME = 1 << 10,
+ DAPI_CAP_ADDRESSBOOKGETEMAILS = 1 << 11,
+ DAPI_CAP_ADDRESSBOOKFINDBYNAME = 1 << 12,
+ DAPI_CAP_ADDRESSBOOKOWNER = 1 << 13,
+ DAPI_CAP_ADDRESSBOOKGETVCARD30 = 1 << 14
+} DapiCapability;
+
+#endif /* __DAPI_COMMON_H__ */
+
diff --git a/data/org.freedesktop.dapi.service.in b/data/org.freedesktop.dapi.service.in
new file mode 100644
index 0000000..067bb70
--- /dev/null
+++ b/data/org.freedesktop.dapi.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.dapi
+Exec=@bindir@/dapi_gnome
diff --git a/doc/status-report-20060714.txt b/doc/status-report-20060714.txt
new file mode 100644
index 0000000..d7929a6
--- /dev/null
+++ b/doc/status-report-20060714.txt
@@ -0,0 +1,29 @@
+GNOME Integration for Project Portland:
+=======================================
+
+REPORTING PERIOD:
+July 3rd 2006 - July 14th 2006
+
+ACHIEVEMENTS/CLOSED ISSUES:
+The daemon is implemented and all the functionality is in place. A few comments
+have been brought up and are listed in the MISC section and will pasted in the
+report email for discussion.
+
+We have currently put the GNOME daemon in it's own package outside of the
+generic/KDE build tree for easier split out and putting it in the GnomeCVS. If
+it would be better to keep it in the Portland source tree for now it can be
+adapted for that.
+
+NEXT WEEKS/ISSUES IN PROGRESS:
+
+Next week both Mikael Hallendal and Martyn Russell will be on vacation. The
+week leading up to delivery will be used for testing and debugging of the
+daemon.
+
+PROBLEMS:
+None.
+
+MISC:
+The OpenUrl and ExecuteUrl functionality is a bit odd, or at least the naming.
+Suggestions would be OpenUrl (for the current ExecuteUrl functionality) and
+OpenUrlInBrowser (for doing what OpenUrl does right now).
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..be9395d
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,34 @@
+#
+# DBUS
+#
+
+BUILT_SOURCES = dapi-command-glue.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+%-glue.h: $(top_builddir)/data/%.xml
+ $(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+
+
+#
+# Daemon
+#
+INCLUDES = \
+ -I$(top_srcdir)/data \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
+ $(DAPI_GNOME_CFLAGS)
+
+bin_PROGRAMS = dapi_gnome
+
+dapi_gnome_SOURCES = \
+ dapi-command.c \
+ dapi-command.h \
+ dapi-daemon.c \
+ dapi-debug.c \
+ dapi-debug.h \
+ dapi-gnome.c \
+ dapi-gnome.h
+
+dapi_gnome_LDADD = \
+ $(DAPI_GNOME_LIBS)
+
diff --git a/src/dapi-command.c b/src/dapi-command.c
new file mode 100644
index 0000000..53e3ff2
--- /dev/null
+++ b/src/dapi-command.c
@@ -0,0 +1,833 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include "dapi-debug.h"
+#include "dapi-command.h"
+#include "dapi-gnome.h"
+
+#define DEBUG_DOMAIN "Command"
+
+#define DAPI_COMMAND_ERROR_DOMAIN "DAPI"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DAPI_TYPE_COMMAND, DapiCommandPriv))
+
+#define NEW_DATA(data, d1, d2, d3) \
+ data = g_new0 (CommandData, 1); \
+ \
+ data->data1 = d1; \
+ data->data2 = d2; \
+ data->data3 = d3;
+
+#define command_async_return_if_fail(expr,context) \
+ G_STMT_START { \
+ if G_LIKELY(expr) { } else { \
+ GError *error = NULL; \
+ \
+ g_set_error (&error, \
+ DAPI_GNOME_ERROR, \
+ 0, \
+ _("Assertion `%s' failed"), \
+ #expr); \
+ \
+ dbus_g_method_return_error (context, error); \
+ g_clear_error (&error); \
+ \
+ return; \
+ }; \
+ } G_STMT_END
+
+#define command_return_val_if_fail(expr,val,error) \
+ G_STMT_START { \
+ if G_LIKELY(expr) { } else { \
+ g_set_error (error, \
+ DAPI_GNOME_ERROR, \
+ 0, \
+ _("Assertion `%s' failed"), \
+ #expr); \
+ \
+ return val; \
+ }; \
+ } G_STMT_END
+
+typedef struct {
+ DBusGProxy *fd_proxy;
+ guint request_id;
+} DapiCommandPriv;
+
+typedef struct {
+ gpointer data1;
+ gpointer data2;
+ gpointer data3;
+} CommandData;
+
+static void dbus_finalize (GObject *obj);
+static guint command_get_next_request_id (DapiCommand *obj);
+static void command_local_file_cb (const gchar *filename,
+ GError *error,
+ gpointer user_data);
+static void command_upload_file_cb (GError *error,
+ gpointer user_data);
+static void command_address_book_list_cb (GList *ids,
+ GError *error,
+ gpointer user_data);
+static void command_address_book_find_by_name_cb (const gchar *name,
+ GList *ids,
+ GError *error,
+ gpointer user_data);
+static void command_address_book_get_name_cb (const gchar *id,
+ const gchar *given_name,
+ const gchar *family_name,
+ const gchar *full_name,
+ GError *error,
+ gpointer user_data);
+static void command_address_book_get_emails_cb (const gchar *id,
+ GList *emails,
+ GError *error,
+ gpointer user_data);
+static void command_address_book_get_vcard_cb (const gchar *id,
+ const gchar *vcard,
+ GError *error,
+ gpointer user_data);
+
+G_DEFINE_TYPE(DapiCommand, dapi_command, G_TYPE_OBJECT)
+
+static void
+dapi_command_class_init (DapiCommandClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = dbus_finalize;
+
+ g_type_class_add_private (object_class, sizeof (DapiCommandPriv));
+}
+
+static void
+dapi_command_init (DapiCommand *obj)
+{
+}
+
+static void
+dbus_finalize (GObject *obj)
+{
+ DapiCommandPriv *priv;
+
+ priv = GET_PRIV (obj);
+
+ dapi_debug (DEBUG_DOMAIN, "Shutting down...");
+
+ if (priv->fd_proxy) {
+ g_object_unref (priv->fd_proxy);
+ }
+
+ G_OBJECT_CLASS (dapi_command_parent_class)->finalize (obj);
+}
+
+GQuark
+dapi_command_error_quark (void)
+{
+ return g_quark_from_static_string (DAPI_COMMAND_ERROR_DOMAIN);
+}
+
+static guint
+command_get_next_request_id (DapiCommand *obj)
+{
+ DapiCommandPriv *priv;
+
+ priv = GET_PRIV (obj);
+
+ return ++(priv->request_id);
+}
+
+/*
+ * Functions
+ */
+gboolean
+dapi_command_capabilities (DapiCommand *obj,
+ gint *capabilities,
+ GError **error)
+{
+ guint request_id;
+
+ command_return_val_if_fail (capabilities != NULL, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for capability set",
+ request_id);
+
+ *capabilities = dapi_gnome_get_capabilities ();
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] Success",
+ request_id);
+
+ return TRUE;
+}
+
+gboolean
+dapi_command_open_url (DapiCommand *obj,
+ const gchar *url,
+ GValue *windowinfo,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ command_return_val_if_fail (url != NULL && strlen (url) > 0, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to open URL:'%s'",
+ request_id, url);
+
+ result = dapi_gnome_open_url (url, error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error:'%s'",
+ request_id,
+ result ? "Success" : "Failed",
+ error && *error ? (*error)->message : "");
+
+ return result;
+}
+
+gboolean
+dapi_command_execute_url (DapiCommand *obj,
+ const gchar *url,
+ GValue *windowinfo,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ command_return_val_if_fail (url != NULL && strlen (url) > 0, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to execute URL:'%s'",
+ request_id, url);
+
+ result = dapi_gnome_execute_url (url, error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error:'%s'",
+ request_id,
+ result ? "Success" : "Failed",
+ error && *error ? (*error)->message : "");
+
+ return result;
+}
+
+gboolean
+dapi_command_button_order (DapiCommand *obj,
+ guint *order,
+ GError **error)
+{
+ gboolean alternative_order;
+ gboolean result;
+ guint request_id;
+
+ command_return_val_if_fail (order != NULL, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for button order",
+ request_id);
+
+ result = dapi_gnome_button_order (&alternative_order, error);
+
+ /* We use a boolean because there are only 2 orders the
+ * buttons can be in, and the spec says we return:
+ * 0 for error,
+ * 1 for cancel/ok.
+ * 2 for ok/cancel,
+ *
+ * We don't return 0, since the error is propagated by DBus.
+ */
+ if (alternative_order) {
+ *order = 2;
+ } else {
+ *order = 1;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s (button order:'%s'), error:'%s'",
+ request_id,
+ result ? "Success" : "Failed",
+ alternative_order ? "alternative" : "normal",
+ error && *error ? (*error)->message : "");
+
+ return result;
+}
+
+gboolean
+dapi_command_run_as_user (DapiCommand *obj,
+ const gchar *user,
+ const gchar *command,
+ GValue *windowinfo,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ command_return_val_if_fail (user != NULL && strlen (user) > 0, FALSE, error);
+ command_return_val_if_fail (command != NULL && strlen (user) > 0, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to run command:'%s' as user:'%s'",
+ request_id, command, user);
+
+ result = dapi_gnome_run_as_user (user, command, error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error:'%s'",
+ request_id,
+ result ? "Success" : "Failed",
+ error && *error ? (*error)->message : "");
+
+ return result;
+}
+
+gboolean
+dapi_command_suspend_screen_saving (DapiCommand *obj,
+ guint client_id,
+ gboolean suspend,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to %s screen saving from client id:%d",
+ request_id,
+ suspend ? "suspend" : "cancel suspend",
+ client_id);
+
+ result = dapi_gnome_suspend_screen_saving (client_id, suspend, error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s",
+ request_id,
+ result ? "Success" : "Failed");
+
+ return result;
+}
+
+gboolean
+dapi_command_mail_to (DapiCommand *obj,
+ const gchar *subject,
+ const gchar *body,
+ const gchar *to,
+ const gchar *cc,
+ const gchar *bcc,
+ const gchar **attachments,
+ GValue *windowinfo,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to send mail to:'%s' with subject:'%s', cc:'%s', bcc:'%s'",
+ request_id, to, subject, cc, bcc);
+
+ result = dapi_gnome_mail_to (to, cc, bcc, subject, body, attachments, error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s",
+ request_id, result ? "Success" : "Failed");
+
+ return result;
+}
+
+static void
+command_local_file_cb (const gchar *filename,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ dbus_g_method_return (context, filename);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_local_file (DapiCommand *obj,
+ const gchar *url,
+ const gchar *local,
+ gboolean allow_download,
+ GValue *windowinfo,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ command_async_return_if_fail (url != NULL && strlen (url) > 0, context);
+ command_async_return_if_fail (local != NULL && strlen (local) > 0, context);
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to get file:'%s' and save as:'%s', %sallowing download",
+ request_id, url, local, allow_download ? "" : "not ");
+
+ dapi_gnome_local_file (url, local, allow_download, command_local_file_cb, data);
+}
+
+static void
+command_upload_file_cb (GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ dbus_g_method_return (context);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_upload_file (DapiCommand *obj,
+ const gchar *local,
+ const gchar *url,
+ gboolean remove_local,
+ GValue *windowinfo,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ command_async_return_if_fail (local != NULL && strlen (local) > 0, context);
+ command_async_return_if_fail (url != NULL && strlen (url) > 0, context);
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to upload file:'%s' to:'%s', %sremoving local file",
+ url, local, remove_local ? "" : "not ");
+
+ dapi_gnome_upload_file (url, local, remove_local, command_upload_file_cb, data);
+}
+
+gboolean
+dapi_command_remove_temporary_local_file (DapiCommand *obj,
+ const gchar *local,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ command_return_val_if_fail (local != NULL && strlen (local) > 0, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request to remove temporary local file:'%s'",
+ request_id, local);
+
+ result = dapi_gnome_remove_temp_local_file (local);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error && *error ? (*error)->message : "no error given");
+
+ return result;
+}
+
+static void
+command_address_book_list_cb (GList *ids,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+ GList *l;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ gchar **strs;
+ gint i;
+
+ strs = g_new (gchar*, g_list_length (ids) + 1);
+ for (l = ids, i = 0; l; l = l->next, i++) {
+ strs[i] = g_strdup (l->data);
+ }
+
+ strs[i] = NULL;
+ dbus_g_method_return (context, strs);
+ g_strfreev (strs);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_address_book_list (DapiCommand *obj,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for address book list",
+ request_id);
+
+ dapi_gnome_address_book_get_list (command_address_book_list_cb, data);
+}
+
+gboolean
+dapi_command_address_book_owner (DapiCommand *obj,
+ gchar **contact_id,
+ GError **error)
+{
+ gboolean result;
+ guint request_id;
+
+ command_return_val_if_fail (contact_id != NULL, FALSE, error);
+
+ request_id = command_get_next_request_id (obj);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> Request for address book owner");
+
+ result = dapi_gnome_address_book_get_owner (contact_id, error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error:'%s'",
+ request_id,
+ result ? "Success" : "Failed",
+ error && *error ? (*error)->message : "no error given");
+
+ return result;
+}
+
+static void
+command_address_book_find_by_name_cb (const gchar *name,
+ GList *ids,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ GList *l;
+ gchar **strs;
+ gint i;
+
+ strs = g_new (gchar*, g_list_length (ids) + 1);
+ for (l = ids, i = 0; l; l = l->next, i++) {
+ strs[i] = g_strdup (l->data);
+ }
+
+ strs[i] = NULL;
+ dbus_g_method_return (context, strs);
+ g_strfreev (strs);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_address_book_find_by_name (DapiCommand *obj,
+ const gchar *name,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ command_async_return_if_fail (name != NULL && strlen (name) > 0, context);
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for address book contact by name:'%s'",
+ request_id, name);
+
+ dapi_gnome_address_book_find_by_name (name, command_address_book_find_by_name_cb, data);
+}
+
+static void
+command_address_book_get_name_cb (const gchar *id,
+ const gchar *given_name,
+ const gchar *family_name,
+ const gchar *full_name,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ dbus_g_method_return (context, given_name, family_name, full_name);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_address_book_get_name (DapiCommand *obj,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ command_async_return_if_fail (contact_id != NULL && strlen (contact_id) > 0, context);
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for address book name for contact:'%s'",
+ request_id, contact_id);
+
+ dapi_gnome_address_book_get_name (contact_id, command_address_book_get_name_cb, data);
+}
+
+static void
+command_address_book_get_emails_cb (const gchar *id,
+ GList *emails,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ GList *l;
+ gchar **strs;
+ gint i;
+
+ strs = g_new (gchar*, g_list_length (emails) + 1);
+ for (l = emails, i = 0; l; l = l->next, i++) {
+ strs[i] = g_strdup (l->data);
+ }
+
+ strs[i] = NULL;
+ dbus_g_method_return (context, strs);
+ g_strfreev (strs);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_address_book_get_emails (DapiCommand *obj,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ command_async_return_if_fail (contact_id != NULL && strlen (contact_id) > 0, context);
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for address book email addresses for contact:'%s'",
+ request_id, contact_id);
+
+ dapi_gnome_address_book_get_emails (contact_id, command_address_book_get_emails_cb, data);
+}
+
+static void
+command_address_book_get_vcard_cb (const gchar *id,
+ const gchar *vcard,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context;
+ CommandData *data;
+ guint request_id;
+
+ data = user_data;
+
+ request_id = GPOINTER_TO_UINT (data->data1);
+ context = data->data2;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "<--- [%d] %s, error: %s",
+ request_id,
+ error ? "Failed" : "Success",
+ error ? error->message : "no error given");
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ } else {
+ dbus_g_method_return (context, vcard);
+ }
+
+ g_free (data);
+}
+
+void
+dapi_command_address_book_get_vcard30 (DapiCommand *obj,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ CommandData *data;
+ guint request_id;
+
+ command_async_return_if_fail (contact_id != NULL && strlen (contact_id) > 0, context);
+
+ request_id = command_get_next_request_id (obj);
+
+ NEW_DATA(data, GUINT_TO_POINTER (request_id), context, NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "---> [%d] Request for address book vcard for contact:'%s'",
+ request_id, contact_id);
+
+ dapi_gnome_address_book_get_vcard (contact_id, command_address_book_get_vcard_cb, data);
+}
+
diff --git a/src/dapi-command.h b/src/dapi-command.h
new file mode 100644
index 0000000..3d2e9b6
--- /dev/null
+++ b/src/dapi-command.h
@@ -0,0 +1,131 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __DAPI_COMMAND_H__
+#define __DAPI_COMMAND_H__
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#define DAPI_SERVICE "org.freedesktop.dapi"
+#define DAPI_PATH "/org/freedesktop/dapi"
+#define DAPI_INTERFACE "org.freedesktop.dapi"
+
+G_BEGIN_DECLS
+
+#define DAPI_TYPE_COMMAND (dapi_command_get_type ())
+#define DAPI_COMMAND(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DAPI_TYPE_COMMAND, DapiCommand))
+#define DAPI_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DAPI_TYPE_COMMAND, DapiCommandClass))
+#define DAPI_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DAPI_TYPE_COMMAND))
+#define DAPI_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DAPI_TYPE_COMMAND))
+#define DAPI_COMMAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DAPI_TYPE_COMMAND, DapiCommandClass))
+
+#define DAPI_COMMAND_ERROR dapi_command_error_quark()
+
+typedef struct DapiCommand DapiCommand;
+typedef struct DapiCommandClass DapiCommandClass;
+
+struct DapiCommand {
+ GObject parent;
+};
+
+struct DapiCommandClass {
+ GObjectClass parent;
+};
+
+GType dapi_command_get_type (void);
+GQuark dapi_command_error_quark (void) G_GNUC_CONST;
+gboolean dapi_command_capabilities (DapiCommand *obj,
+ gint *capabilities,
+ GError **error);
+gboolean dapi_command_open_url (DapiCommand *obj,
+ const gchar *url,
+ GValue *windowinfo,
+ GError **error);
+gboolean dapi_command_execute_url (DapiCommand *obj,
+ const gchar *url,
+ GValue *windowinfo,
+ GError **error);
+gboolean dapi_command_button_order (DapiCommand *obj,
+ guint *order,
+ GError **error);
+gboolean dapi_command_run_as_user (DapiCommand *obj,
+ const gchar *user,
+ const gchar *command,
+ GValue *windowinfo,
+ GError **error);
+gboolean dapi_command_suspend_screen_saving (DapiCommand *obj,
+ guint client_id,
+ gboolean suspend,
+ GError **error);
+gboolean dapi_command_mail_to (DapiCommand *obj,
+ const gchar *subject,
+ const gchar *body,
+ const gchar *to,
+ const gchar *cc,
+ const gchar *bcc,
+ const gchar **attachments,
+ GValue *windowinfo,
+ GError **error);
+void dapi_command_local_file (DapiCommand *obj,
+ const gchar *url,
+ const gchar *local,
+ gboolean allow_download,
+ GValue *windowinfo,
+ DBusGMethodInvocation *context,
+ GError **error);
+void dapi_command_upload_file (DapiCommand *obj,
+ const gchar *local,
+ const gchar *url,
+ gboolean remove_local,
+ GValue *windowinfo,
+ DBusGMethodInvocation *context,
+ GError **error);
+gboolean dapi_command_remove_temporary_local_file (DapiCommand *obj,
+ const gchar *local,
+ GError **error);
+void dapi_command_address_book_list (DapiCommand *obj,
+ DBusGMethodInvocation *context,
+ GError **error);
+gboolean dapi_command_address_book_owner (DapiCommand *obj,
+ gchar **contact_id,
+ GError **error);
+void dapi_command_address_book_find_by_name (DapiCommand *obj,
+ const gchar *name,
+ DBusGMethodInvocation *context,
+ GError **error);
+void dapi_command_address_book_get_name (DapiCommand *obj,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context,
+ GError **error);
+void dapi_command_address_book_get_emails (DapiCommand *obj,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context,
+ GError **error);
+void dapi_command_address_book_get_vcard30 (DapiCommand *obj,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context,
+ GError **error);
+G_END_DECLS
+
+#endif /* __DAPI_COMMAND_H__ */
diff --git a/src/dapi-daemon.c b/src/dapi-daemon.c
new file mode 100644
index 0000000..8d37b44
--- /dev/null
+++ b/src/dapi-daemon.c
@@ -0,0 +1,195 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Mikael Hallendal <micke@imendio.com>
+ * Author: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+
+#include "dapi-debug.h"
+#include "dapi-command.h"
+#include "dapi-command-glue.h"
+#include "dapi-gnome.h"
+
+#define DEBUG_DOMAIN "Daemon"
+
+static GMainLoop *main_loop;
+
+static void daemon_show_version (void);
+static void daemon_show_debug_information (void);
+static void daemon_quit_cb (int sig);
+
+static gboolean show_version = FALSE;
+static gboolean show_debug_information = FALSE;
+
+static const GOptionEntry options[] = {
+ { "version", 'v',
+ 0, G_OPTION_ARG_NONE, &show_version,
+ N_("Show version information"),
+ NULL },
+ { "debug", 'd',
+ 0, G_OPTION_ARG_NONE, &show_debug_information,
+ N_("Show debugging information"),
+ NULL },
+ { NULL }
+};
+
+static void
+daemon_show_version (void)
+{
+ g_print ("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+}
+
+static void
+daemon_show_debug_information (void)
+{
+ g_print ("\n"
+ "You can set the \"DAPI_DEBUG\" environment variable to a \n"
+ "colon/comma/space separated list of domains you want \n"
+ "debugging information on, or \"all\" to get all debug output.\n"
+ "\n");
+}
+
+static void
+daemon_quit_cb (int sig)
+{
+ dapi_debug (DEBUG_DOMAIN, "Caught SIGINT or SIGQUIT");
+ g_main_loop_quit (main_loop);
+}
+
+static gboolean
+daemon_register_object (DBusGConnection *connection,
+ GObject *obj)
+{
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ guint result;
+
+ dapi_debug (DEBUG_DOMAIN, "Registering DBus object...");
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ if (!org_freedesktop_DBus_request_name (proxy,
+ DAPI_SERVICE,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ &result, &error)) {
+ g_warning ("Could not aquire name:'%s', %s",
+ DAPI_SERVICE,
+ error ? error->message : "no error given");
+ g_error_free (error);
+ g_object_unref (proxy);
+
+ return FALSE;
+ }
+
+ g_object_unref (proxy);
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ g_warning ("DBus service name already taken, "
+ "are you already running this daemon?");
+ return FALSE;
+ }
+
+ dbus_g_object_type_install_info (DAPI_TYPE_COMMAND, &dbus_glib_dapi_command_object_info);
+ dbus_g_connection_register_g_object (connection, DAPI_PATH, obj);
+
+ dapi_debug (DEBUG_DOMAIN, "Registered!");
+ return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ DBusGConnection *bus;
+ DapiCommand *command;
+
+ g_type_init ();
+
+ context = g_option_context_new ("- DAPI Gnome Daemon");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ if (show_version) {
+ daemon_show_version ();
+ return EXIT_SUCCESS;
+ }
+
+ if (show_debug_information) {
+ daemon_show_debug_information ();
+ return EXIT_SUCCESS;
+ }
+
+ /* Make sure we quit nicely with Ctrl+C */
+ signal (SIGINT, daemon_quit_cb);
+ signal (SIGQUIT, daemon_quit_cb);
+
+ dapi_debug (DEBUG_DOMAIN, "Starting up...");
+
+ bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (!bus) {
+ g_warning ("Could not connect to the session bus, %s",
+ error ? error->message : "no error given.");
+ return EXIT_FAILURE;
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Creating new command object");
+ command = g_object_new (DAPI_TYPE_COMMAND, NULL);
+
+ if (!daemon_register_object (bus, G_OBJECT (command))) {
+ return EXIT_FAILURE;
+ }
+
+ if (!dapi_gnome_startup ()) {
+ return EXIT_FAILURE;
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Starting main loop");
+ dapi_debug (DEBUG_DOMAIN, "Ready!");
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ dapi_debug (DEBUG_DOMAIN, "Shutting down...");
+
+ dapi_gnome_shutdown ();
+
+ if (command) {
+ g_object_unref (command);
+ }
+
+ g_main_loop_unref (main_loop);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/dapi-debug.c b/src/dapi-debug.c
new file mode 100644
index 0000000..6ac8c24
--- /dev/null
+++ b/src/dapi-debug.c
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+
+/* Set DAPI_DEBUG to a colon/comma/space separated list of domains, or "all"
+ * to get all debug output.
+ */
+
+#include "dapi-debug.h"
+
+static gchar **debug_strv;
+static gboolean all_domains = FALSE;
+
+static void
+debug_init (void)
+{
+ static gboolean inited = FALSE;
+
+ if (!inited) {
+ const gchar *env;
+ gint i;
+
+ env = g_getenv ("DAPI_DEBUG");
+
+ if (env) {
+ debug_strv = g_strsplit_set (env, ":, ", 0);
+ } else {
+ debug_strv = NULL;
+ }
+
+ for (i = 0; debug_strv && debug_strv[i]; i++) {
+ if (strcmp ("all", debug_strv[i]) == 0) {
+ all_domains = TRUE;
+ }
+ }
+
+ inited = TRUE;
+ }
+}
+
+void
+dapi_debug_impl (const gchar *domain, const gchar *msg, ...)
+{
+ gint i;
+
+ g_return_if_fail (domain != NULL);
+ g_return_if_fail (msg != NULL);
+
+ debug_init ();
+
+ for (i = 0; debug_strv && debug_strv[i]; i++) {
+ if (all_domains || strcmp (domain, debug_strv[i]) == 0) {
+ va_list args;
+
+ g_print ("%s: ", domain);
+
+ va_start (args, msg);
+ g_vprintf (msg, args);
+ va_end (args);
+
+ g_print ("\n");
+ break;
+ }
+ }
+}
+
diff --git a/src/dapi-debug.h b/src/dapi-debug.h
new file mode 100644
index 0000000..f863e76
--- /dev/null
+++ b/src/dapi-debug.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __DAPI_DEBUG_H__
+#define __DAPI_DEBUG_H__
+
+#include <glib.h>
+
+#ifdef G_HAVE_ISO_VARARGS
+# ifdef DAPI_DISABLE_DEBUG
+# define dapi_debug(...)
+# else
+# define dapi_debug(...) dapi_debug_impl (__VA_ARGS__)
+# endif
+#elif defined(G_HAVE_GNUC_VARARGS)
+# if DAPI_DISABLE_DEBUG
+# define dapi_debug(fmt...)
+# else
+# define dapi_debug(fmt...) dapi_debug_impl(fmt)
+# endif
+#else
+# if DAPI_DISABLE_DEBUG
+# define dapi_debug(x)
+# else
+# define dapi_debug dapi_debug_impl
+# endif
+#endif
+
+void dapi_debug_impl (const gchar *domain, const gchar *msg, ...);
+
+#endif /* __DAPI_DEBUG_H__ */
+
diff --git a/src/dapi-gnome.c b/src/dapi-gnome.c
new file mode 100644
index 0000000..631cc14
--- /dev/null
+++ b/src/dapi-gnome.c
@@ -0,0 +1,1710 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <gconf/gconf-client.h>
+#include <libebook/e-book.h>
+
+#include <dapi-common.h>
+
+#include "dapi-debug.h"
+#include "dapi-gnome.h"
+
+#define DEBUG_DOMAIN "Gnome"
+
+#define DAPI_GNOME_ERROR_DOMAIN "DAPI-Gnome"
+
+#define GCONF_URL_HANDLERS_PATH "/desktop/gnome/url-handlers"
+
+#define gnome_return_val_if_not_capable(expr,val) \
+ G_STMT_START { \
+ if (dapi_gnome_has_capability(expr)) { } else { return (val); }; \
+ } G_STMT_END
+
+#define gnome_return_if_not_capable(expr) \
+ G_STMT_START { \
+ if (dapi_gnome_has_capability(expr)) { } else { return; }; \
+ } G_STMT_END
+
+typedef enum {
+ GNOME_MODULE_GNOMEVFS = 1 << 0,
+ GNOME_MODULE_GTK = 1 << 1,
+ GNOME_MODULE_EBOOK = 1 << 2,
+} GnomeModule;
+
+typedef struct {
+ gchar *filename;
+ gboolean flag;
+ GError *error;
+ gconstpointer callback;
+ gpointer user_data;
+} TransferFileData;
+
+static gchar * gnome_open_url_get_exec (const char *scheme);
+static const gchar *gnome_vfs_xfer_phase_to_str (GnomeVFSXferPhase phase);
+static void gnome_ebook_get_names_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure);
+static void gnome_ebook_get_email_addresses_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure);
+static void gnome_ebook_find_by_name_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure);
+static void gnome_ebook_loaded_cb (EBook *book,
+ EBookStatus status,
+ gpointer closure);
+
+static gint capabilities = 0;
+static GHashTable *temporary_files = NULL;
+static GHashTable *dpms_clients = NULL;
+
+GQuark
+dapi_gnome_error_quark (void)
+{
+ return g_quark_from_static_string (DAPI_GNOME_ERROR_DOMAIN);
+}
+
+gboolean
+dapi_gnome_startup (void)
+{
+ static gboolean inited = FALSE;
+ EBook *book;
+ gboolean ok;
+ gint modules = 0;
+
+ if (inited) {
+ return TRUE;
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Starting up...");
+
+ temporary_files = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ NULL);
+
+ dpms_clients = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ NULL);
+
+ /* Check GnomeVFS */
+ ok = gnome_vfs_init ();
+ dapi_debug (DEBUG_DOMAIN, "---> GnomeVFS...%s", ok ? "OK" : "Failed");
+
+ if (ok) {
+ modules |= GNOME_MODULE_GNOMEVFS;
+ }
+
+ /* Check GTK+ */
+ ok = gtk_init_check (0, NULL);
+ dapi_debug (DEBUG_DOMAIN, "---> GTK+...%s", ok ? "OK" : "Failed");
+
+ if (ok) {
+ modules |= GNOME_MODULE_GTK;
+ }
+
+ /* Check Ebook */
+ book = e_book_new_system_addressbook (NULL);
+ dapi_debug (DEBUG_DOMAIN, "---> Ebook...%s", book ? "OK" : "Failed");
+
+ if (book) {
+ modules |= GNOME_MODULE_EBOOK;
+ g_object_unref (book);
+ }
+
+ /* We set up a list of capabilities that we can use at run time */
+#ifdef HAVE_GKSU
+ capabilities |= DAPI_CAP_RUNASUSER;
+#endif
+
+#ifdef HAVE_GNOME_SCREENSAVER
+ capabilities |= DAPI_CAP_SUSPENDSCREENSAVING;
+#endif
+
+ if (modules & GNOME_MODULE_GNOMEVFS) {
+ capabilities |= DAPI_CAP_OPENURL;
+ capabilities |= DAPI_CAP_EXECUTEURL;
+ capabilities |= DAPI_CAP_MAILTO;
+ capabilities |= DAPI_CAP_LOCALFILE;
+ capabilities |= DAPI_CAP_UPLOADFILE;
+ capabilities |= DAPI_CAP_REMOVETEMPORARYLOCALFILE;
+ }
+
+ if (modules & GNOME_MODULE_GTK) {
+ capabilities |= DAPI_CAP_BUTTONORDER;
+ }
+
+ if (modules & GNOME_MODULE_EBOOK) {
+ capabilities |= DAPI_CAP_ADDRESSBOOKLIST;
+ capabilities |= DAPI_CAP_ADDRESSBOOKGETNAME;
+ capabilities |= DAPI_CAP_ADDRESSBOOKGETEMAILS;
+ capabilities |= DAPI_CAP_ADDRESSBOOKFINDBYNAME;
+ capabilities |= DAPI_CAP_ADDRESSBOOKOWNER;
+ capabilities |= DAPI_CAP_ADDRESSBOOKGETVCARD30;
+ }
+
+ inited = TRUE;
+ dapi_debug (DEBUG_DOMAIN, "Ready!");
+
+ return TRUE;
+}
+
+void
+dapi_gnome_shutdown (void)
+{
+ dapi_debug (DEBUG_DOMAIN, "Shutting down...");
+
+ gnome_vfs_shutdown ();
+ dapi_debug (DEBUG_DOMAIN, "---> GnomeVFS...OK");
+
+ g_hash_table_destroy (temporary_files);
+ g_hash_table_destroy (dpms_clients);
+}
+
+gint
+dapi_gnome_get_capabilities (void)
+{
+ return capabilities;
+}
+
+gboolean
+dapi_gnome_has_capability (DapiCapability capability)
+{
+ return capabilities & capability;
+}
+
+static gchar *
+gnome_open_url_get_exec (const char *scheme)
+{
+ GConfClient *gconf_client;
+ gchar *path;
+ gchar *exec;
+
+ gconf_client = gconf_client_get_default ();
+ if (!gconf_client) {
+ g_warning ("Could not get default gconf client");
+ return NULL;
+ }
+
+ path = g_strdup_printf ("%s/%s/command", GCONF_URL_HANDLERS_PATH, scheme);
+ exec = gconf_client_get_string (gconf_client, path, NULL);
+ g_free (path);
+
+ return exec;
+}
+
+gboolean
+dapi_gnome_open_url (const gchar *url,
+ GError **error)
+{
+ gchar *exec_format;
+ gchar *exec;
+ gboolean result = FALSE;
+
+ gnome_return_val_if_not_capable (DAPI_CAP_OPENURL, FALSE);
+
+ g_return_val_if_fail (url != NULL && strlen (url) > 0, FALSE);
+
+ dapi_debug (DEBUG_DOMAIN, "Opening URL:'%s'", url);
+
+ if (!strchr (url, ':')) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Scheme (e.g. http://) was not present in URL:'%s'"), url);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_set_error (error, DAPI_GNOME_ERROR, result, str);
+ g_free (str);
+
+ return FALSE;
+ }
+
+ exec_format = gnome_open_url_get_exec ("http");
+
+ if (strstr (exec_format, "%s")) {
+ exec = g_strdup_printf (exec_format, url);
+ } else {
+ exec = g_strdup_printf ("%s %s", exec_format, url);
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Using command:'%s'", exec);
+ result = g_spawn_command_line_async (exec, error);
+
+ if (result) {
+ dapi_debug (DEBUG_DOMAIN,
+ "Started browser successfully");
+ result = TRUE;
+ } else {
+ dapi_debug (DEBUG_DOMAIN,
+ "Could not start browser process, error:'%s'",
+ error && *error ? (*error)->message : "");
+ }
+
+ g_free (exec);
+ g_free (exec_format);
+
+ return result;
+}
+
+gboolean
+dapi_gnome_execute_url (const gchar *url,
+ GError **error)
+{
+ GnomeVFSResult result;
+
+ gnome_return_val_if_not_capable (DAPI_CAP_EXECUTEURL, FALSE);
+
+ g_return_val_if_fail (url != NULL && strlen (url) > 0, FALSE);
+
+ result = gnome_vfs_url_show (url);
+
+ if (result == GNOME_VFS_OK) {
+ dapi_debug (DEBUG_DOMAIN,
+ "Executed URL:'%s' successfully",
+ url);
+ } else {
+ const gchar *str;
+
+ str = gnome_vfs_result_to_string (result);
+ g_set_error (error, DAPI_GNOME_ERROR, result, str);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Could not executed URL:'%s', error:'%s'",
+ url,
+ error && *error ? (*error)->message : "");
+ }
+
+ return result == GNOME_VFS_OK;
+}
+
+gboolean
+dapi_gnome_button_order (gboolean *alternative_button_order,
+ GError **error)
+{
+ GtkSettings *settings;
+
+ gnome_return_val_if_not_capable (DAPI_CAP_BUTTONORDER, FALSE);
+
+ g_return_val_if_fail (alternative_button_order != NULL, FALSE);
+
+ /* Default */
+ *alternative_button_order = FALSE;
+
+ /* This gets the default settings for the default screen */
+ settings = gtk_settings_get_default ();
+ if (!settings) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not get GTK+ default settings"));
+
+ g_set_error (error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ return FALSE;
+ }
+
+ g_object_get (settings,
+ "gtk-alternative-button-order", alternative_button_order,
+ NULL);
+
+ dapi_debug (DEBUG_DOMAIN, "Getting button order...%s",
+ *alternative_button_order ? "Alternative (OK/Cancel)" : "Normal (Cancel/OK)");
+
+ return TRUE;
+}
+
+gboolean
+dapi_gnome_run_as_user (const gchar *user,
+ const gchar *command,
+ GError **error)
+{
+#ifdef HAVE_GKSU
+ gchar *exec;
+ gboolean result;
+
+ gnome_return_val_if_not_capable (DAPI_CAP_RUNASUSER, FALSE);
+
+ g_return_val_if_fail (user != NULL && strlen (user) > 0, FALSE);
+ g_return_val_if_fail (command != NULL && strlen (command) > 0, FALSE);
+
+ /* We can't check if the file exists or is executable here
+ * because if we do then it will be relative to this user not
+ * the user trying to run the command.
+ */
+ exec = g_strdup_printf ("%s -u %s %s", HAVE_GKSU, user, command);
+ result = g_spawn_command_line_async (exec, error);
+ g_free (exec);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Running gksu for command:'%s' as user:'%s'...%s->'%s'",
+ command, user,
+ result ? "OK" : "Failed",
+ error && *error ? (*error)->message : "No Errors");
+
+ g_clear_error (error);
+
+ /* gksu SHOULD return 0 or 1 based on success of failure but
+ * it seems to always return 0 regardless. So we are always
+ * successfull here as a result even if the filename we want
+ * to execute can not be found.
+ */
+
+ return result;
+#else
+ gnome_return_val_if_not_capable (DAPI_CAP_RUNASUSER, FALSE);
+#endif
+}
+
+static gboolean
+gnome_suspend_screen_saving_timeout_cb (gpointer data)
+{
+ GError *error = NULL;
+ gboolean result;
+ gchar *exec;
+
+ exec = g_strdup_printf ("%s --poke", HAVE_GNOME_SCREENSAVER);
+ result = g_spawn_command_line_async (exec, &error);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Running '%s':... %s->'%s'",
+ exec,
+ result ? "OK" : "Failed",
+ error ? error->message : "No Errors");
+
+ g_clear_error (&error);
+ g_free (exec);
+
+ return TRUE;
+}
+
+gboolean
+dapi_gnome_suspend_screen_saving (guint client_id,
+ gboolean suspend,
+ GError **error)
+{
+#ifdef HAVE_GNOME_SCREENSAVER
+ static guint timeout_id = 0;
+
+ if (suspend) {
+ gpointer p;
+
+ p = g_hash_table_lookup (dpms_clients,
+ GUINT_TO_POINTER (client_id));
+ if (p) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Client %d has already requested to "
+ "suspend screen saving"),
+ client_id);
+
+ g_set_error (error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ return FALSE;
+ }
+
+ g_hash_table_insert (dpms_clients,
+ GUINT_TO_POINTER (client_id),
+ GUINT_TO_POINTER (1));
+
+ if (timeout_id == 0) {
+ /* Start timeouts */
+ timeout_id = g_timeout_add (30000,
+ gnome_suspend_screen_saving_timeout_cb,
+ NULL);
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Started to ping the screensaver");
+ } else {
+ gboolean removed;
+
+ removed = g_hash_table_remove (dpms_clients,
+ GUINT_TO_POINTER (client_id));
+ if (!removed) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Client %d had not requested to "
+ "resume screen saving"),
+ client_id);
+ g_set_error (error, DAPI_GNOME_ERROR, 2, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ return FALSE;
+ }
+
+ if (g_hash_table_size (dpms_clients) < 1) {
+ /* Stop pinging the screensaver */
+ if (timeout_id != 0) {
+ g_source_remove (timeout_id);
+ timeout_id = 0;
+
+ dapi_debug (DEBUG_DOMAIN, "Stopped to ping the screensaver");
+ }
+ }
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Suspending screen saving: %s for client "
+ "with id:%d... (%d clients left)",
+ suspend ? "enable" : "disable",
+ client_id,
+ g_hash_table_size (dpms_clients));
+
+ return TRUE;
+#else
+ gnome_return_val_if_not_capable (DAPI_CAP_SUSPENDSCREENSAVING, FALSE);
+#endif
+}
+
+gboolean
+dapi_gnome_mail_to (const gchar *to,
+ const gchar *cc,
+ const gchar *bcc,
+ const gchar *subject,
+ const gchar *body,
+ const gchar **attachments,
+ GError **error)
+{
+ GnomeVFSResult result;
+ GString *url;
+ gint i;
+
+ gnome_return_val_if_not_capable (DAPI_CAP_MAILTO, FALSE);
+
+ url = g_string_new ("mailto:?");
+
+ dapi_debug (DEBUG_DOMAIN, "Sending mail with details:");
+
+ if (to && strlen (to) > 0) {
+ g_string_append_printf (url, "to=%s", to);
+ dapi_debug (DEBUG_DOMAIN, "\t\tcc:'%s'", to);
+ }
+
+ if (cc && strlen (cc) > 0) {
+ g_string_append_printf (url, "&cc=%s", cc);
+ dapi_debug (DEBUG_DOMAIN, "\t\tcc:'%s'", cc);
+ }
+
+ if (bcc && strlen (bcc) > 0) {
+ g_string_append_printf (url, "&bcc=%s", bcc);
+ dapi_debug (DEBUG_DOMAIN, "\t\tbcc:'%s'", bcc);
+ }
+
+ if (subject && strlen (subject) > 0) {
+ g_string_append_printf (url, "&subject=%s", subject);
+ dapi_debug (DEBUG_DOMAIN, "\t\tsubject:'%s'", subject);
+ }
+
+ if (body && strlen (body) > 0) {
+ g_string_append_printf (url, "&body=%s", body);
+ dapi_debug (DEBUG_DOMAIN, "\t\tbody:'%s'", body);
+ }
+
+ if (attachments) {
+ for (i = 0; attachments[i]; i++) {
+ g_string_append_printf (url, "&attach=%s", attachments[i]);
+ dapi_debug (DEBUG_DOMAIN, "\t\tattachment %2.2d:'%s'", i, attachments[i]);
+ }
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Sending mail using url:'%s'", url->str);
+
+ result = gnome_vfs_url_show (url->str);
+ if (result == GNOME_VFS_OK) {
+ dapi_debug (DEBUG_DOMAIN,
+ "Executed URL:'%s' successfully",
+ url->str);
+ } else {
+ const gchar *str;
+
+ str = gnome_vfs_result_to_string (result);
+ g_set_error (error, DAPI_GNOME_ERROR, result, str);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Could not execute URL:'%s', error:'%s'",
+ url->str,
+ error && *error ? (*error)->message : "");
+ }
+
+ g_string_free (url, TRUE);
+
+ return result == GNOME_VFS_OK;
+}
+
+static const gchar *
+gnome_vfs_xfer_phase_to_str (GnomeVFSXferPhase phase)
+{
+ switch (phase) {
+ case GNOME_VFS_XFER_PHASE_INITIAL:
+ /* Initial phase */
+ return "Initial";
+ case GNOME_VFS_XFER_CHECKING_DESTINATION:
+ /* Checking if destination can handle move/copy */
+ return "Checking Destination";
+ case GNOME_VFS_XFER_PHASE_COLLECTING:
+ /* Collecting file list */
+ return "Collecting";
+ case GNOME_VFS_XFER_PHASE_READYTOGO:
+ /* File list collected (*) */
+ return "Ready To Go";
+ case GNOME_VFS_XFER_PHASE_OPENSOURCE:
+ /* Opening source file for reading */
+ return "Open Source";
+ case GNOME_VFS_XFER_PHASE_OPENTARGET:
+ /* Creating target file for copy */
+ return "Open target";
+ case GNOME_VFS_XFER_PHASE_COPYING:
+ /* Copying data from source to target (*) */
+ return "Copying";
+ case GNOME_VFS_XFER_PHASE_MOVING:
+ /* Moving file from source to target (*) */
+ return "Moving";
+ case GNOME_VFS_XFER_PHASE_READSOURCE:
+ /* Reading data from source file */
+ return "Read Source";
+ case GNOME_VFS_XFER_PHASE_WRITETARGET:
+ /* Writing data to target file */
+ return "Write Target";
+ case GNOME_VFS_XFER_PHASE_CLOSESOURCE:
+ /* Closing source file */
+ return "Close Source";
+ case GNOME_VFS_XFER_PHASE_CLOSETARGET:
+ /* Closing target file */
+ return "Close Target";
+ case GNOME_VFS_XFER_PHASE_DELETESOURCE:
+ /* Deleting source file */
+ return "Delete Source";
+ case GNOME_VFS_XFER_PHASE_SETATTRIBUTES:
+ /* Setting attributes on target file */
+ return "Set Attributes";
+ case GNOME_VFS_XFER_PHASE_FILECOMPLETED:
+ /* Go to the next file (*) */
+ return "File Completed";
+ case GNOME_VFS_XFER_PHASE_CLEANUP:
+ /* cleaning up after a move (removing source files, etc.) */
+ return "Clean Up";
+ case GNOME_VFS_XFER_PHASE_COMPLETED:
+ /* Operation finished (*) */
+ return "Completed";
+
+ default:
+ break;
+ }
+
+ return "Unknown";
+}
+
+static gint
+gnome_local_file_transfer_cb (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *info,
+ TransferFileData *data)
+{
+ const gchar *str;
+
+ switch (info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ str = "OK";
+ break;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ str = gnome_vfs_result_to_string (info->vfs_status);
+ break;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+ str = "Overwrite";
+ break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Transfer progress update, status:%d->'%s' phase:%d->'%s'...",
+ info->status, str, info->phase, gnome_vfs_xfer_phase_to_str (info->phase));
+
+ if (info->status == GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR &&
+ info->vfs_status != GNOME_VFS_OK) {
+ if (!data->error) {
+ g_set_error (&data->error, DAPI_GNOME_ERROR,
+ info->vfs_status, str);
+ }
+
+ return 0;
+ }
+
+ if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+ DapiGnomeLocalFileCallback func;
+
+ func = data->callback;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Transfer %s to destination:'%s'",
+ data->error ? "failed" : "success",
+ data->filename);
+
+ (func) (data->filename, data->error, data->user_data);
+
+ if (data->flag) {
+ /* Don't free data->filename here because we need to remember
+ * it in our hash table so that the remove local file
+ * function can check we have actually created it. We must
+ * ONLY remove local files we created according to the spec.
+ */
+ g_hash_table_insert (temporary_files,
+ data->filename,
+ GINT_TO_POINTER (1));
+ } else {
+ g_free (data->filename);
+ }
+
+ g_clear_error (&data->error);
+ g_free (data);
+ }
+
+ return 1;
+}
+
+void
+dapi_gnome_local_file (const gchar *url,
+ const gchar *local,
+ gboolean allow_download,
+ DapiGnomeLocalFileCallback callback,
+ gpointer user_data)
+{
+ GnomeVFSURI *source;
+ GnomeVFSURI *target = NULL;
+ GnomeVFSAsyncHandle *handle;
+ GnomeVFSResult result;
+ GList *source_uri_list;
+ GList *target_uri_list;
+ gboolean is_temporary = FALSE;
+ GError *error = NULL;
+ gchar *str;
+ TransferFileData *data;
+
+ gnome_return_if_not_capable (DAPI_CAP_LOCALFILE);
+ g_return_if_fail (url != NULL && strlen (url) > 0);
+ g_return_if_fail (local != NULL && strlen (local) > 0);
+ g_return_if_fail (callback != NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Copying remote url:'%s' to local url:'%s' (allow download: %s)",
+ url, local, allow_download ? "yes" : "no");
+
+ source = gnome_vfs_uri_new (url);
+
+ /* If the URL is local already, we just return that */
+ if (gnome_vfs_uri_is_local (source)) {
+ str = g_strdup_printf (_("The remote URL:'%s' is already local"), url);
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ /* Not sure if we should add this to the hash table so
+ * we can remove it later with remove local file
+ */
+ (callback)(url, error, user_data);
+
+ g_clear_error (&error);
+ gnome_vfs_uri_unref (source);
+
+ return;
+ }
+
+ /* If the URL is remote and we can't download it, we just
+ * return
+ */
+ if (!allow_download) {
+ str = g_strdup_printf (_("The remote URL:'%s' needs downloading "
+ "and you have not allowed downloading"),
+ url);
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(url, error, user_data);
+
+ g_clear_error (&error);
+ gnome_vfs_uri_unref (source);
+
+ return;
+ }
+
+ /* If the target URI already exists, we generate another
+ * temporary file name and use that instead
+ */
+ if (local) {
+ target = gnome_vfs_uri_new (local);
+
+ if (gnome_vfs_uri_exists (target)) {
+ gnome_vfs_uri_unref (target);
+ target = NULL;
+ }
+ }
+
+ if (!target) {
+ gchar *tmp_filename;
+ gint fd;
+
+ fd = g_file_open_tmp ("dapi-gnome-XXXXXX", &tmp_filename, NULL);
+ if (fd == -1) {
+ str = g_strdup (_("Could not create temporary filename."));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(url, error, user_data);
+
+ g_clear_error (&error);
+ gnome_vfs_uri_unref (source);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Specified local URL already exists or wasn't given, creating "
+ "new temporary URL:'%s'...",
+ tmp_filename);
+
+ target = gnome_vfs_uri_new (tmp_filename);
+ g_free (tmp_filename);
+
+ close (fd);
+
+ is_temporary = TRUE;
+ }
+
+ data = g_new0 (TransferFileData, 1);
+
+ data->filename = gnome_vfs_uri_to_string (target,
+ GNOME_VFS_URI_HIDE_NONE);
+
+ data->flag = is_temporary;
+
+ data->callback = callback;
+ data->user_data = user_data;
+
+ source_uri_list = g_list_append (NULL, source);
+ target_uri_list = g_list_append (NULL, target);
+
+ result = gnome_vfs_async_xfer (&handle,
+ source_uri_list,
+ target_uri_list,
+ GNOME_VFS_XFER_RECURSIVE,
+ GNOME_VFS_XFER_ERROR_MODE_QUERY,
+ GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ (GnomeVFSAsyncXferProgressCallback)
+ gnome_local_file_transfer_cb,
+ data,
+ NULL, NULL);
+
+ g_list_foreach (source_uri_list, (GFunc) gnome_vfs_uri_unref, NULL);
+ g_list_foreach (target_uri_list, (GFunc) gnome_vfs_uri_unref, NULL);
+
+ g_list_free (source_uri_list);
+ g_list_free (target_uri_list);
+
+ if (result != GNOME_VFS_OK) {
+ str = g_strdup (_("File transfer failed locally for an unknown reason."));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(url, error, user_data);
+
+ g_clear_error (&error);
+
+ g_free (data->filename);
+ g_free (data);
+
+ return;
+ }
+}
+
+static gint
+gnome_upload_file_transfer_cb (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *info,
+ TransferFileData *data)
+{
+ const gchar *str;
+
+ switch (info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ str = "OK";
+ break;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ str = gnome_vfs_result_to_string (info->vfs_status);
+ break;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+ str = "Overwrite";
+ break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Transfer progress update, status:%d->'%s' phase:%d->'%s'...",
+ info->status, str, info->phase, gnome_vfs_xfer_phase_to_str (info->phase));
+
+ if (info->status == GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR &&
+ info->vfs_status != GNOME_VFS_OK) {
+ if (!data->error) {
+ g_set_error (&data->error, DAPI_GNOME_ERROR,
+ info->vfs_status, str);
+ }
+
+ return 0;
+ }
+
+ if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+ DapiGnomeUploadFileCallback func;
+
+ func = data->callback;
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Transfer %s to destination:'%s'",
+ data->error ? "failed" : "complete",
+ data->filename);
+
+ (func) (data->error, data->user_data);
+
+ if (data->flag) {
+ dapi_gnome_remove_temp_local_file (data->filename);
+ }
+
+ g_clear_error (&data->error);
+
+ g_free (data->filename);
+ g_free (data);
+ }
+
+ return 1;
+}
+
+void
+dapi_gnome_upload_file (const gchar *local,
+ const gchar *url,
+ gboolean remove_local,
+ DapiGnomeUploadFileCallback callback,
+ gpointer user_data)
+{
+ GnomeVFSURI *source;
+ GnomeVFSURI *target;
+ GnomeVFSAsyncHandle *handle;
+ GnomeVFSResult result;
+ GList *source_uri_list;
+ GList *target_uri_list;
+ GError *error = NULL;
+ gchar *str;
+ TransferFileData *data;
+
+ gnome_return_if_not_capable (DAPI_CAP_UPLOADFILE);
+ g_return_if_fail (url != NULL && strlen (url) > 0);
+ g_return_if_fail (local != NULL && strlen (local) > 0);
+ g_return_if_fail (callback != NULL);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Copying remote url:'%s' to local url:'%s' (remove local: %s)",
+ url, local, remove_local ? "yes" : "no");
+
+ target = gnome_vfs_uri_new (url);
+
+ /* If the URL is local already, we just return that */
+ if (gnome_vfs_uri_is_local (target)) {
+ str = g_strdup_printf (_("The remote URL:'%s' is already local"), url);
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ /* Not sure if we should add this to the hash table so
+ * we can remove it later with remove local file
+ */
+ (callback)(error, user_data);
+
+ g_clear_error (&error);
+ gnome_vfs_uri_unref (target);
+
+ return;
+ }
+
+ source = gnome_vfs_uri_new (local);
+
+ if (!gnome_vfs_uri_exists (source)) {
+ str = g_strdup_printf (_("The local URL:'%s' does not exist"), local);
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(error, user_data);
+
+ g_clear_error (&error);
+
+ gnome_vfs_uri_unref (target);
+ gnome_vfs_uri_unref (source);
+
+ return;
+ }
+
+ data = g_new0 (TransferFileData, 1);
+
+ data->filename = gnome_vfs_uri_to_string (source,
+ GNOME_VFS_URI_HIDE_NONE);
+
+ data->flag = remove_local;
+
+ data->callback = callback;
+ data->user_data = user_data;
+
+ source_uri_list = g_list_append (NULL, source);
+ target_uri_list = g_list_append (NULL, target);
+
+ result = gnome_vfs_async_xfer (&handle,
+ source_uri_list,
+ target_uri_list,
+ GNOME_VFS_XFER_RECURSIVE,
+ GNOME_VFS_XFER_ERROR_MODE_QUERY,
+ GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ (GnomeVFSAsyncXferProgressCallback)
+ gnome_upload_file_transfer_cb,
+ data,
+ NULL, NULL);
+
+ g_list_foreach (source_uri_list, (GFunc) gnome_vfs_uri_unref, NULL);
+ g_list_foreach (target_uri_list, (GFunc) gnome_vfs_uri_unref, NULL);
+
+ g_list_free (source_uri_list);
+ g_list_free (target_uri_list);
+
+ if (result != GNOME_VFS_OK) {
+ str = g_strdup (_("File transfer failed locally for an unknown reason."));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(error, user_data);
+
+ g_clear_error (&error);
+
+ g_free (data->filename);
+ g_free (data);
+
+ return;
+ }
+}
+
+gboolean
+dapi_gnome_remove_temp_local_file (const gchar *filename)
+{
+ gnome_return_val_if_not_capable (DAPI_CAP_REMOVETEMPORARYLOCALFILE, FALSE);
+
+ g_return_val_if_fail (filename != NULL && strlen (filename) > 0, FALSE);
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Removing temporary local file:'%s'",
+ filename);
+
+ if (!g_hash_table_lookup (temporary_files, filename)) {
+ dapi_debug (DEBUG_DOMAIN,
+ "Filename:'%s' was not created by this daemon or has "
+ "already been removed, doing nothing.",
+ filename);
+ return FALSE;
+ }
+
+ g_hash_table_remove (temporary_files, filename);
+
+ return gnome_vfs_unlink (filename) == GNOME_VFS_OK;
+}
+
+/* FIXME: For some reason the e_book_async_get_contact() fails to work
+ * properly so we get all contacts and go through them instead. This
+ * is detailed in bug #349069.
+ */
+#undef USE_DIRECT_EBOOK_API
+#ifdef USE_DIRECT_EBOOK_API
+
+static void
+gnome_ebook_get_names_cb (EBook *book,
+ EBookStatus status,
+ EContact *contact,
+ gpointer closure)
+{
+ const gchar *id;
+ DapiGnomeNamesCallback callback;
+ gpointer user_data;
+
+ const gchar *given_name = NULL;
+ const gchar *family_name = NULL;
+ const gchar *full_name = NULL;
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not get names for contact:'%s', error %d"),
+ id, status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (id, NULL, NULL, NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Getting address book names (given, family, full) "
+ "for user ID:'%s'...",
+ id);
+
+ given_name = e_contact_get_const (contact, E_CONTACT_GIVEN_NAME);
+ family_name = e_contact_get_const (contact, E_CONTACT_FAMILY_NAME);
+ full_name = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
+
+ (callback) (id, given_name, family_name, full_name, user_data);
+
+ g_object_unref (book);
+}
+
+static void
+gnome_ebook_get_email_addresses_cb (EBook *book,
+ EBookStatus status,
+ EContact *contact,
+ gpointer closure)
+{
+ const gchar *id;
+ DapiGnomeEmailsCallback callback;
+ gpointer user_data;
+
+ GError *error = NULL;
+ GList *addresses = NULL;
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not get all email addresses "
+ "for contact:'%s', error %d"),
+ id, status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (id, NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Getting address book email addresses for user ID:'%s'...",
+ id);
+
+ addresses = e_contact_get (contact, E_CONTACT_EMAIL);
+
+ (callback) (id, addresses, NULL, user_data);
+
+ g_list_foreach (addresses, (GFunc) g_free, NULL);
+ g_list_free (addresses);
+
+ g_object_unref (book);
+}
+
+#else /* USE_DIRECT_EBOOK_API */
+
+static void
+gnome_ebook_get_list_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure)
+{
+ DapiGnomeListCallback callback;
+ gpointer user_data;
+
+ GError *error = NULL;
+ GList *ids = NULL;
+ GList *l;
+
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not get all contacts, error %d"),
+ status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Getting address book user IDs...");
+
+ for (l = contacts; l; l = l->next) {
+ gconstpointer p;
+
+ p = e_contact_get_const (E_CONTACT (l->data), E_CONTACT_UID);
+ ids = g_list_prepend (ids, (gpointer) p);
+ }
+
+ dapi_debug (DEBUG_DOMAIN, "Found %d user IDs", g_list_length (ids));
+
+ (callback)(ids, NULL, user_data);
+
+ g_list_free (ids);
+ g_object_unref (book);
+}
+
+static void
+gnome_ebook_get_names_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure)
+{
+ const gchar *id;
+ DapiGnomeNameCallback callback;
+ gpointer user_data;
+ GList *l;
+
+ GError *error = NULL;
+ const gchar *given_name = NULL;
+ const gchar *family_name = NULL;
+ const gchar *full_name = NULL;
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not get names for contact:'%s', error %d"),
+ id, status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (id, NULL, NULL, NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Getting address book names for user ID:'%s'...",
+ id);
+
+ for (l = contacts; l; l = l->next) {
+ EContact *contact;
+ const gchar *this_id;
+
+ contact = E_CONTACT (l->data);
+ this_id = e_contact_get_const (contact, E_CONTACT_UID);
+
+ if (this_id && strcmp (this_id, id) == 0) {
+ given_name = e_contact_get_const (contact, E_CONTACT_GIVEN_NAME);
+ family_name = e_contact_get_const (contact, E_CONTACT_FAMILY_NAME);
+ full_name = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
+ break;
+ }
+ }
+
+ if (given_name || family_name || full_name) {
+ dapi_debug (DEBUG_DOMAIN,
+ "Found given name:'%s', family name:'%s', "
+ "full name:'%s' for user ID:'%s'",
+ given_name ? given_name : "",
+ family_name ? family_name : "",
+ full_name ? full_name : "",
+ id);
+ } else {
+ dapi_debug (DEBUG_DOMAIN,
+ "Found no names related to the user ID:'%s'",
+ id);
+ }
+
+ (callback) (id, given_name, family_name, full_name, NULL, user_data);
+
+ g_object_unref (book);
+}
+
+static void
+gnome_ebook_get_email_addresses_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure)
+{
+ const gchar *id;
+ DapiGnomeEmailsCallback callback;
+ gpointer user_data;
+
+ GError *error = NULL;
+ GList *addresses = NULL;
+ GList *l;
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not email addresses contact:'%s', error %d"),
+ id, status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (id, NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Getting address book email addresses for user ID:'%s'...",
+ id);
+
+ for (l = contacts; l; l = l->next) {
+ EContact *contact;
+ const gchar *this_id;
+
+ contact = E_CONTACT (l->data);
+ this_id = e_contact_get_const (contact, E_CONTACT_UID);
+
+ if (this_id && strcmp (this_id, id) == 0) {
+ addresses = e_contact_get (contact, E_CONTACT_EMAIL);
+ break;
+ }
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Found %d email addresses for user ID:'%s'",
+ g_list_length (addresses), id);
+
+ (callback) (id, addresses, NULL, user_data);
+
+ g_list_foreach (addresses, (GFunc) g_free, NULL);
+ g_list_free (addresses);
+
+ g_object_unref (book);
+}
+
+static void
+gnome_ebook_get_vcard_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure)
+{
+ const gchar *id;
+ DapiGnomeVCardCallback callback;
+ gpointer user_data;
+
+ GError *error = NULL;
+ GList *l;
+ gchar *vcard = NULL;
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not get vcard for contact:'%s', error %d"),
+ id, status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (id, NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Getting address book vcard for user ID:'%s'...",
+ id);
+
+ for (l = contacts; l; l = l->next) {
+ EContact *contact;
+ const gchar *this_id;
+
+ contact = E_CONTACT (l->data);
+ this_id = e_contact_get_const (contact, E_CONTACT_UID);
+
+ if (this_id && strcmp (this_id, id) == 0) {
+ vcard = e_vcard_to_string (E_VCARD (contact),
+ EVC_FORMAT_VCARD_30);
+ break;
+ }
+ }
+
+ /* Should we use the GError if the vcard is empty? */
+ dapi_debug (DEBUG_DOMAIN,
+ "%s vcard for user ID:'%s'",
+ vcard ? "Found" : "Could not find", id);
+
+ (callback) (id, vcard, NULL, user_data);
+
+ g_free (vcard);
+
+ g_object_unref (book);
+}
+
+#endif /* USE_DIRECT_EBOOK_API */
+
+static void
+gnome_ebook_find_by_name_cb (EBook *book,
+ EBookStatus status,
+ GList *contacts,
+ gpointer closure)
+{
+ const gchar *name;
+ DapiGnomeFindCallback callback;
+ gpointer user_data;
+
+ GError *error = NULL;
+ GList *ids = NULL;
+ GList *l;
+
+ name = g_object_get_data (G_OBJECT (book), "name");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ if (status != E_BOOK_ERROR_OK) {
+ gchar *str;
+
+ str = g_strdup_printf (_("Could not find contact by name:'%s', error %d"),
+ name, status);
+ g_set_error (&error, DAPI_GNOME_ERROR, status, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback) (name, NULL, error, user_data);
+
+ g_clear_error (&error);
+ g_object_unref (book);
+
+ return;
+ }
+
+ dapi_debug (DEBUG_DOMAIN,
+ "Finding address book user IDs by name:'%s'...",
+ name);
+
+ for (l = contacts; l; l = l->next) {
+ EContact *contact;
+ const gchar *this_name;
+
+ contact = E_CONTACT (l->data);
+ this_name = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
+
+ if (this_name && strcmp (this_name, name) == 0) {
+ dapi_debug (DEBUG_DOMAIN, "\t\t'%s'...YES", this_name);
+ ids = g_list_prepend
+ (ids, (gpointer) e_contact_get_const (contact, E_CONTACT_UID));
+ break;
+ } else {
+ dapi_debug (DEBUG_DOMAIN, "\t\t'%s'...NO", this_name);
+ }
+ }
+
+ (callback) (name, ids, NULL, user_data);
+
+ g_list_free (ids);
+
+ g_object_unref (book);
+}
+
+static void
+gnome_ebook_loaded_cb (EBook *book,
+ EBookStatus status,
+ gpointer closure)
+{
+ EBookQuery *query;
+ EBookListCallback func;
+
+ func = g_object_get_data (G_OBJECT (book), "func");
+
+ if (status != E_BOOK_ERROR_OK) {
+ g_warning ("Could not load book, status is %d", status);
+ return;
+ }
+
+ query = e_book_query_field_exists (E_CONTACT_FULL_NAME);
+ e_book_async_get_contacts (book, query,
+ (EBookListCallback) func,
+ NULL);
+ e_book_query_unref (query);
+}
+
+void
+dapi_gnome_address_book_get_list (DapiGnomeListCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+ GError *error = NULL;
+
+ gnome_return_if_not_capable (DAPI_CAP_ADDRESSBOOKLIST);
+ g_return_if_fail (callback != NULL);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ gchar *str;
+
+ str = g_strdup (_("Could not get system address book"));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(NULL, error, user_data);
+
+ g_clear_error (&error);
+
+ return;
+ }
+
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book), "func", gnome_ebook_get_list_cb);
+
+ e_book_async_open (book, FALSE,
+ (EBookCallback) gnome_ebook_loaded_cb, NULL);
+}
+
+void
+dapi_gnome_address_book_get_name (const gchar *id,
+ DapiGnomeNameCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+ GError *error = NULL;
+
+ gnome_return_if_not_capable (DAPI_CAP_ADDRESSBOOKGETNAME);
+ g_return_if_fail (id != NULL && strlen (id) > 0);
+ g_return_if_fail (callback != NULL);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ gchar *str;
+
+ str = g_strdup (_("Could not get system address book"));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(id, NULL, NULL, NULL, error, user_data);
+
+ g_clear_error (&error);
+
+ return;
+ }
+
+ g_object_set_data_full (G_OBJECT (book), "id", g_strdup (id), g_free);
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book), "func", gnome_ebook_get_names_cb);
+
+ e_book_async_open (book, FALSE,
+ (EBookCallback) gnome_ebook_loaded_cb, NULL);
+}
+
+void
+dapi_gnome_address_book_get_emails (const gchar *id,
+ DapiGnomeEmailsCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+ GError *error = NULL;
+
+ gnome_return_if_not_capable (DAPI_CAP_ADDRESSBOOKGETEMAILS);
+ g_return_if_fail (id != NULL && strlen (id) > 0);
+ g_return_if_fail (callback != NULL);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ gchar *str;
+
+ str = g_strdup (_("Could not get system address book"));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(id, NULL, error, user_data);
+
+ g_clear_error (&error);
+
+ return;
+ }
+
+ g_object_set_data_full (G_OBJECT (book), "id", g_strdup (id), g_free);
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book), "func", gnome_ebook_get_email_addresses_cb);
+
+ e_book_async_open (book, FALSE,
+ (EBookCallback) gnome_ebook_loaded_cb, NULL);
+}
+
+void
+dapi_gnome_address_book_find_by_name (const gchar *name,
+ DapiGnomeFindCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+ GError *error = NULL;
+
+ gnome_return_if_not_capable (DAPI_CAP_ADDRESSBOOKFINDBYNAME);
+ g_return_if_fail (name != NULL && strlen (name) > 0);
+ g_return_if_fail (callback != NULL);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ gchar *str;
+
+ str = g_strdup (_("Could not get system address book"));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(name, NULL, error, user_data);
+
+ g_clear_error (&error);
+
+ return;
+ }
+
+ g_object_set_data_full (G_OBJECT (book), "name", g_strdup (name), g_free);
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book),
+ "func", gnome_ebook_find_by_name_cb);
+
+ e_book_async_open (book, FALSE,
+ (EBookCallback) gnome_ebook_loaded_cb, NULL);
+}
+
+gboolean
+dapi_gnome_address_book_get_owner (gchar **id,
+ GError **error)
+{
+ EBook *book;
+ EContact *contact;
+
+ gnome_return_val_if_not_capable (DAPI_CAP_ADDRESSBOOKOWNER, FALSE);
+
+ g_return_val_if_fail (id != NULL, FALSE);
+
+ if (!e_book_get_self (&contact, &book, error)) {
+ dapi_debug (DEBUG_DOMAIN, "Could not get own contact id, %s",
+ error && *error ? (*error)->message : "No Errors");
+ return FALSE;
+ }
+
+ *id = e_contact_get (contact, E_CONTACT_UID);
+
+ g_object_unref (contact);
+ g_object_unref (book);
+
+ return TRUE;
+}
+
+void
+dapi_gnome_address_book_get_vcard (const gchar *id,
+ DapiGnomeVCardCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+ GError *error = NULL;
+
+ gnome_return_if_not_capable (DAPI_CAP_ADDRESSBOOKGETVCARD30);
+ g_return_if_fail (id != NULL && strlen (id) > 0);
+ g_return_if_fail (callback != NULL);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ gchar *str;
+
+ str = g_strdup (_("Could not get system address book"));
+ g_set_error (&error, DAPI_GNOME_ERROR, 1, str);
+ dapi_debug (DEBUG_DOMAIN, str);
+ g_free (str);
+
+ (callback)(id, NULL, error, user_data);
+
+ g_clear_error (&error);
+
+ return;
+ }
+
+ g_object_set_data_full (G_OBJECT (book), "id", g_strdup (id), g_free);
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book),
+ "func", gnome_ebook_get_vcard_cb);
+
+ e_book_async_open (book, FALSE,
+ (EBookCallback) gnome_ebook_loaded_cb, NULL);
+}
+
diff --git a/src/dapi-gnome.h b/src/dapi-gnome.h
new file mode 100644
index 0000000..4292bda
--- /dev/null
+++ b/src/dapi-gnome.h
@@ -0,0 +1,114 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __DAPI_GNOME_H__
+#define __DAPI_GNOME_H__
+
+#include <glib.h>
+
+#include <dapi-common.h>
+
+#define DAPI_GNOME_ERROR dapi_gnome_error_quark()
+
+GQuark dapi_gnome_error_quark (void);
+gboolean dapi_gnome_startup (void);
+void dapi_gnome_shutdown (void);
+gboolean dapi_gnome_has_capability (DapiCapability capability);
+gint dapi_gnome_get_capabilities (void);
+gboolean dapi_gnome_open_url (const gchar *url,
+ GError **error);
+gboolean dapi_gnome_execute_url (const gchar *url,
+ GError **error);
+gboolean dapi_gnome_button_order (gboolean *alternative_button_order,
+ GError **error);
+gboolean dapi_gnome_run_as_user (const gchar *user,
+ const gchar *command,
+ GError **error);
+gboolean dapi_gnome_suspend_screen_saving (guint client_id,
+ gboolean suspend,
+ GError **error);
+gboolean dapi_gnome_mail_to (const gchar *to,
+ const gchar *cc,
+ const gchar *bcc,
+ const gchar *subject,
+ const gchar *body,
+ const gchar **attachments,
+ GError **error);
+
+/* Async calls */
+typedef void (*DapiGnomeLocalFileCallback) (const gchar *filename,
+ GError *error,
+ gpointer user_data);
+typedef void (*DapiGnomeUploadFileCallback) (GError *error,
+ gpointer user_data);
+typedef void (*DapiGnomeListCallback) (GList *ids,
+ GError *error,
+ gpointer user_data);
+typedef void (*DapiGnomeNameCallback) (const gchar *id,
+ const gchar *given_name,
+ const gchar *family_name,
+ const gchar *full_name,
+ GError *error,
+ gpointer user_data);
+typedef void (*DapiGnomeEmailsCallback) (const gchar *id,
+ GList *addresses,
+ GError *error,
+ gpointer user_data);
+typedef void (*DapiGnomeFindCallback) (const gchar *name,
+ GList *ids,
+ GError *error,
+ gpointer user_data);
+typedef void (*DapiGnomeVCardCallback) (const gchar *id,
+ const gchar *vcard,
+ GError *error,
+ gpointer user_data);
+
+void dapi_gnome_local_file (const gchar *url,
+ const gchar *local,
+ gboolean allow_download,
+ DapiGnomeLocalFileCallback callback,
+ gpointer user_data);
+void dapi_gnome_upload_file (const gchar *local,
+ const gchar *url,
+ gboolean remove_local,
+ DapiGnomeUploadFileCallback callback,
+ gpointer user_data);
+gboolean dapi_gnome_remove_temp_local_file (const gchar *filename);
+void dapi_gnome_address_book_get_list (DapiGnomeListCallback callback,
+ gpointer user_data);
+void dapi_gnome_address_book_get_name (const gchar *id,
+ DapiGnomeNameCallback callback,
+ gpointer user_data);
+void dapi_gnome_address_book_get_emails (const gchar *id,
+ DapiGnomeEmailsCallback callback,
+ gpointer user_data);
+void dapi_gnome_address_book_find_by_name (const gchar *name,
+ DapiGnomeFindCallback callback,
+ gpointer user_data);
+gboolean dapi_gnome_address_book_get_owner (gchar **id,
+ GError **error);
+void dapi_gnome_address_book_get_vcard (const gchar *id,
+ DapiGnomeVCardCallback callback,
+ gpointer user_data);
+
+#endif /* __DAPI_GNOME_H__ */
+
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..504cfc3
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,40 @@
+TESTS = \
+ test-api
+#
+# DBUS
+#
+
+BUILT_SOURCES = dapi-command-bindings.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+%-bindings.h: $(top_builddir)/data/%.xml
+ $(DBUSBINDINGTOOL) --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^
+
+
+#
+# Tests
+#
+INCLUDES = \
+ -I$(top_srcdir)/data \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
+ $(DAPI_GNOME_CFLAGS)
+
+LIBS = \
+ $(DAPI_GNOME_LIBS) \
+ -lcheck
+
+noinst_PROGRAMS = \
+ test-client \
+ test-ebook-async-get-contact \
+ $(TESTS)
+
+test_client = test-client.c
+
+test_api_SOURCES = \
+ test-api.c \
+ test-addressbook.c \
+ tests.h
+
+test_ebook_async_get_contact = test-ebook-async-get-contact.c
+
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..0b2d864
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,3 @@
+Example sending an email:
+
+./test-daemon -m martyn@imendio.com --mail-subject sliff --mail-body sloff --mail-cc richard@imendio.com --mail-bcc micke@imendio.com --mail-attachment /etc/fstab --mail-attachment /etc/hosts
diff --git a/tests/test-addressbook.c b/tests/test-addressbook.c
new file mode 100644
index 0000000..17719da
--- /dev/null
+++ b/tests/test-addressbook.c
@@ -0,0 +1,380 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Mikael Hallendal <micke@test-user.com>
+ * Martyn Russell <martyn@test-user.com>
+ */
+
+#include <string.h>
+
+#include <glib.h>
+#include <libebook/e-book.h>
+
+#include "tests.h"
+
+#define d(x)
+
+#define CONTACT_FULL_NAME "Dapi TestUser"
+#define CONTACT_GIVEN_NAME "Dapi"
+#define CONTACT_FAMILY_NAME "TestUser"
+#define CONTACT_FILE_AS "TestUser, Dapi"
+#define CONTACT_EMAIL_1 "Dapi@test-user.com"
+#define CONTACT_EMAIL_2 "TestUser@test-user.com"
+#define CONTACT_EMAIL_3 "DapiTestUser@test-user.com"
+
+static const gchar *new_contact_id = NULL;
+
+/* FIXME: I have noticed that if a test fails that the post condition
+ * is NEVER run, which means you end up with a lot of new contacts
+ * which don't get deleted!
+ */
+
+static void
+pre_test (void)
+{
+ EBook *book;
+ EContact *contact;
+ EBookChange *change;
+ GList *changes;
+ GError *error = NULL;
+ const gchar *str;
+ gboolean success;
+
+ if (new_contact_id) {
+ g_warning ("Contact ID is already set, it looks like "
+ "the previous test didn't clean up");
+ return;
+ }
+
+ d(g_print ("\n"));
+
+ /* Add a contact to the address book here */
+ book = e_book_new_system_addressbook (NULL);
+ g_return_if_fail (book != NULL);
+
+ success = e_book_open (book, FALSE, &error);
+ if (!success) {
+ g_warning ("Could not open address book, %s",
+ error ? error->message : "no error given");
+ g_clear_error (&error);
+ g_object_unref (book);
+ return;
+ }
+
+ contact = e_contact_new ();
+ if (!contact) {
+ g_warning ("Could not create new contact");
+ g_object_unref (book);
+ return;
+ }
+
+ /* Set details for contact */
+ e_contact_set (contact, E_CONTACT_FILE_AS, CONTACT_FILE_AS);
+ e_contact_set (contact, E_CONTACT_FULL_NAME, CONTACT_FULL_NAME);
+ e_contact_set (contact, E_CONTACT_GIVEN_NAME, CONTACT_GIVEN_NAME);
+ e_contact_set (contact, E_CONTACT_FAMILY_NAME, CONTACT_FAMILY_NAME);
+ e_contact_set (contact, E_CONTACT_EMAIL_1, CONTACT_EMAIL_1);
+ e_contact_set (contact, E_CONTACT_EMAIL_2, CONTACT_EMAIL_2);
+ e_contact_set (contact, E_CONTACT_EMAIL_3, CONTACT_EMAIL_3);
+
+ success = e_book_add_contact (book, contact, &error);
+ if (!success) {
+ g_warning ("Could not add new contact, %s",
+ error ? error->message : "no error given");
+ g_clear_error (&error);
+ g_object_unref (book);
+ return;
+ }
+
+ if (!e_book_get_changes (book, "changeidtest", &changes, &error)) {
+ g_warning ("Could not get book changes, %s",
+ error ? error->message : "no error given");
+ g_object_unref (contact);
+ g_object_unref (book);
+ return;
+ }
+
+ change = changes->data;
+ if (change->change_type != E_BOOK_CHANGE_CARD_ADDED) {
+ g_warning ("Expected change to be E_BOOK_CHANGE_CARD_ADDED, but didn't get it.\n");
+ e_book_free_change_list (changes);
+ g_object_unref (contact);
+ g_object_unref (book);
+ return;
+ }
+
+ /* Remember pertinent information */
+ str = e_contact_get_const (change->contact, E_CONTACT_UID);
+ if (!str) {
+ g_warning ("Could not get new contact's ID");
+ } else {
+ /* Remember this contact id */
+ new_contact_id = g_strdup (str);
+
+ d(g_print ("Added new contact with ID is '%s'\n", new_contact_id));
+ }
+
+ e_book_free_change_list (changes);
+ g_object_unref (contact);
+ g_object_unref (book);
+}
+
+static void
+post_test (void)
+{
+ EBook *book;
+ GError *error = NULL;
+ gboolean success;
+
+ if (!new_contact_id) {
+ g_warning ("Contact ID was NULL, it looks like "
+ "the test was not set up correctly");
+ return;
+ }
+
+ /* Remove the added test contact from the addressbook here */
+ book = e_book_new_system_addressbook (NULL);
+ g_return_if_fail (book != NULL);
+
+ success = e_book_open (book, FALSE, &error);
+ if (!success) {
+ g_warning ("Could not open address book, %s",
+ error ? error->message : "no error given");
+ g_clear_error (&error);
+ g_object_unref (book);
+ return;
+ }
+
+ success = e_book_remove_contact (book, new_contact_id, &error);
+ if (!success) {
+ g_warning ("Could not remove new contact with ID:'%s', %s",
+ new_contact_id,
+ error ? error->message : "no error given");
+ g_clear_error (&error);
+ } else {
+ d(g_print ("Removed new contact with ID is '%s'\n", new_contact_id));
+ }
+
+ g_object_unref (book);
+
+ new_contact_id = NULL;
+}
+
+START_TEST (test_addressbook_list)
+{
+ DBusGProxy *proxy;
+ gchar **ids, **p;
+ gint count;
+ gboolean found;
+ gboolean success;
+
+ /* Test the list call here */
+ /* 1. Check that the command run successfully */
+ /* 2. Check that our contact is among the listed */
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ success = org_freedesktop_dapi_address_book_list (proxy, &ids, NULL);
+ fail_if (success == FALSE);
+ fail_if (ids == NULL);
+
+ for (p = ids, found = FALSE, count = 0;
+ *p && !found;
+ p++, count++) {
+ if (strcmp (*p, new_contact_id) == 0) {
+ found = TRUE;
+ }
+ }
+
+ d(g_print ("Address book has %d contacts and our new contact was %sfound\n",
+ count, found ? "" : "not "));
+
+ fail_if (found == FALSE);
+}
+END_TEST
+
+START_TEST (test_addressbook_owner)
+{
+ DBusGProxy *proxy;
+ gchar *contact_id;
+ gboolean success;
+
+ /* Test the owner call here */
+ /* 1. Check that the command run successfully */
+ /* 2. Unsure if we can really do any data checking here? */
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ success = org_freedesktop_dapi_address_book_owner (proxy, &contact_id, NULL);
+ fail_if (success == FALSE);
+ fail_if (contact_id == NULL);
+
+ d(g_print ("Own contact is '%s'\n", contact_id));
+}
+END_TEST
+
+START_TEST (test_addressbook_find_by_name)
+{
+ DBusGProxy *proxy;
+ gchar **ids, **p;
+ gint count;
+ gboolean found;
+ gboolean success;
+
+ /* Test the owner call here */
+ /* 1. Check that the command run successfully */
+ /* 2. Check that the ID we got back was the one we added above */
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ success = org_freedesktop_dapi_address_book_find_by_name (proxy, CONTACT_FULL_NAME, &ids, NULL);
+ fail_if (success == FALSE);
+ fail_if (ids == NULL);
+
+ for (p = ids, found = FALSE, count = 0;
+ *p && !found;
+ p++, count++) {
+ if (strcmp (*p, new_contact_id) == 0) {
+ found = TRUE;
+ }
+ }
+
+ d(g_print ("Address book found %d contacts matching and our new contact was %sfound\n",
+ count, found ? "" : "not "));
+
+ fail_if (found == FALSE);
+}
+END_TEST
+
+START_TEST (test_addressbook_get_name)
+{
+ DBusGProxy *proxy;
+ gchar *given_name;
+ gchar *family_name;
+ gchar *full_name;
+ gboolean success;
+
+ /* Test the owner call here */
+ /* 1. Check that the command run successfully */
+ /* 2. Check that the name is correctly retrieved */
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ success = org_freedesktop_dapi_address_book_get_name (proxy, new_contact_id,
+ &given_name,
+ &family_name,
+ &full_name,
+ NULL);
+ fail_if (success == FALSE);
+ fail_if (strcmp (given_name, CONTACT_GIVEN_NAME) != 0);
+ fail_if (strcmp (family_name, CONTACT_FAMILY_NAME) != 0);
+ fail_if (strcmp (full_name, CONTACT_FULL_NAME) != 0);
+
+ d(g_print ("New contact's names are, given:'%s', family:'%s', full:'%s'\n",
+ given_name, family_name, full_name));
+
+}
+END_TEST
+
+START_TEST (test_addressbook_get_emails)
+{
+ DBusGProxy *proxy;
+ gchar **addresses, **p;
+ gint count, found;
+ gboolean success;
+
+ /* Test the owner call here */
+ /* 1. Check that the command run successfully */
+ /* 2. Check that all the emails (we should set more than one) are
+ * retrieved correctly */
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ success = org_freedesktop_dapi_address_book_get_emails (proxy, new_contact_id, &addresses, NULL);
+ fail_if (success == FALSE);
+ fail_if (addresses == NULL);
+
+ for (p = addresses, found = 0, count = 0;
+ *p && found < 3;
+ p++, count++) {
+ if (strcmp (*p, CONTACT_EMAIL_1) == 0 ||
+ strcmp (*p, CONTACT_EMAIL_2) == 0 ||
+ strcmp (*p, CONTACT_EMAIL_3) == 0) {
+ found++;
+ }
+ }
+
+ d(g_print ("Address book found %d email addresses\n", found));
+
+ fail_if (found < 3);
+}
+END_TEST
+
+START_TEST (test_addressbook_get_vcard30)
+{
+ DBusGProxy *proxy;
+ gchar *vcard;
+ gboolean success;
+
+ /* Test the owner call here */
+ /* 1. Check that the command run successfully */
+ /* 2. Check that the vcard looks good */
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ success = org_freedesktop_dapi_address_book_get_vcard30 (proxy, new_contact_id, &vcard, NULL);
+ fail_if (success == FALSE);
+ fail_if (vcard == NULL);
+ fail_if (strstr (vcard, CONTACT_FULL_NAME) == NULL);
+
+ d(g_print ("VCard for contact ID:'%s' is\n%s\n", new_contact_id, vcard));
+
+ /* Expected failures */
+ success = org_freedesktop_dapi_address_book_get_vcard30 (proxy, NULL, &vcard, NULL);
+ fail_if (success == TRUE);
+}
+END_TEST
+
+Suite *
+tests_create_addressbook_test_suite (void)
+{
+ Suite *suite;
+ TCase *t_case;
+
+ suite = suite_create ("Addressbook");
+
+ t_case = tcase_create ("Api");
+ tcase_add_checked_fixture (t_case, pre_test, post_test);
+ tcase_add_test (t_case, test_addressbook_list);
+ tcase_add_test (t_case, test_addressbook_owner);
+ tcase_add_test (t_case, test_addressbook_find_by_name);
+ tcase_add_test (t_case, test_addressbook_get_name);
+ tcase_add_test (t_case, test_addressbook_get_emails);
+ tcase_add_test (t_case, test_addressbook_get_vcard30);
+
+ suite_add_tcase (suite, t_case);
+
+ return suite;
+}
diff --git a/tests/test-api.c b/tests/test-api.c
new file mode 100644
index 0000000..8b87efe
--- /dev/null
+++ b/tests/test-api.c
@@ -0,0 +1,380 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tests.h"
+
+#define DAPI_DBUS_SERVICE "org.freedesktop.dapi"
+#define DAPI_DBUS_PATH "/org/freedesktop/dapi"
+#define DAPI_DBUS_INTERFACE "org.freedesktop.dapi"
+
+DBusGProxy *
+tests_get_dbus_proxy (void)
+{
+ DBusGConnection *connection;
+ static DBusGProxy *proxy = NULL;
+ GError *error = NULL;
+
+ if (proxy) {
+ return proxy;
+ }
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (connection == NULL) {
+ g_warning ("Failed to open connection to session bus: %s\n",
+ error->message);
+ g_clear_error (&error);
+ return NULL;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ DAPI_DBUS_SERVICE,
+ DAPI_DBUS_PATH,
+ DAPI_DBUS_INTERFACE);
+
+ return proxy;
+}
+
+static GValue *
+tests_get_windowinfo (gboolean clear)
+{
+ static GValue windowinfo = {0, };
+
+ if (clear && G_IS_VALUE (&windowinfo)) {
+ g_value_unset (&windowinfo);
+ return NULL;
+ }
+
+ if (G_IS_VALUE (&windowinfo)) {
+ return &windowinfo;
+ }
+
+ g_value_init (&windowinfo, G_TYPE_INT);
+
+ return &windowinfo;
+}
+
+/*
+ * Actual tests
+ */
+
+START_TEST (test_get_capabilities)
+{
+ DBusGProxy *proxy;
+ gboolean result;
+ gint capabilities;
+
+ proxy = tests_get_dbus_proxy ();
+
+ result = org_freedesktop_dapi_capabilities (proxy, &capabilities, NULL);
+ fail_if (result == FALSE);
+ fail_if (capabilities < 1);
+}
+END_TEST
+
+START_TEST (test_get_button_order)
+{
+ DBusGProxy *proxy;
+ gboolean result;
+ gint order;
+
+ proxy = tests_get_dbus_proxy ();
+
+ result = org_freedesktop_dapi_button_order (proxy, &order, NULL);
+ fail_if (result == FALSE);
+ fail_if (order < 1);
+ fail_if (order > 2);
+}
+END_TEST
+
+START_TEST (test_run_as_user)
+{
+ DBusGProxy *proxy;
+ gboolean result;
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ result = org_freedesktop_dapi_run_as_user (proxy, "root", "/usr/bin/test",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == FALSE);
+
+ /* Expected failures */
+
+ /* gksu doesn't return FALSE on failure, so we always get
+ * TRUE, this test can't be concluded until we can trust the
+ * return value.
+ *
+ * result = org_freedesktop_dapi_run_as_user (proxy, "invalidusername", "/test", NULL);
+ * fail_if (result == TRUE);
+ */
+
+ result = org_freedesktop_dapi_run_as_user (proxy, NULL, NULL,
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == TRUE);
+}
+END_TEST
+
+START_TEST (test_screen_saving_suspend)
+{
+ DBusGProxy *proxy;
+ gboolean result;
+
+ proxy = tests_get_dbus_proxy ();
+
+ result = org_freedesktop_dapi_suspend_screen_saving (proxy, 1, TRUE, NULL);
+ fail_if (result == FALSE);
+
+ /* Should fail due to the client id already setting suspend on */
+ result = org_freedesktop_dapi_suspend_screen_saving (proxy, 1, TRUE, NULL);
+ fail_if (result == TRUE);
+
+ result = org_freedesktop_dapi_suspend_screen_saving (proxy, 1, FALSE, NULL);
+ fail_if (result == FALSE);
+
+ /* Should fail due to the client id already setting resume */
+ result = org_freedesktop_dapi_suspend_screen_saving (proxy, 1, FALSE, NULL);
+ fail_if (result == TRUE);
+}
+END_TEST
+
+START_TEST (test_open_url)
+{
+ DBusGProxy *proxy;
+ gboolean result;
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ result = org_freedesktop_dapi_open_url (proxy, "http://www.google.com",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == FALSE);
+
+ /* Expected failures */
+ result = org_freedesktop_dapi_open_url (proxy, "www.google.com",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == TRUE);
+}
+END_TEST
+
+START_TEST (test_execute_url)
+{
+ DBusGProxy *proxy;
+ gboolean result;
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected successes */
+ result = org_freedesktop_dapi_execute_url (proxy, "http://www.imendio.com",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == FALSE);
+
+ result = org_freedesktop_dapi_execute_url (proxy, "file:///etc/fstab",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == FALSE);
+
+ /* Expected failures */
+ result = org_freedesktop_dapi_execute_url (proxy, "etc/fstab",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == TRUE);
+
+ result = org_freedesktop_dapi_execute_url (proxy, "aaa:///etc/fstab",
+ tests_get_windowinfo (FALSE), NULL);
+ fail_if (result == TRUE);
+}
+END_TEST
+
+START_TEST (test_mail_to)
+{
+ DBusGProxy *proxy;
+ const gchar *nullp[] = { 0, };
+ gboolean result;
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Note: DBus sucks because it doesn't NULL check the
+ * G_TYPE_STRV attachments so we have to pass our nullp
+ * variable in otherwise it will SEGV, --MJR
+ */
+
+ /* Expected successes */
+ result = org_freedesktop_dapi_mail_to (proxy,
+ "test", "foo",
+ "martyn@imendio.com",
+ "micke@imendio.com",
+ "waldo.bastian@intel.com",
+ nullp,
+ tests_get_windowinfo (FALSE),
+ NULL);
+ fail_if (result == FALSE);
+}
+END_TEST
+
+START_TEST (test_files)
+{
+ DBusGProxy *proxy;
+ gchar *filename;
+ gchar *p = NULL;
+ gboolean result;
+
+ proxy = tests_get_dbus_proxy ();
+
+ /* Expected failures */
+ result = org_freedesktop_dapi_local_file (proxy,
+ "http://www.google.com/index.html",
+ "file:///tmp/index.html",
+ FALSE,
+ tests_get_windowinfo (FALSE),
+ &filename,
+ NULL);
+
+
+ fail_if (result == TRUE);
+
+ /* FIXME: This next line WILL fail, because DBus sucks and
+ * doesn't set data that we are receiving to NULL when there
+ * is an error.
+ *
+ * fail_if (filename != NULL || strlen (filename) > 0);
+ */
+
+ result = org_freedesktop_dapi_remove_temporary_local_file (proxy, "file:///tmp/somefile.txt", NULL);
+ fail_if (result == TRUE);
+
+ /* Expected successes (we do this after because we use the other APIs to clean up */
+ result = org_freedesktop_dapi_local_file (proxy,
+ "http://www.google.com/index.html",
+ "file:///tmp/index.html",
+ TRUE,
+ tests_get_windowinfo (FALSE),
+ &filename,
+ NULL);
+
+ /* FIXME: We can't use a filename in the format of
+ * 'file:///tmp/foo' here, we need to remove the 'file://' part
+ */
+ if (filename && strstr (filename, "file://")) {
+ p = filename + 7;
+ }
+
+ fail_if (result == FALSE);
+ fail_if (filename == NULL || strlen (filename) < 1);
+ fail_if (p && g_file_test (p, G_FILE_TEST_EXISTS) == FALSE);
+
+ result = org_freedesktop_dapi_remove_temporary_local_file (proxy, filename, NULL);
+ fail_if (result == FALSE);
+ fail_if (p && g_file_test (p, G_FILE_TEST_EXISTS) == TRUE);
+
+ /* Final clean up */
+ g_free (filename);
+}
+END_TEST
+
+static Suite *
+tests_create_synchronous_test_suite (void)
+{
+ Suite *suite;
+ TCase *t_case;
+
+ suite = suite_create ("Synchronous");
+
+ t_case = tcase_create ("Capabilities");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_get_capabilities);
+ t_case = tcase_create ("Button Order");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_get_button_order);
+ t_case = tcase_create ("Run As User");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_run_as_user);
+ t_case = tcase_create ("Suspend Screen Saving");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_screen_saving_suspend);
+ t_case = tcase_create ("Opening URL");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_open_url);
+ t_case = tcase_create ("Executing URL");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_execute_url);
+ t_case = tcase_create ("Creating Mail");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_mail_to);
+
+ return suite;
+}
+
+static Suite *
+tests_create_asynchronous_test_suite (void)
+{
+ Suite *suite;
+ TCase *t_case;
+
+ suite = suite_create ("Asynchronous");
+
+ t_case = tcase_create ("Local/Upload/Remove");
+ suite_add_tcase (suite, t_case);
+ tcase_add_test (t_case, test_files);
+
+ return suite;
+}
+
+int
+main (int argc, char **argv)
+{
+ DBusGProxy *proxy;
+ Suite *suite;
+ SRunner *runner;
+ int failures, successes;
+
+ g_type_init ();
+
+ proxy = tests_get_dbus_proxy ();
+ if (!proxy) {
+ g_warning ("Could not connect to DBus service");
+ return EXIT_FAILURE;
+ }
+
+ suite = suite_create ("-");
+ runner = srunner_create (suite);
+ srunner_add_suite (runner, tests_create_synchronous_test_suite ());
+ srunner_add_suite (runner, tests_create_asynchronous_test_suite ());
+ srunner_add_suite (runner, tests_create_addressbook_test_suite ());
+
+ srunner_run_all (runner, CK_NORMAL);
+ failures = srunner_ntests_failed (runner);
+ successes = srunner_ntests_run (runner) - failures;
+ srunner_free (runner);
+
+ /* Clean up */
+ tests_get_windowinfo (TRUE);
+
+ if (successes < 1) {
+ g_print ("\nHave you checked that the daemon is running?\n\n");
+ }
+
+ return (failures == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/test-client.c b/tests/test-client.c
new file mode 100644
index 0000000..2ac69f0
--- /dev/null
+++ b/tests/test-client.c
@@ -0,0 +1,1015 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <dapi-common.h>
+
+#include "dapi-command-bindings.h"
+
+#define DAPI_DBUS_SERVICE "org.freedesktop.dapi"
+#define DAPI_DBUS_PATH "/org/freedesktop/dapi"
+#define DAPI_DBUS_INTERFACE "org.freedesktop.dapi"
+
+static gchar * test_capabilities_to_str (gint capability);
+static gboolean test_show_capabilities (DBusGProxy *proxy);
+static gboolean test_open_url (DBusGProxy *proxy,
+ const gchar *url,
+ GValue *windowinfo);
+static gboolean test_execute_url (DBusGProxy *proxy,
+ const gchar *url,
+ GValue *windowinfo);
+static gboolean test_button_order (DBusGProxy *proxy);
+static gboolean test_run_as_user (DBusGProxy *proxy,
+ const gchar *user,
+ const gchar *command,
+ GValue *windowinfo);
+static gboolean test_suspend_screen_saving (DBusGProxy *proxy,
+ gint seconds);
+static gboolean test_mailto (DBusGProxy *proxy,
+ const gchar *subject,
+ const gchar *body,
+ const gchar *to,
+ const gchar *cc,
+ const gchar *bcc,
+ const gchar **attachments,
+ GValue *windowinfo);
+static void test_local_file_cb (DBusGProxy *proxy,
+ gchar *filename,
+ GError *error,
+ gpointer user_data);
+static gboolean test_local_file (DBusGProxy *proxy,
+ const gchar *remote_url,
+ const gchar *local_url,
+ gboolean allow_download,
+ GValue *windowinfo);
+static void test_upload_file_cb (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data);
+static gboolean test_upload_file (DBusGProxy *proxy,
+ const gchar *local_url,
+ const gchar *remote_url,
+ gboolean remove_local,
+ GValue *windowinfo);
+static gboolean test_remove_temporary_local_file (DBusGProxy *proxy,
+ const gchar *url);
+static void test_address_book_get_list_cb (DBusGProxy *proxy,
+ gchar **ids,
+ GError *error,
+ gpointer user_data);
+static gboolean test_address_book_get_list (DBusGProxy *proxy);
+static void test_address_book_get_name_cb (DBusGProxy *proxy,
+ gchar *given_name,
+ gchar *family_name,
+ gchar *full_name,
+ GError *error,
+ gpointer user_data);
+static gboolean test_address_book_get_name (DBusGProxy *proxy,
+ const gchar *id);
+static void test_address_book_get_emails_cb (DBusGProxy *proxy,
+ gchar **email_addresses,
+ GError *error,
+ gpointer user_data);
+static gboolean test_address_book_get_emails (DBusGProxy *proxy,
+ const gchar *id);
+static gboolean test_address_book_find_by_name (DBusGProxy *proxy,
+ const gchar *name);
+static gboolean test_address_book_get_owner (DBusGProxy *proxy);
+static gboolean test_address_book_get_vcard (DBusGProxy *proxy,
+ const gchar *id);
+static void test_address_book_get_vcard30_cb (DBusGProxy *proxy,
+ gchar *vcard,
+ GError *error,
+ gpointer user_data);
+static DBusGProxy *test_get_dbus_proxy (void);
+static void test_status_update (gboolean complete);
+
+static gboolean show_capabilities = FALSE;
+static const gchar *open_url = NULL;
+static const gchar *execute_url = NULL;
+static gboolean button_order = FALSE;
+static const gchar *run_user = NULL;
+static const gchar *run_command = NULL;
+static gint suspend_screensaver = 0;
+static const gchar *mail_subject = NULL;
+static const gchar *mail_body = NULL;
+static const gchar *mail_to = NULL;
+static const gchar *mail_cc = NULL;
+static const gchar *mail_bcc = NULL;
+static const gchar **mail_attachments = NULL;
+static const gchar *local_url = NULL;
+static gboolean allow_download = FALSE;
+static const gchar *upload_url = NULL;
+static gboolean remove_local = FALSE;
+static const gchar *remote_url = NULL;
+static const gchar *remove_temporary_local_file = NULL;
+static gboolean address_book_get_list = FALSE;
+static const gchar *address_book_get_name = NULL;
+static const gchar *address_book_get_emails = NULL;
+static const gchar *address_book_find_by_name = NULL;
+static gboolean address_book_get_owner = FALSE;
+static const gchar *address_book_get_vcard = NULL;
+
+static GMainLoop *main_loop = NULL;
+static gint tasks_waiting = 0;
+
+static const GOptionEntry options[] = {
+ { "show-capabilities", 'c',
+ 0, G_OPTION_ARG_NONE, &show_capabilities,
+ N_("Show a list of capabilities"),
+ NULL },
+ { "open-url", 'o',
+ 0, G_OPTION_ARG_STRING, &open_url,
+ N_("Open a URL (e.g. http://www.google.com/) using the default browser"),
+ NULL },
+ { "execute-url", 'x',
+ 0, G_OPTION_ARG_STRING, &execute_url,
+ N_("Open a URL (e.g. file:///tmp/test.txt) using the default application"),
+ NULL },
+ { "button-order", 'b',
+ 0, G_OPTION_ARG_NONE, &button_order,
+ N_("Retrieve the current button order (e.g. OK/Cancel or Cancel/OK)"),
+ NULL },
+ { "run-as-user", 'u',
+ 0, G_OPTION_ARG_STRING, &run_user,
+ N_("Used with --run-command, user to run as (e.g. root)"),
+ NULL },
+ { "run-command", 'r',
+ 0, G_OPTION_ARG_STRING, &run_command,
+ N_("Used with --run-as-user, command to run (e.g. /usr/bin/synaptic)"),
+ NULL },
+ { "suspend-screensaver", 's',
+ 0, G_OPTION_ARG_INT, &suspend_screensaver,
+ N_("Suspend the screensaver for the number of seconds specified"),
+ NULL },
+ { "mail-to", 'm',
+ 0, G_OPTION_ARG_STRING, &mail_to,
+ N_("Send a mail to the address specified"),
+ NULL },
+ /* Add a bunch of flags for the mailto test */
+ { "mail-subject", 0,
+ 0, G_OPTION_ARG_STRING, &mail_subject,
+ N_("Used with --mail-to, subject of the email"),
+ NULL },
+ { "mail-body", 0,
+ 0, G_OPTION_ARG_STRING, &mail_body,
+ N_("Used with --mail-to, body of the email"),
+ NULL },
+ { "mail-cc", 0,
+ 0, G_OPTION_ARG_STRING, &mail_cc,
+ N_("Used with --mail-to, cc addresses to send to"),
+ NULL },
+ { "mail-bcc", 0,
+ 0, G_OPTION_ARG_STRING, &mail_bcc,
+ N_("Used with --mail-to, bcc addresses to send to"),
+ NULL },
+ { "mail-attachment", 0,
+ 0, G_OPTION_ARG_STRING_ARRAY, &mail_attachments,
+ N_("Used with --mail-to, attachment to send (can be used multiple times)"),
+ NULL },
+ { "local-url", 0,
+ 0, G_OPTION_ARG_STRING, &local_url,
+ N_("Used with --remote-url and --allow-download, Copy remote url to local file"),
+ NULL },
+ { "upload-url", 0,
+ 0, G_OPTION_ARG_STRING, &upload_url,
+ N_("Used with --remote-url and --remove-local, Copy local file back to remote url"),
+ NULL },
+ { "remote-url", 0,
+ 0, G_OPTION_ARG_STRING, &remote_url,
+ N_("Used with --local-url and --upload-url, this is the remote url to download or upload"),
+ NULL },
+ { "allow-download", 0,
+ 0, G_OPTION_ARG_NONE, &allow_download,
+ N_("Used with --local-url, allow the remote url to be downloaded (optional, default is FALSE)"),
+ NULL },
+ { "remove-temporary-local-file", 0,
+ 0, G_OPTION_ARG_STRING, &remove_temporary_local_file,
+ N_("Used with --local-url, this removes a temporary file created by --local-url"),
+ NULL },
+ { "remove-local", 0,
+ 0, G_OPTION_ARG_NONE, &remove_local,
+ N_("Used with --upload-url, remove local temporary file after uploaded (optional, default is FALSE)"),
+ NULL },
+ { "address-book-get-list", 'l',
+ 0, G_OPTION_ARG_NONE, &address_book_get_list,
+ N_("Retrieve address book user IDs"),
+ NULL },
+ { "address-book-get-names", 'n',
+ 0, G_OPTION_ARG_STRING, &address_book_get_name,
+ N_("Retrieve names associated with a user ID"),
+ NULL },
+ { "address-book-get-emails", 'e',
+ 0, G_OPTION_ARG_STRING, &address_book_get_emails,
+ N_("Retrieve emails addresses associated with a user ID"),
+ NULL },
+ { "address-book-find-by-name", 'f',
+ 0, G_OPTION_ARG_STRING, &address_book_find_by_name,
+ N_("Find a contact's user ID by their real name."),
+ NULL },
+ { "address-book-get-owner", 'w',
+ 0, G_OPTION_ARG_NONE, &address_book_get_owner,
+ N_("Retrieve address book owner's user ID"),
+ NULL },
+ { "address-book-get-vcard", 'v',
+ 0, G_OPTION_ARG_STRING, &address_book_get_vcard,
+ N_("Retrieve the vcard associated with a user ID"),
+ NULL },
+ { NULL }
+};
+
+static gchar *
+test_capabilities_to_str (gint capability)
+{
+ GString *s;
+
+ s = g_string_new ("");
+
+ if (capability & DAPI_CAP_OPENURL)
+ s = g_string_append (s, "DAPI_CAP_OPENURL | ");
+ if (capability & DAPI_CAP_EXECUTEURL)
+ s = g_string_append (s, "DAPI_CAP_EXECUTEURL | ");
+ if (capability & DAPI_CAP_BUTTONORDER)
+ s = g_string_append (s, "DAPI_CAP_BUTTONORDER | ");
+ if (capability & DAPI_CAP_RUNASUSER)
+ s = g_string_append (s, "DAPI_CAP_RUNASUSER | ");
+ if (capability & DAPI_CAP_SUSPENDSCREENSAVING)
+ s = g_string_append (s, "DAPI_CAP_SUSPENDSCREENSAVING | ");
+ if (capability & DAPI_CAP_MAILTO)
+ s = g_string_append (s, "DAPI_CAP_MAILTO | ");
+ if (capability & DAPI_CAP_LOCALFILE)
+ s = g_string_append (s, "DAPI_CAP_LOCALFILE | ");
+ if (capability & DAPI_CAP_UPLOADFILE)
+ s = g_string_append (s, "DAPI_CAP_UPLOADFILE | ");
+ if (capability & DAPI_CAP_REMOVETEMPORARYLOCALFILE)
+ s = g_string_append (s, "DAPI_CAP_REMOVETEMPORARYLOCALFILE | ");
+ if (capability & DAPI_CAP_ADDRESSBOOKLIST)
+ s = g_string_append (s, "DAPI_CAP_ADDRESSBOOKLIST | ");
+ if (capability & DAPI_CAP_ADDRESSBOOKGETNAME)
+ s = g_string_append (s, "DAPI_CAP_ADDRESSBOOKGETNAME | ");
+ if (capability & DAPI_CAP_ADDRESSBOOKGETEMAILS)
+ s = g_string_append (s, "DAPI_CAP_ADDRESSBOOKGETEMAILS | ");
+ if (capability & DAPI_CAP_ADDRESSBOOKFINDBYNAME)
+ s = g_string_append (s, "DAPI_CAP_ADDRESSBOOKFINDBYNAME | ");
+ if (capability & DAPI_CAP_ADDRESSBOOKOWNER)
+ s = g_string_append (s, "DAPI_CAP_ADDRESSBOOKOWNER | ");
+ if (capability & DAPI_CAP_ADDRESSBOOKGETVCARD30)
+ s = g_string_append (s, "DAPI_CAP_ADDRESSBOOKGETVCARD30 | ");
+
+ s->len -= 3;
+ s->str[s->len] = '\0';
+
+ return g_string_free (s, FALSE);
+}
+
+static gboolean
+test_show_capabilities (DBusGProxy *proxy)
+{
+ gint capabilities;
+ gchar *str, **strv;
+ GError *error = NULL;
+
+ if (!org_freedesktop_dapi_capabilities (proxy, &capabilities, &error)) {
+ g_printerr ("Could not get capabilities, error: %s\n",
+ error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ if (capabilities < 1) {
+ g_print ("No capabilities returned\n");
+ return TRUE;
+ }
+
+ g_print ("Capabilities (%d):\n", capabilities);
+
+ /* Use for an int not an array of ints */
+ str = test_capabilities_to_str (capabilities);
+ strv = g_strsplit (str, "|", -1);
+ g_free (str);
+
+ str = g_strjoinv ("\n\t --->", strv);
+ g_strfreev (strv);
+
+ g_print ("\t ---> %s\n", str);
+ g_free (str);
+
+ return TRUE;
+}
+
+static gboolean
+test_open_url (DBusGProxy *proxy,
+ const gchar *url,
+ GValue *windowinfo)
+{
+ GError *error = NULL;
+
+ if (!org_freedesktop_dapi_open_url (proxy, url, windowinfo, &error)) {
+ g_printerr ("Could not open URL:'%s', error: %s\n",
+ url, error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Opened URL:'%s'\n", url);
+
+ return TRUE;
+}
+
+static gboolean
+test_execute_url (DBusGProxy *proxy,
+ const gchar *url,
+ GValue *windowinfo)
+{
+ GError *error = NULL;
+
+ if (!org_freedesktop_dapi_execute_url (proxy, url, windowinfo, &error)) {
+ g_printerr ("Could not execute URL:'%s', error: %s\n",
+ url, error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Executed URL:'%s'\n", url);
+
+ return TRUE;
+}
+
+static gboolean
+test_button_order (DBusGProxy *proxy)
+{
+ GError *error = NULL;
+ const gchar *str = "Unknown";
+ gint button_order;
+
+ if (!org_freedesktop_dapi_button_order (proxy, &button_order, &error)) {
+ g_printerr ("Could not get button order, error: %s\n",
+ error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ if (button_order == 1) {
+ str = "Cancel/OK";
+ } else if (button_order == 2) {
+ str = "OK/Cancel";
+ }
+
+ g_print ("Button order is %s\n", str);
+
+ return TRUE;
+}
+
+static gboolean
+test_run_as_user (DBusGProxy *proxy,
+ const gchar *user,
+ const gchar *command,
+ GValue *windowinfo)
+{
+ GError *error = NULL;
+
+ if (!org_freedesktop_dapi_run_as_user (proxy, user, command, windowinfo, &error)) {
+ g_printerr ("Could not run command:'%s' as user:'%s', error: %s\n",
+ command, user, error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Ran command:'%s' as user:'%s'\n", command, user);
+
+ return TRUE;
+}
+
+static gboolean
+test_suspend_screen_saving (DBusGProxy *proxy,
+ gint seconds)
+{
+ GError *error = NULL;
+ guint client_id = 1;
+
+ if (!org_freedesktop_dapi_suspend_screen_saving (proxy, client_id, TRUE, &error)) {
+ g_printerr ("Could not suspend screen saving, error: %s\n",
+ error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Suspended screen saving for %d seconds.\n", seconds);
+
+ g_usleep (G_USEC_PER_SEC * seconds);
+
+ if (!org_freedesktop_dapi_suspend_screen_saving (proxy, client_id, FALSE, &error)) {
+ g_printerr ("Could not resumed screen saving, error: %s\n",
+ error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+test_mailto (DBusGProxy *proxy,
+ const gchar *subject,
+ const gchar *body,
+ const gchar *to,
+ const gchar *cc,
+ const gchar *bcc,
+ const gchar **attachments,
+ GValue *windowinfo)
+{
+ GError *error = NULL;
+ const gchar **p;
+ const gchar *nullp[] = { 0, };
+
+ if (attachments) {
+ p = attachments;
+ } else {
+ p = nullp;
+ }
+
+ if (!org_freedesktop_dapi_mail_to (proxy, subject, body, to, cc, bcc, p, windowinfo, &error)) {
+ g_printerr ("Could not create new mail to:'%s', error: %s\n",
+ to, error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Created new mail to:'%s'\n", to);
+
+ return TRUE;
+}
+
+static void
+test_local_file_cb (DBusGProxy *proxy,
+ gchar *filename,
+ GError *error,
+ gpointer user_data)
+{
+ gchar *remote_url;
+
+ remote_url = user_data;
+
+ if (error) {
+ g_print ("Could not create local file from url:'%s', error: %s\n",
+ remote_url, error->message);
+ } else {
+ g_print ("Created local file from url:'%s' as:'%s'\n",
+ remote_url, filename);
+ }
+
+ g_free (remote_url);
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_local_file (DBusGProxy *proxy,
+ const gchar *remote_url,
+ const gchar *local_url,
+ gboolean allow_download,
+ GValue *windowinfo)
+{
+ if (!org_freedesktop_dapi_local_file_async (proxy,
+ remote_url,
+ local_url,
+ allow_download,
+ windowinfo,
+ test_local_file_cb,
+ g_strdup (remote_url))) {
+ g_printerr ("Could not create local file:'%s' from remote file:'%s', no error given\n",
+ local_url, remote_url);
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static void
+test_upload_file_cb (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ gchar *local_url;
+
+ local_url = user_data;
+
+ if (error) {
+ g_print ("Could not upload local file:'%s', error: %s\n",
+ local_url, error->message);
+ } else {
+ g_print ("Uploaded local file:'%s'\n",
+ local_url);
+ }
+
+ g_free (local_url);
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_upload_file (DBusGProxy *proxy,
+ const gchar *local_url,
+ const gchar *remote_url,
+ gboolean remove_local,
+ GValue *windowinfo)
+{
+ if (!org_freedesktop_dapi_upload_file_async (proxy,
+ remote_url,
+ local_url,
+ allow_download,
+ windowinfo,
+ test_upload_file_cb,
+ g_strdup (local_url))) {
+ g_printerr ("Could not upload local file:'%s' to remote file:'%s', no error given\n",
+ local_url, remote_url);
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+test_remove_temporary_local_file (DBusGProxy *proxy,
+ const gchar *local)
+{
+ GError *error = NULL;
+
+ if (!org_freedesktop_dapi_remove_temporary_local_file (proxy, local, &error)) {
+ g_printerr ("Could not remove temporary local file:'%s', error: %s\n",
+ local, error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Removed temporary local file:'%s'\n", local);
+
+ return TRUE;
+}
+
+static void
+test_address_book_get_list_cb (DBusGProxy *proxy,
+ gchar **ids,
+ GError *error,
+ gpointer user_data)
+{
+ if (error) {
+ g_print ("Could not get address book list, error: %s\n",
+ error->message);
+ } else {
+ gchar **p;
+
+ g_print ("Address book list\n");
+
+ for (p = ids; *p; p++) {
+ g_print ("\t\"%s\"\n", *p);
+ }
+ }
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_address_book_get_list (DBusGProxy *proxy)
+{
+ if (!org_freedesktop_dapi_address_book_list_async (proxy,
+ test_address_book_get_list_cb,
+ NULL)) {
+ g_printerr ("Could not get address book list, no error given\n");
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static void
+test_address_book_get_name_cb (DBusGProxy *proxy,
+ gchar *given_name,
+ gchar *family_name,
+ gchar *full_name,
+ GError *error,
+ gpointer user_data)
+{
+ gchar *id;
+
+ id = user_data;
+
+ if (error) {
+ g_print ("Could not get address book names for id:'%s', error: %s\n",
+ id, error->message);
+ } else {
+ if (!given_name && !family_name && !full_name) {
+ g_print ("No names are associated with id:'%s'\n", id);
+ } else {
+ g_print ("Names for id:'%s'\n", id);
+
+ if (given_name) {
+ g_print ("\tGiven name:'%s'\n", given_name);
+ }
+
+ if (family_name) {
+ g_print ("\tFamily name:'%s'\n", family_name);
+ }
+
+ if (full_name) {
+ g_print ("\tFull name:'%s'\n", full_name);
+ }
+ }
+ }
+
+ g_free (id);
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_address_book_get_name (DBusGProxy *proxy,
+ const gchar *id)
+{
+ if (!org_freedesktop_dapi_address_book_get_name_async (proxy,
+ id,
+ test_address_book_get_name_cb,
+ g_strdup (id))) {
+ g_printerr ("Could not get address book names "
+ "for id:'%s', no error given\n",
+ id);
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static void
+test_address_book_get_emails_cb (DBusGProxy *proxy,
+ gchar **email_addresses,
+ GError *error,
+ gpointer user_data)
+{
+ gchar *id;
+
+ id = user_data;
+
+ if (error) {
+ g_print ("Could not get address book email addresses "
+ "for contact:'%s', error: %s\n",
+ id, error->message);
+ } else {
+ gchar **p;
+
+ g_print ("Email addresses:\n");
+
+ for (p = email_addresses; *p; p++) {
+ g_print ("\t\"%s\"\n", *p);
+ }
+ }
+
+ g_free (id);
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_address_book_get_emails (DBusGProxy *proxy,
+ const gchar *id)
+{
+ if (!org_freedesktop_dapi_address_book_get_emails_async (proxy,
+ id,
+ test_address_book_get_emails_cb,
+ g_strdup (id))) {
+ g_printerr ("Could not get address book email addresses "
+ "for id:'%s', no error given\n",
+ id);
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static void
+test_address_book_find_by_name_cb (DBusGProxy *proxy,
+ gchar **ids,
+ GError *error,
+ gpointer user_data)
+{
+ gchar *name;
+
+ name = user_data;
+
+ if (error) {
+ g_print ("Could not find address book contacts "
+ "by name:'%s', error: %s\n",
+ name, error->message);
+ } else {
+ gchar **p;
+
+ g_print ("Contacts:\n");
+
+ for (p = ids; *p; p++) {
+ g_print ("\t\"%s\"\n", *p);
+ }
+ }
+
+ g_free (name);
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_address_book_find_by_name (DBusGProxy *proxy,
+ const gchar *name)
+{
+ if (!org_freedesktop_dapi_address_book_find_by_name_async (proxy,
+ name,
+ test_address_book_find_by_name_cb,
+ g_strdup (name))) {
+ g_printerr ("Could not find address book contacts "
+ "by name:'%s', no error given\n",
+ name);
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+test_address_book_get_owner (DBusGProxy *proxy)
+{
+ GError *error = NULL;
+ gchar *contact_id;
+
+ if (!org_freedesktop_dapi_address_book_owner (proxy, &contact_id, &error)) {
+ g_printerr ("Could not get address book owner, error: %s\n",
+ error ? error->message : "none");
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ g_print ("Address book owner has contact id:'%s'\n", contact_id);
+
+ return TRUE;
+}
+
+static void
+test_address_book_get_vcard30_cb (DBusGProxy *proxy,
+ gchar *vcard,
+ GError *error,
+ gpointer user_data)
+{
+ gchar *id;
+
+ id = user_data;
+
+ if (error) {
+ g_print ("Could not get vcard for contact "
+ "by id:'%s', error: %s\n",
+ id, error->message);
+ } else {
+ g_print ("VCard:\n%s\n", vcard);
+ }
+
+ g_free (id);
+
+ test_status_update (TRUE);
+}
+
+static gboolean
+test_address_book_get_vcard (DBusGProxy *proxy,
+ const gchar *id)
+{
+ if (!org_freedesktop_dapi_address_book_get_vcard30_async (proxy,
+ id,
+ test_address_book_get_vcard30_cb,
+ g_strdup (id))) {
+ g_printerr ("Could not get vcard for contact "
+ "by id:'%s', no error given\n",
+ id);
+ return FALSE;
+ }
+
+ test_status_update (FALSE);
+
+ return TRUE;
+}
+
+static DBusGProxy *
+test_get_dbus_proxy (void)
+{
+ DBusGConnection *connection;
+ static DBusGProxy *proxy = NULL;
+ GError *error = NULL;
+
+ if (proxy) {
+ return proxy;
+ }
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (connection == NULL) {
+ g_warning ("Failed to open connection to session bus: %s\n",
+ error->message);
+ g_clear_error (&error);
+ return NULL;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ DAPI_DBUS_SERVICE,
+ DAPI_DBUS_PATH,
+ DAPI_DBUS_INTERFACE);
+
+ return proxy;
+}
+
+static void
+test_status_update (gboolean complete)
+{
+ if (complete) {
+ tasks_waiting--;
+
+ if (tasks_waiting < 1) {
+ g_main_loop_quit (main_loop);
+ }
+ } else {
+ tasks_waiting++;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ DBusGProxy *proxy;
+ GValue windowinfo = {0, };
+ gboolean success = TRUE;
+
+ g_type_init ();
+
+ context = g_option_context_new ("- Test DAPI Daemon");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ if ((!show_capabilities && !open_url && !execute_url &&
+ !mail_to && !suspend_screensaver && !run_user &&
+ !run_command && !button_order &&
+ !address_book_get_list && !address_book_get_emails &&
+ !address_book_get_name && !address_book_find_by_name &&
+ !address_book_get_owner && !address_book_get_vcard &&
+ !local_url && !remote_url && !allow_download &&
+ !upload_url && !remove_temporary_local_file) ||
+ ((!run_user && run_command) || (!run_command && run_user)) ||
+ ((!local_url && remote_url && !upload_url) ||
+ (!remote_url && local_url && !upload_url)) ||
+ ((!upload_url && remote_url && !local_url) ||
+ (!remote_url && upload_url && !local_url))) {
+ g_printerr ("For usage, try %s --help\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ /* Set up DBus connection */
+ proxy = test_get_dbus_proxy ();
+ if (!proxy) {
+ return EXIT_FAILURE;
+ }
+
+ /* Set up empty window info, we have to do this because DBus
+ * doesn't NULL check G_TYPE_STRV or variants and SEGFAULTS
+ */
+ g_value_init (&windowinfo, G_TYPE_INT);
+
+ /* Run arguments */
+ if (success && show_capabilities &&
+ !test_show_capabilities (proxy)) {
+ success = FALSE;
+ }
+
+ if (success && open_url &&
+ !test_open_url (proxy, open_url, &windowinfo)) {
+ success = FALSE;
+ }
+
+ if (success && execute_url &&
+ !test_execute_url (proxy, execute_url, &windowinfo)) {
+ success = FALSE;
+ }
+
+ if (success && button_order &&
+ !test_button_order (proxy)) {
+ success = FALSE;
+ }
+
+ if (success && run_user && run_command &&
+ !test_run_as_user (proxy, run_user, run_command, &windowinfo)) {
+ success = FALSE;
+ }
+
+ if (success && suspend_screensaver &&
+ !test_suspend_screen_saving (proxy, suspend_screensaver)) {
+ success = FALSE;
+ }
+
+ if (success && mail_to &&
+ !test_mailto (proxy,
+ mail_subject,
+ mail_body,
+ mail_to,
+ mail_cc,
+ mail_bcc,
+ mail_attachments,
+ NULL)) {
+ success = FALSE;
+ }
+
+ if (success && local_url && remote_url &&
+ !test_local_file (proxy, remote_url, local_url, allow_download, &windowinfo)) {
+ success = FALSE;
+ }
+
+ if (success && upload_url && remote_url &&
+ !test_upload_file (proxy, upload_url, remote_url, remove_local, &windowinfo)) {
+ success = FALSE;
+ }
+
+ if (success && remove_temporary_local_file &&
+ !test_remove_temporary_local_file (proxy, remove_temporary_local_file)) {
+ success = FALSE;
+ }
+
+ if (success && address_book_get_list &&
+ !test_address_book_get_list (proxy)) {
+ success = FALSE;
+ }
+
+ if (success && address_book_get_name &&
+ !test_address_book_get_name (proxy, address_book_get_name)) {
+ success = FALSE;
+ }
+
+ if (success && address_book_get_emails &&
+ !test_address_book_get_emails (proxy, address_book_get_emails)) {
+ success = FALSE;
+ }
+
+ if (success && address_book_find_by_name &&
+ !test_address_book_find_by_name (proxy, address_book_find_by_name)) {
+ success = FALSE;
+ }
+
+ if (success && address_book_get_owner &&
+ !test_address_book_get_owner (proxy)) {
+ success = FALSE;
+ }
+
+ if (success && address_book_get_vcard &&
+ !test_address_book_get_vcard (proxy, address_book_get_vcard)) {
+ success = FALSE;
+ }
+
+ /* If we have async functions still to be completed, wait in a
+ * loop for them to be called back.
+ */
+ if (tasks_waiting > 0) {
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ g_main_loop_unref (main_loop);
+ }
+
+ g_object_unref (proxy);
+ g_value_unset (&windowinfo);
+
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/test-ebook-async-get-contact.c b/tests/test-ebook-async-get-contact.c
new file mode 100644
index 0000000..b283952
--- /dev/null
+++ b/tests/test-ebook-async-get-contact.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+#include <stdlib.h>
+
+#include <glib.h>
+#include <libebook/e-book.h>
+
+/* Abstract layer */
+typedef void (*NamesCallback) (const gchar *id,
+ const gchar *given_name,
+ const gchar *family_name,
+ const gchar *full_name,
+ gpointer user_data);
+typedef void (*EmailsCallback) (const gchar *id,
+ GList *addresses,
+ gpointer user_data);
+
+
+static void address_book_get_names_cb (EBook *book,
+ EBookStatus status,
+ EContact *contact,
+ gpointer closure);
+static void address_book_get_email_addresses_cb (EBook *book,
+ EBookStatus status,
+ EContact *contact,
+ gpointer closure);
+static void address_book_loaded_cb (EBook *book,
+ EBookStatus status,
+ gpointer closure);
+static gboolean address_book_get_names (const gchar *id,
+ NamesCallback callback,
+ gpointer user_data);
+static gboolean address_book_get_emails (const gchar *id,
+ EmailsCallback callback,
+ gpointer user_data);
+static gboolean address_book_get_owner (gchar **id);
+
+
+/* My functions */
+static void should_quit (void);
+static void get_names_cb (const gchar *id,
+ const gchar *given_name,
+ const gchar *family_name,
+ const gchar *full_name,
+ gpointer user_data);
+static void get_email_addresses_cb (const gchar *id,
+ GList *addresses,
+ gpointer user_data);
+
+static GMainLoop *main_loop = NULL;
+static gboolean have_names = FALSE;
+static gboolean have_email_addresses = FALSE;
+
+static void
+address_book_get_names_cb (EBook *book,
+ EBookStatus status,
+ EContact *contact,
+ gpointer closure)
+{
+ const gchar *id;
+ NamesCallback callback;
+ gpointer user_data;
+
+ const gchar *given_name = NULL;
+ const gchar *family_name = NULL;
+ const gchar *full_name = NULL;
+
+/* g_print ("EContact is %p\n", contact); */
+
+ /* FIXME: This should NOT fail */
+ g_return_if_fail (contact != NULL);
+ g_return_if_fail (E_IS_CONTACT (contact));
+
+ if (status != E_BOOK_ERROR_OK) {
+ g_warning ("Could not get contact, status is %d", status);
+ return;
+ }
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ g_print ("Getting address book names (given, family, full) "
+ "for user ID:'%s'...", id);
+
+ given_name = e_contact_get_const (contact, E_CONTACT_GIVEN_NAME);
+ family_name = e_contact_get_const (contact, E_CONTACT_FAMILY_NAME);
+ full_name = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
+
+ (callback) (id, given_name, family_name, full_name, user_data);
+
+ g_object_unref (book);
+}
+
+static void
+address_book_get_email_addresses_cb (EBook *book,
+ EBookStatus status,
+ EContact *contact,
+ gpointer closure)
+{
+ const gchar *id;
+ EmailsCallback callback;
+ gpointer user_data;
+
+ GList *addresses = NULL;
+
+/* g_print ("EContact is %p\n", contact); */
+
+ /* FIXME: This should NOT fail */
+ g_return_if_fail (contact != NULL);
+ g_return_if_fail (E_IS_CONTACT (contact));
+
+ if (status != E_BOOK_ERROR_OK) {
+ g_warning ("Could not get all emails, status is %d", status);
+ return;
+ }
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ callback = g_object_get_data (G_OBJECT (book), "callback");
+ user_data = g_object_get_data (G_OBJECT (book), "userdata");
+
+ g_print ("Getting address book email addresses for user ID:'%s'...", id);
+
+ addresses = e_contact_get (contact, E_CONTACT_EMAIL);
+
+ (callback) (id, addresses, user_data);
+
+ g_list_foreach (addresses, (GFunc) g_free, NULL);
+ g_list_free (addresses);
+
+ g_object_unref (book);
+}
+
+static void
+address_book_loaded_cb (EBook *book,
+ EBookStatus status,
+ gpointer closure)
+{
+ EBookContactCallback func;
+ const gchar *id;
+ guint result;
+
+ id = g_object_get_data (G_OBJECT (book), "id");
+ func = g_object_get_data (G_OBJECT (book), "func");
+
+ if (status != E_BOOK_ERROR_OK) {
+ g_warning ("Could not load book, status is %d", status);
+ return;
+ }
+
+ result = e_book_async_get_contact (book, id,
+ (EBookContactCallback) func,
+ NULL);
+
+ if (!result) {
+ g_warning ("Could not get contact:'%s', "
+ "e_book_async_get_contact() failed",
+ id);
+ return;
+ }
+}
+
+static gboolean
+address_book_get_names (const gchar *id,
+ NamesCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+
+ g_return_val_if_fail (id != NULL, FALSE);
+ g_return_val_if_fail (callback != NULL, FALSE);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ g_warning ("Couldn't get ebook");
+ return FALSE;
+ }
+
+ g_object_set_data_full (G_OBJECT (book), "id", g_strdup (id), g_free);
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book), "func", address_book_get_names_cb);
+
+ e_book_async_open (book, FALSE, (EBookCallback) address_book_loaded_cb, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+address_book_get_emails (const gchar *id,
+ EmailsCallback callback,
+ gpointer user_data)
+{
+ EBook *book;
+
+ g_return_val_if_fail (id != NULL, FALSE);
+ g_return_val_if_fail (callback != NULL, FALSE);
+
+ book = e_book_new_system_addressbook (NULL);
+ if (!book) {
+ g_warning ("Couldn't get ebook");
+ return FALSE;
+ }
+
+ g_object_set_data_full (G_OBJECT (book), "id", g_strdup (id), g_free);
+ g_object_set_data (G_OBJECT (book), "callback", callback);
+ g_object_set_data (G_OBJECT (book), "userdata", user_data);
+ g_object_set_data (G_OBJECT (book), "func", address_book_get_email_addresses_cb);
+
+ e_book_async_open (book, FALSE,
+ (EBookCallback) address_book_loaded_cb, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+address_book_get_owner (gchar **id)
+{
+ EBook *book;
+ EContact *contact;
+ GError *error = NULL;
+
+ g_return_val_if_fail (id != NULL, FALSE);
+
+ if (!e_book_get_self (&contact, &book, &error)) {
+ g_warning ("Could not get own contact details, %s",
+ error ? error->message : "");
+ g_clear_error (&error);
+
+ return FALSE;
+ }
+
+ *id = e_contact_get (contact, E_CONTACT_UID);
+
+ g_object_unref (contact);
+ g_object_unref (book);
+
+ return TRUE;
+}
+
+/*
+ * My callbacks.
+ */
+
+static void
+should_quit (void)
+{
+ if (have_names && have_email_addresses) {
+ g_main_loop_quit (main_loop);
+ }
+}
+
+static void
+get_names_cb (const gchar *id,
+ const gchar *given_name,
+ const gchar *family_name,
+ const gchar *full_name,
+ gpointer user_data)
+{
+ g_print ("<--- Found given name:'%s', family name:'%s', full name:'%s'\n",
+ given_name, family_name, full_name);
+
+ should_quit ();
+}
+
+static void
+get_email_addresses_cb (const gchar *id,
+ GList *addresses,
+ gpointer user_data)
+{
+ g_print ("<--- Found %d email addresses\n", g_list_length (addresses));
+
+ should_quit ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ gchar *id = NULL;
+
+ address_book_get_owner (&id);
+ if (!id) {
+ return EXIT_FAILURE;
+ }
+
+ g_print ("Address book owner has ID:'%s'\n", id);
+
+ address_book_get_emails (id, get_email_addresses_cb, NULL);
+ address_book_get_names (id, get_names_cb, NULL);
+
+ g_free (id);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ g_print ("Quitting...\n");
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tests.h b/tests/tests.h
new file mode 100644
index 0000000..5dc5df3
--- /dev/null
+++ b/tests/tests.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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: Martyn Russell <martyn@imendio.com>
+ */
+
+#include <check.h>
+
+#ifndef __TESTS_H__
+#define __TESTS_H__
+
+#include <check.h>
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <dapi-common.h>
+
+#include "dapi-command-bindings.h"
+
+DBusGProxy *tests_get_dbus_proxy (void);
+
+Suite * tests_create_addressbook_test_suite (void);
+
+#endif /* __TESTS_H__ */