diff options
author | Mikael Hallendal <micke@imendio.com> | 2006-12-01 11:56:38 +0000 |
---|---|---|
committer | Mikael Hallendal <micke@imendio.com> | 2006-12-01 11:56:38 +0000 |
commit | fbcbdb8ccfe5ea45555faf2733d2483ece7fc05b (patch) | |
tree | ab49543a8382c36a62a24e87a1de7da906cf4e19 | |
parent | e22c581532cb43042818fc4f3b149d561e0b9edf (diff) |
Moved the dapi_gnome into gnome subdir of dapi-dbus
31 files changed, 7101 insertions, 0 deletions
diff --git a/gnome/AUTHORS b/gnome/AUTHORS new file mode 100644 index 0000000..fa05488 --- /dev/null +++ b/gnome/AUTHORS @@ -0,0 +1,2 @@ +Martyn Russell <martyn@imendio.com> +Mikael Hallendal <micke@imendio.com> diff --git a/gnome/COPYING b/gnome/COPYING new file mode 100644 index 0000000..623b625 --- /dev/null +++ b/gnome/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/gnome/ChangeLog b/gnome/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gnome/ChangeLog diff --git a/gnome/ChangeLog-pre-0.2 b/gnome/ChangeLog-pre-0.2 new file mode 100644 index 0000000..cc52b8d --- /dev/null +++ b/gnome/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/gnome/INSTALL b/gnome/INSTALL new file mode 100644 index 0000000..23e5f25 --- /dev/null +++ b/gnome/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/gnome/Makefile.am b/gnome/Makefile.am new file mode 100644 index 0000000..139965a --- /dev/null +++ b/gnome/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = data src tests + diff --git a/gnome/NEWS b/gnome/NEWS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gnome/NEWS diff --git a/gnome/README b/gnome/README new file mode 100644 index 0000000..aa175ff --- /dev/null +++ b/gnome/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/gnome/TODO b/gnome/TODO new file mode 100644 index 0000000..1fa39c2 --- /dev/null +++ b/gnome/TODO @@ -0,0 +1,3 @@ +TODO: +===== + diff --git a/gnome/acinclude.m4 b/gnome/acinclude.m4 new file mode 100644 index 0000000..4f736e9 --- /dev/null +++ b/gnome/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, µ) != 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/gnome/autogen.sh b/gnome/autogen.sh new file mode 100755 index 0000000..9593d55 --- /dev/null +++ b/gnome/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/gnome/configure.ac b/gnome/configure.ac new file mode 100644 index 0000000..aa698ea --- /dev/null +++ b/gnome/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/gnome/data/Makefile.am b/gnome/data/Makefile.am new file mode 100644 index 0000000..7ead8bb --- /dev/null +++ b/gnome/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/gnome/data/dapi-command.xml b/gnome/data/dapi-command.xml new file mode 100644 index 0000000..2a5a42f --- /dev/null +++ b/gnome/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/gnome/data/dapi-common.h b/gnome/data/dapi-common.h new file mode 100644 index 0000000..b6d547d --- /dev/null +++ b/gnome/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/gnome/data/org.freedesktop.dapi.service.in b/gnome/data/org.freedesktop.dapi.service.in new file mode 100644 index 0000000..067bb70 --- /dev/null +++ b/gnome/data/org.freedesktop.dapi.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.freedesktop.dapi +Exec=@bindir@/dapi_gnome diff --git a/gnome/src/Makefile.am b/gnome/src/Makefile.am new file mode 100644 index 0000000..be9395d --- /dev/null +++ b/gnome/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/gnome/src/dapi-command.c b/gnome/src/dapi-command.c new file mode 100644 index 0000000..53e3ff2 --- /dev/null +++ b/gnome/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/gnome/src/dapi-command.h b/gnome/src/dapi-command.h new file mode 100644 index 0000000..3d2e9b6 --- /dev/null +++ b/gnome/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/gnome/src/dapi-daemon.c b/gnome/src/dapi-daemon.c new file mode 100644 index 0000000..8d37b44 --- /dev/null +++ b/gnome/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/gnome/src/dapi-debug.c b/gnome/src/dapi-debug.c new file mode 100644 index 0000000..6ac8c24 --- /dev/null +++ b/gnome/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/gnome/src/dapi-debug.h b/gnome/src/dapi-debug.h new file mode 100644 index 0000000..f863e76 --- /dev/null +++ b/gnome/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/gnome/src/dapi-gnome.c b/gnome/src/dapi-gnome.c new file mode 100644 index 0000000..631cc14 --- /dev/null +++ b/gnome/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/gnome/src/dapi-gnome.h b/gnome/src/dapi-gnome.h new file mode 100644 index 0000000..4292bda --- /dev/null +++ b/gnome/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/gnome/tests/Makefile.am b/gnome/tests/Makefile.am new file mode 100644 index 0000000..504cfc3 --- /dev/null +++ b/gnome/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/gnome/tests/README b/gnome/tests/README new file mode 100644 index 0000000..0b2d864 --- /dev/null +++ b/gnome/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/gnome/tests/test-addressbook.c b/gnome/tests/test-addressbook.c new file mode 100644 index 0000000..7b2cef8 --- /dev/null +++ b/gnome/tests/test-addressbook.c @@ -0,0 +1,400 @@ +/* -*- 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 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 +remove_known_test_contacts (void) +{ + DBusGProxy *proxy; + gchar **ids, **p; + gint count; + gboolean found; + gboolean success; + EBook *book; + GError *error = NULL; + + /* Remove the added test contact from the addressbook here */ + book = e_book_new_system_addressbook (NULL); + g_return_if_fail (book != NULL); + + proxy = tests_get_dbus_proxy (); + + /* Expected successes */ + success = org_freedesktop_dapi_address_book_find_by_name (proxy, CONTACT_FULL_NAME, &ids, NULL); + if (!success) { + return; + } + + /* Remove all found */ + 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; + } + + for (p = ids, found = FALSE, count = 0; + *p && !found; + p++, count++) { + success = e_book_remove_contact (book, *p, &error); + if (!success) { + g_warning ("Could not remove new contact with ID:'%s', %s", + *p, + error ? error->message : "no error given"); + g_clear_error (&error); + } else { + d(g_print ("Removed new contact with ID is '%s'\n", *p)); + } + } + + g_object_unref (book); +} + +static void +pre_test (void) +{ + EBook *book; + EContact *contact; + EBookChange *change; + GList *changes; + GError *error = NULL; + const gchar *str; + gboolean success; + + remove_known_test_contacts (); + + 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) +{ + remove_known_test_contacts (); + + g_free (new_contact_id); + 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/gnome/tests/test-api.c b/gnome/tests/test-api.c new file mode 100644 index 0000000..8b87efe --- /dev/null +++ b/gnome/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/gnome/tests/test-client.c b/gnome/tests/test-client.c new file mode 100644 index 0000000..2ac69f0 --- /dev/null +++ b/gnome/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/gnome/tests/test-ebook-async-get-contact.c b/gnome/tests/test-ebook-async-get-contact.c new file mode 100644 index 0000000..b283952 --- /dev/null +++ b/gnome/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/gnome/tests/tests.h b/gnome/tests/tests.h new file mode 100644 index 0000000..5dc5df3 --- /dev/null +++ b/gnome/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__ */ |