policykit-gnome r2 - in trunk: . data doc examples po polkit-gnome src tools



Author: davidz
Date: Fri Apr  4 07:02:43 2008
New Revision: 2
URL: http://svn.gnome.org/viewvc/policykit-gnome?rev=2&view=rev

Log:
Merge ../PolicyKit-gnome


Added:
   trunk/AUTHORS
   trunk/COPYING
   trunk/HACKING
   trunk/MAINTAINERS
   trunk/Makefile.am
   trunk/NEWS
   trunk/README
   trunk/TODO
   trunk/autogen.sh   (contents, props changed)
   trunk/configure.ac
   trunk/data/
   trunk/data/Makefile.am
   trunk/data/gnome-org.freedesktop.PolicyKit.AuthenticationAgent.service.in
   trunk/data/org.gnome.PolicyKit.AuthorizationManager.service.in
   trunk/data/org.gnome.PolicyKit.service.in
   trunk/data/polkit-gnome-authorization.desktop.in
   trunk/data/polkit-gnome.pc.in
   trunk/doc/
   trunk/doc/Makefile.am
   trunk/doc/auth-details.png
   trunk/doc/auth-retain-always.png
   trunk/doc/auth-retain-session.png
   trunk/doc/auth-root.png
   trunk/doc/auth-self.png
   trunk/doc/auth-wheel-group-1.png
   trunk/doc/auth-wheel-group-2.png
   trunk/doc/polkit-gnome-docs.xml
   trunk/doc/polkit-gnome-example-auth-dialog-twiddle.png
   trunk/doc/polkit-gnome-example-screenshot-authorized.png
   trunk/doc/polkit-gnome-example-screenshot.png
   trunk/doc/version.xml.in
   trunk/examples/
   trunk/examples/Makefile.am
   trunk/examples/polkit-gnome-example.c
   trunk/examples/polkit-gnome-example.policy.in
   trunk/gtk-doc.make
   trunk/po/
   trunk/po/ChangeLog
   trunk/po/LINGUAS
   trunk/po/POTFILES.in
   trunk/po/da.po
   trunk/polkit-gnome/
   trunk/polkit-gnome/Makefile.am
   trunk/polkit-gnome/polkit-gnome-action.c
   trunk/polkit-gnome/polkit-gnome-action.h
   trunk/polkit-gnome/polkit-gnome-auth.c
   trunk/polkit-gnome/polkit-gnome-auth.h
   trunk/polkit-gnome/polkit-gnome-context.c
   trunk/polkit-gnome/polkit-gnome-context.h
   trunk/polkit-gnome/polkit-gnome-toggle-action.c
   trunk/polkit-gnome/polkit-gnome-toggle-action.h
   trunk/polkit-gnome/polkit-gnome.h
   trunk/src/
   trunk/src/Makefile.am
   trunk/src/inotify_local.h
   trunk/src/main.c
   trunk/src/polkit-gnome-auth-dialog.c
   trunk/src/polkit-gnome-auth-dialog.h
   trunk/src/polkit-gnome-manager.c
   trunk/src/polkit-gnome-manager.h
   trunk/src/polkit-gnome-manager.xml
   trunk/tools/
   trunk/tools/Makefile.am
   trunk/tools/polkit-gnome-authorization.c
   trunk/tools/single-instance.xml

Added: trunk/AUTHORS
==============================================================================
--- (empty file)
+++ trunk/AUTHORS	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,2 @@
+David Zeuthen <davidz redhat com>
+

Added: trunk/COPYING
==============================================================================
--- (empty file)
+++ trunk/COPYING	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,838 @@
+
+The polkit-gnome library (polkit-gnome/*) is licensed to you under the
+GNU Lesser General Public License version 2 or later. The PolicyKit
+GNOME authentication D-Bus service (src/*) is licensed to you under
+the GNU General Public License version 2 or later.
+
+Both licenses are included here. Each source code file is marked with
+the proper copyright and license information.
+
+-- GPL BEGIN --
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  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) 19yy  <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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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) 19yy 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.
+
+-- GPL END --
+
+-- LGPL BEGIN --
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, 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 library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, 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 companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, 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 library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+  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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+  If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  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.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+  9. 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 Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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.
+
+  11. 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 Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  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 library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the 
+    Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
+    Boston, MA  02111-1307  USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+-- LGPL END --

Added: trunk/HACKING
==============================================================================
--- (empty file)
+++ trunk/HACKING	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,85 @@
+SCM (will be moved to GNOME SVN at some point)
+==============================================
+
+ - anonymous checkouts
+
+   $ git clone git://people.freedesktop.org/~david/PolicyKit-gnome
+
+ - commit to local repository
+
+   $ git commit -a
+
+ - pull changes from master repository at fd.o
+
+   $ git pull
+
+ - diff of working tree versus local repository
+
+   $ git diff
+
+ - diff of local repository vs. master repository at fd.o
+
+   synchronize with upstream repo:
+   $ git pull
+
+   (possibly merge changes)
+
+   generate the diff:
+   $ git diff origin HEAD
+
+ - influential environment variables (set these in e.g. .bash_profile)
+
+   export GIT_AUTHOR_NAME='Your Full Name'
+   export GIT_COMMITTER_NAME='Your Full Name'
+   export GIT_COMMITTER_EMAIL=youremail domain net
+   export GIT_AUTHOR_EMAIL=youremail domain net
+
+ - see also
+
+    http://www.kernel.org/pub/software/scm/git/docs/
+
+
+Committing code
+===
+
+ - Commit messages should be of the form (the five lines between the
+   lines starting with ===)
+
+=== begin example commit ===
+short explanation of the commit
+
+Longer explanation explaining exactly what's changed, whether any
+external or private interfaces changed, what bugs were fixed (with bug
+tracker reference if applicable) and so forth. Be concise but not too brief.
+=== end example commit ===
+
+ - Always add a brief description of the commit to the _first_ line of
+   the commit and terminate by two newlines (it will work without the
+   second newline, but that is not nice for the interfaces). 
+
+ - First line (the brief description) must only be one sentence and
+   must not start with a capital letter. Don't use a trailing period
+   either.
+
+ - The main description (the body) is normal prose and should use normal
+   punctuation and capital letters where appropriate. Normally, for patches
+   sent to a mailing list it's copied from there.
+
+ - When committing code on behalf of others use the --author option, e.g.
+   git commit -a --author "Joe Coder <joe coder org>"
+
+Coding Style
+===
+
+ - Please follow the coding style already used - it's not a must, but it's
+   nice to have consistency.
+
+ - Write docs for all functions and structs and so on. We use gtkdoc format.
+
+ - All external interfaces (network protocols, file formats, etc.)
+   should have documented specifications sufficient to allow an
+   alternative implementation to be written. Our implementation should
+   be strict about specification compliance (should not for example
+   heuristically parse a file and accept not-well-formed
+   data). Avoiding heuristics is also important for security reasons;
+   if it looks funny, ignore it (or exit, or disconnect).

Added: trunk/MAINTAINERS
==============================================================================
--- (empty file)
+++ trunk/MAINTAINERS	Fri Apr  4 07:02:43 2008
@@ -0,0 +1 @@
+David Zeuthen <davidz redhat com>

Added: trunk/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,45 @@
+SUBDIRS = data src polkit-gnome tools
+
+if BUILD_EXAMPLES
+SUBDIRS += examples
+endif
+
+# Need to build docs after examples because the docs include generated files 
+SUBDIRS += doc po
+
+# Creating ChangeLog from git log (taken from cairo/Makefile.am):
+ChangeLog: $(srcdir)/ChangeLog
+
+$(srcdir)/ChangeLog:
+	@if test -d "$(srcdir)/.git"; then \
+	  (cd "$(srcdir)" && \
+	  ./missing --run git-log --stat) | fmt --split-only > $  tmp \
+	  && mv -f $  tmp $@ \
+	  || ($(RM) $  tmp; \
+	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
+	      (test -f $@ || echo git-log is required to generate this file >> $@)); \
+	else \
+	  test -f $@ || \
+	  (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
+	  echo A git checkout and git-log is required to generate this file >> $@); \
+	fi
+
+.PHONY: ChangeLog $(srcdir)/ChangeLog
+
+
+EXTRA_DIST = \
+	autogen.sh		\
+	intltool-extract.in	\
+	intltool-merge.in	\
+	intltool-update.in	\
+	TODO			\
+	HACKING			\
+	ChangeLog
+
+DISTCLEANFILES = \
+	intltool-extract	\
+	intltool-merge		\
+	intltool-update
+
+clean-local :
+	rm -f *~ po/*~

Added: trunk/NEWS
==============================================================================
--- (empty file)
+++ trunk/NEWS	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,211 @@
+==========
+PolicyKit-gnome 0.7
+==========
+
+Released on December 5th 2007.
+
+This is the fifth release of PolicyKit-gnome.
+
+Highlights of this release
+
+ o  Also listen on the new desktop-neutral session bus interface as
+    defined by PolicyKit
+    http://hal.freedesktop.org/docs/PolicyKit/model-authentication-agent.html
+
+ o  New libpolkit-gnome library with lots of cool features
+
+ o  New polkit-gnome-authorizations tool for managing authorizations
+
+ o  Support for vendor name, site and icon. The icon will be blended over
+    the south-east quarter of the lock icon
+
+ o  Various bug fixes
+
+David Zeuthen (65):
+      post-release version bump
+      grab the pointer and keyboard when showing an auth dialog
+      don't grab the X keyboard; only grab the X pointer
+      do grab the keyboard anyway
+      add infrastructure for building a library
+      forgot to add gtk-doc.make
+      first stab at subclassing GtkAction for the libpolkit-gnome library
+      add authentication convience function and make PolKitGnomeAction smarter
+      add a polkit_gnome_action_create_button() convenience method
+      remove functionality to pass the X11 XID in PolKitGnomeAction
+      pass XID for top-level of the widget that caused the ::activate signal
+      show labels in buttons created by polkit_gnome_action_create_button()
+      add signals for ::auth_start, ::auth_end on PolKitGnomeAction
+      make all setters of PolKitGnomeAction private
+      clean up the example, include it in inline docs and remove the helper
+      ref the PolKitAction when returning it as a property
+      in the example, unref the PolKitAction objects to plug memory leaks
+      require (unreleased) PolicyKit 0.7 instead of 0.5
+      update label for buttons created with polkit_gnome_action_create_button()
+      show an example of properties of PolKitGnomeAction can be overridden
+      also propagate the ::activate signal if PolicyKit says 'no'
+      update example
+      add support for the 'short-label' property in PolKitGnomeAction
+      add toolbar and menubar to the example
+      minor style / translation fixes for polkit-gnome-example
+      fixed some i18n issues with polkit-gnome-example
+      add documentation for the authentication daemon
+      add some warning flags from gcc and fix up some warnings
+      the auth daemon is not multi-threaded, no need to init threads
+      we don't use libgnome nor libgnomeui so don't check for it in configure.ac
+      separate library dependencies into separate pkg-config modules
+      clean TODO - yay, down to one single trivial entry
+      for PolKitGnomeAction define what happens if PolKitAction is set to NULL
+      assorted libpolkit-gnome fixes
+      fix description of the Kick actions in the example
+      add a "Manage Authorization" application
+      various fixed for PolKitGnomeAction
+      include png
+      new class PolKitGnomeToggleAction
+      include PolKitGnomeToggleAction and update a screenshot
+      use PolKitGnomeToggleAction in example
+      various work-in-progress bits for the authorization tool
+      update for recent changes on PolicyKit HEAD
+      add support for one-shot authorizations
+      update screenshots in docs
+      update to slightly modified iterator API in PolicyKit HEAD
+      update to gtk-doc.make to handle parallel builds
+      use a tree for the actions and their namespaces instead of a flat list
+      add support for grant, revoke and editing implicit authorizations
+      add notebook to avoid showing summary when an action isn't selected
+      add support for vendor and icon
+      pull in sexy and gnome-vfs for better presentation and handling of vendor url's
+      make auth dialog show a link to the auth manager and add a .desktop file
+      actually do single instance by refusing to run if we can't claim the Name
+      add support for negative auths
+      fix corner case for the toggle action
+      also claim the name org.freedesktop.PolicyKit.AuthenticationAgent
+      add support for "target-pid" property and streamline auth interface
+      fix up POLKIT_TYPE_GNOME_CONTEXT to be POLKIT_GNOME_TYPE_CONTEXT
+      update docs to reflect the interface switch from org.gnome to org.freedesktop
+      for negative auths, make the face bw to make the stop icon stand out
+      update to latest PolicyKit API changes
+      introduce new polkit-action-sufficient property
+      update for latest PolicyKit API changes
+      update NEWS file
+
+Requirements for PolicyKit-gnome 0.7
+
+ - PolicyKit        == 0.7
+ - GTK+             >= 2.12
+ - dbus             >= 1.0
+ - dbus-glib        >= 0.71
+ - gnome-vfs        >= 2.4
+ - libsexy          >= 0.1.11
+
+==========
+PolicyKit-gnome 0.6
+==========
+
+Released on October 11th 2007.
+
+This is the fourth release of PolicyKit-gnome. This release should be
+compatible with the PolicyKit-gnome 0.5 release.
+
+David Zeuthen (9):
+      post-release version bump
+      Revert "post-release version bump"
+      removed bogus aclocal.m4 file from repository
+      build example by default
+      post release bump to 0.6
+      fix heuristics for localizing PAM strings and support thinkfinger better
+      fix danish translations
+      exit authentication daemon after 30 seconds of inactivity
+      add a --no-exit option to polkit-gnome-manager
+
+Michael Biebl (1):
+      make it possible to build without the demo application
+
+Requirements for PolicyKit-gnome 0.6
+
+ - PolicyKit        == 0.6
+ - GTK+             >= 2.11 (2.10 will do if you don't build the demos)
+ - dbus             >= 1.0
+ - dbus-glib        >= 0.71
+ - libgnome         >= 2.14.0
+ - libgnome-ui      >= 2.14.0
+
+==========
+PolicyKit-gnome 0.5
+==========
+
+Released on August 31st 2007.
+
+This is the third release of PolicyKit-gnome. An incompatible change
+from the 0.4 release has been introduced; the signature of the method
+ShowDialog() has changed; it now takes an X11 window ID. Pass zero
+as the identifier if you don't have a window.
+
+David Zeuthen (12):
+      post-release version bump to version 0.5
+      fix up i18n framework and add Danish translations
+      fix make distcheck
+      put icons on buttons to signify whether the action is permitted
+      update to work with PolicyKit HEAD's support for <define_admin_auth/>
+      break the D-Bus by taking an X11 window ID
+      add en_CA translations
+      update to be compatible with PolicyKit HEAD
+      add an example of how annotations are used
+      update danish translations and remove en_CA translations
+      rename the session daemon from polkit-gnome to polkit-gnome-manager
+      update NEWS
+
+WARNING WARNING WARNING: do not use this software in a stable
+distribution; there are still security sensitive things that needs to
+be audited.
+
+Requirements for PolicyKit-gnome 0.5
+
+ - PolicyKit        == 0.5
+ - GTK+             >= 2.11
+ - dbus             >= 0.90
+ - dbus-glib        >= 0.71
+ - libgnome         >= 2.14.0
+ - libgnome-ui      >= 2.14.0
+
+==========
+PolicyKit-gnome 0.4
+==========
+
+Released on July 25th 2007.
+
+This is the second release of PolicyKit-gnome. 
+
+WARNING WARNING WARNING: do not use this software in a stable
+distribution; there are still security sensitive things that needs to
+be audited.
+
+Requirements for PolicyKit-gnome 0.4
+
+ - PolicyKit        == 0.4
+ - GTK+             >= 2.6
+ - dbus             >= 0.90
+ - dbus-glib        >= 0.71
+ - libgnome         >= 2.14.0
+ - libgnome-ui      >= 2.14.0
+
+==========
+PolicyKit-gnome 0.3
+==========
+
+Released on June 20th 2007.
+
+This is the first release of PolicyKit-gnome.
+
+WARNING WARNING WARNING: do not use this software in a stable
+distribution; there are still security sensitive things that needs to
+be audited.
+
+Requirements for PolicyKit-gnome 0.3
+
+ - PolicyKit        == 0.3
+ - GTK+             >= 2.6
+ - dbus             >= 0.90
+ - dbus-glib        >= 0.71
+ - libgnome         >= 2.14.0
+ - libgnome-ui      >= 2.14.0
+

Added: trunk/README
==============================================================================
--- (empty file)
+++ trunk/README	Fri Apr  4 07:02:43 2008
@@ -0,0 +1 @@
+TODO: write me

Added: trunk/TODO
==============================================================================
--- (empty file)
+++ trunk/TODO	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,3 @@
+
+ - Move the GNOME SVN (ticket ID [gnome.org #2863])
+

Added: trunk/autogen.sh
==============================================================================
--- (empty file)
+++ trunk/autogen.sh	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,20 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+PKG_NAME="PolicyKit-gnome"
+
+(test -f $srcdir/src/Makefile.am) || {
+    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+    echo " top-level $PKG_NAME directory"
+    exit 1
+}
+
+which gnome-autogen.sh || {
+    echo "You need to install gnome-common from the GNOME SVN repository"
+    exit 1
+}
+
+REQUIRED_AUTOMAKE_VERSION=1.9 USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh

Added: trunk/configure.ac
==============================================================================
--- (empty file)
+++ trunk/configure.ac	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,223 @@
+AC_INIT([PolicyKit-gnome],[0.8],[mailto:david fubar dk],[PolicyKit-gnome])
+
+AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 no-dist-gzip])
+
+AC_CONFIG_SRCDIR([src])
+AC_CONFIG_HEADERS([config.h])
+
+AM_MAINTAINER_MODE
+
+# libtool versioning - this applies to all libraries in this package
+#
+# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
+#
+LT_CURRENT=0
+LT_REVISION=0
+LT_AGE=0
+AC_SUBST(LT_CURRENT)
+AC_SUBST(LT_REVISION)
+AC_SUBST(LT_AGE)
+
+AC_PROG_CC
+AC_ISC_POSIX
+AC_HEADER_STDC
+AC_PROG_LIBTOOL
+
+#### gcc warning flags
+
+if test "x$GCC" = "xyes"; then
+  changequote(,)dnl
+  case " $CFLAGS " in
+  *[\ \	]-Wall[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wall" ;;
+  esac
+
+  case " $CFLAGS " in
+  *[\ \	]-Wchar-subscripts[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
+  esac
+
+  case " $CFLAGS " in
+  *[\ \	]-Wmissing-declarations[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
+  esac
+
+  case " $CFLAGS " in
+  *[\ \	]-Wnested-externs[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wnested-externs" ;;
+  esac
+
+  case " $CFLAGS " in
+  *[\ \	]-Wpointer-arith[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wpointer-arith" ;;
+  esac
+
+  case " $CFLAGS " in
+  *[\ \	]-Wcast-align[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wcast-align" ;;
+  esac
+
+  case " $CFLAGS " in
+  *[\ \	]-Wsign-compare[\ \	]*) ;;
+  *) CFLAGS="$CFLAGS -Wsign-compare" ;;
+  esac
+
+  if test "x$enable_ansi" = "xyes"; then
+    case " $CFLAGS " in
+    *[\ \	]-ansi[\ \	]*) ;;
+    *) CFLAGS="$CFLAGS -ansi" ;;
+    esac
+
+    case " $CFLAGS " in
+    *[\ \	]-D_POSIX_C_SOURCE*) ;;
+    *) CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199309L" ;;
+    esac
+
+    case " $CFLAGS " in
+    *[\ \	]-D_BSD_SOURCE[\ \	]*) ;;
+    *) CFLAGS="$CFLAGS -D_BSD_SOURCE" ;;
+    esac
+
+    case " $CFLAGS " in
+    *[\ \	]-pedantic[\ \	]*) ;;
+    *) CFLAGS="$CFLAGS -pedantic" ;;
+    esac
+  fi
+  if test x$enable_gcov = xyes; then
+    case " $CFLAGS " in
+    *[\ \	]-fprofile-arcs[\ \	]*) ;;
+    *) CFLAGS="$CFLAGS -fprofile-arcs" ;;
+    esac
+    case " $CFLAGS " in
+    *[\ \	]-ftest-coverage[\ \	]*) ;;
+    *) CFLAGS="$CFLAGS -ftest-coverage" ;;
+    esac
+
+    ## remove optimization
+    CFLAGS=`echo "$CFLAGS" | sed -e 's/-O[0-9]*//g'`
+  fi
+  changequote([,])dnl
+else
+  if test x$enable_gcov = xyes; then
+    AC_MSG_ERROR([--enable-gcov can only be used with gcc])
+  fi
+fi
+
+# *****
+# GNOME
+# *****
+
+GNOME_COMMON_INIT
+GNOME_DOC_INIT
+GNOME_DEBUG_CHECK
+GNOME_COMPILE_WARNINGS([maximum])
+GNOME_MAINTAINER_MODE_DEFINES
+
+AC_ARG_ENABLE(gtk-doc, AC_HELP_STRING([--enable-gtk-doc],
+  [use gtk-doc to build documentation [default=yes]]),,
+  enable_gtk_doc=yes)
+GTK_DOC_CHECK([1.3])
+
+# ***************************
+# Check for required packages
+# ***************************
+
+GTK_REQUIRED=2.12.0
+SEXY_REQUIRED=0.1.11
+GNOME_VFS_REQUIRED=2.4
+DBUS_GLIB_REQUIRED=0.71
+POLKIT_DBUS_REQUIRED=0.7
+POLKIT_GRANT_REQUIRED=0.7
+
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $GTK_REQUIRED)
+AC_SUBST(GTK_CFLAGS)
+AC_SUBST(GTK_LIBS)
+
+PKG_CHECK_MODULES(SEXY, libsexy >= $SEXY_REQUIRED)
+AC_SUBST(SEXY_CFLAGS)
+AC_SUBST(SEXY_LIBS)
+
+PKG_CHECK_MODULES(GNOME_VFS, gnome-vfs-2.0 >= $GNOME_VFS_REQUIRED)
+AC_SUBST(GNOME_VFS_CFLAGS)
+AC_SUBST(GNOME_VFS_LIBS)
+
+PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1 >= $DBUS_GLIB_REQUIRED)
+AC_SUBST(DBUS_GLIB_CFLAGS)
+AC_SUBST(DBUS_GLIB_LIBS)
+
+PKG_CHECK_MODULES(POLKIT_DBUS, polkit-dbus >= $POLKIT_DBUS_REQUIRED)
+AC_SUBST(POLKIT_DBUS_CFLAGS)
+AC_SUBST(POLKIT_DBUS_LIBS)
+
+PKG_CHECK_MODULES(POLKIT_GRANT, polkit-grant >= $POLKIT_GRANT_REQUIRED)
+AC_SUBST(POLKIT_GRANT_CFLAGS)
+AC_SUBST(POLKIT_GRANT_LIBS)
+
+AC_ARG_ENABLE([examples],
+              AC_HELP_STRING([--enable-examples], [Build the example programs]),,
+              [enable_examples=yes])
+
+AM_CONDITIONAL(BUILD_EXAMPLES, test "x$enable_examples" = "xyes")
+
+if test "x$enable_examples" = "xyes"; then
+    AC_CHECK_PROG([POLKIT_POLICY_FILE_VALIDATE],
+                  [polkit-policy-file-validate], [polkit-policy-file-validate])
+    if test -z "$POLKIT_POLICY_FILE_VALIDATE"; then
+        AC_MSG_ERROR([polkit-policy-file-validate not found])
+    fi
+fi
+
+# ********************
+# Internationalisation
+# ********************
+
+IT_PROG_INTLTOOL([0.35.0])
+
+GETTEXT_PACKAGE=PolicyKit-gnome
+AC_SUBST([GETTEXT_PACKAGE])
+AM_GLIB_GNU_GETTEXT
+AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain])
+
+# *************************************
+# *************************************
+
+AC_SUBST([AM_CPPFLAGS])
+AC_SUBST([AM_CFLAGS])
+AC_SUBST([AM_CXXFLAGS])
+AC_SUBST([AM_LDFLAGS])
+
+AC_CONFIG_FILES([
+Makefile
+data/Makefile
+data/polkit-gnome.pc
+examples/Makefile
+polkit-gnome/Makefile
+src/Makefile
+tools/Makefile
+doc/Makefile
+doc/version.xml
+po/Makefile.in
+])
+
+AC_OUTPUT
+
+echo "
+                  PolicyKit-gnome $VERSION
+                =======================
+
+        prefix:                     ${prefix}
+        libdir:                     ${libdir}
+        libexecdir:                 ${libexecdir}
+        bindir:                     ${bindir}
+        sbindir:                    ${sbindir}
+        datadir:                    ${datadir}
+        sysconfdir:                 ${sysconfdir}
+        localstatedir:              ${localstatedir}
+
+        compiler:                   ${CC}
+        cflags:                     ${CFLAGS}
+        cppflags:                   ${CPPFLAGS}
+
+        Maintainer mode:            ${USE_MAINTAINER_MODE}
+        Building api docs:          ${enable_gtk_doc}
+"

Added: trunk/data/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/data/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,30 @@
+
+ INTLTOOL_DESKTOP_RULE@
+desktopdir = $(datadir)/applications
+desktop_in_files = polkit-gnome-authorization.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+servicedir       = $(datadir)/dbus-1/services
+service_in_files = org.gnome.PolicyKit.service.in                                  \
+		   org.gnome.PolicyKit.AuthorizationManager.service.in             \
+		   gnome-org.freedesktop.PolicyKit.AuthenticationAgent.service.in
+service_DATA     = $(service_in_files:.service.in=.service)
+
+org.gnome.PolicyKit.service : org.gnome.PolicyKit.service.in Makefile
+	@sed -e "s|\ libexecdir\@|$(libexecdir)|" $< > $@
+
+gnome-org.freedesktop.PolicyKit.AuthenticationAgent.service : gnome-org.freedesktop.PolicyKit.AuthenticationAgent.service.in Makefile
+	@sed -e "s|\ libexecdir\@|$(libexecdir)|" $< > $@
+
+org.gnome.PolicyKit.AuthorizationManager.service : org.gnome.PolicyKit.AuthorizationManager.service.in Makefile
+	@sed -e "s|\ bindir\@|$(bindir)|" $< > $@
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = polkit-gnome.pc
+
+DISTCLEANFILES = $(service_DATA) $(desktop_DATA) $(pkgconfig_DATA)
+
+EXTRA_DIST = $(service_in_files) $(desktop_in_files) polkit-gnome.pc.in
+
+clean-local :
+	rm -f *~ $(service_DATA) $(pkgconfig_DATA)

Added: trunk/data/gnome-org.freedesktop.PolicyKit.AuthenticationAgent.service.in
==============================================================================
--- (empty file)
+++ trunk/data/gnome-org.freedesktop.PolicyKit.AuthenticationAgent.service.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.PolicyKit.AuthenticationAgent
+Exec= libexecdir@/polkit-gnome-manager

Added: trunk/data/org.gnome.PolicyKit.AuthorizationManager.service.in
==============================================================================
--- (empty file)
+++ trunk/data/org.gnome.PolicyKit.AuthorizationManager.service.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.PolicyKit.AuthorizationManager
+Exec= bindir@/polkit-gnome-authorization

Added: trunk/data/org.gnome.PolicyKit.service.in
==============================================================================
--- (empty file)
+++ trunk/data/org.gnome.PolicyKit.service.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.PolicyKit
+Exec= libexecdir@/polkit-gnome-manager

Added: trunk/data/polkit-gnome-authorization.desktop.in
==============================================================================
--- (empty file)
+++ trunk/data/polkit-gnome-authorization.desktop.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Authorizations
+_Comment=Configure authorizations
+Icon=gtk-dialog-authentication
+Exec=polkit-gnome-authorization
+Terminal=false
+Type=Application
+Categories=Settings;X-GNOME-SystemSettings;
+OnlyShowIn=GNOME;
+StartupNotify=true

Added: trunk/data/polkit-gnome.pc.in
==============================================================================
--- (empty file)
+++ trunk/data/polkit-gnome.pc.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,11 @@
+prefix= prefix@
+exec_prefix= exec_prefix@
+libdir= libdir@
+includedir= includedir@
+
+Name: polkit-gnome
+Description: PolicyKit add-on library for GNOME
+Version: @VERSION@
+Requires: polkit polkit-dbus polkit-grant gtk+-2.0
+Libs: -L${libdir} -lpolkit-gnome
+Cflags: -I${includedir}/PolicyKit

Added: trunk/doc/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/doc/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,83 @@
+## Process this file with automake to create Makefile.in.
+
+NULL =
+
+AUTOMAKE_OPTIONS = 1.7
+
+# The name of the module.
+DOC_MODULE=polkit-gnome
+
+# The top-level SGML file.
+DOC_MAIN_SGML_FILE=polkit-gnome-docs.xml
+
+# Extra options to supply to gtkdoc-scan
+SCAN_OPTIONS=--ignore-headers=config.h
+
+# The directory containing the source code. Relative to $(srcdir)
+DOC_SOURCE_DIR=../polkit-gnome
+
+# Used for dependencies
+HFILE_GLOB=$(top_srcdir)/polkit-gnome/*.h
+CFILE_GLOB=$(top_srcdir)/polkit-gnome/*.c
+
+# Headers to ignore
+IGNORE_HFILES= 	\
+	$(NULL)
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed
+# if $(DOC_MODULE).types is non-empty.
+INCLUDES = 				\
+	$(GTK_CFLAGS)			\
+	$(DBUS_GLIB_CFLAGS)		\
+	$(POLKIT_DBUS_CFLAGS)		\
+	$(POLKIT_GRANT_CFLAGS)		\
+	-I$(top_srcdir) 		\
+	-I$(top_builddir)		\
+	$(NULL)
+
+GTKDOC_LIBS = \
+	$(GTK_LIBS)					\
+	$(DBUS_GLIB_LIBS)				\
+	$(POLKIT_DBUS_LIBS)				\
+	$(POLKIT_GRANT_LIBS)				\
+	$(top_builddir)/polkit-gnome/libpolkit-gnome.la	\
+	$(NULL)
+
+# Extra options to supply to gtkdoc-mkdb
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-mktmpl
+MKTMPL_OPTIONS=
+
+# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE)
+content_files =  			    \
+	version.xml			    \
+	$(NULL)
+
+# Images to copy into HTML directory
+HTML_IMAGES = 						\
+	polkit-gnome-example-screenshot.png 		\
+	polkit-gnome-example-screenshot-authorized.png 	\
+	polkit-gnome-example-auth-dialog-twiddle.png	\
+	auth-details.png				\
+	auth-retain-always.png				\
+	auth-retain-session.png				\
+	auth-root.png					\
+	auth-self.png					\
+	auth-wheel-group-1.png				\
+	auth-wheel-group-2.png
+
+# Extra options to supply to gtkdoc-fixref
+FIXXREF_OPTIONS=
+
+MAINTAINERCLEANFILES =		\
+	*~			\
+	Makefile.in		\
+	polkit-gnome.types	\
+	polkit-gnome-*.txt	\
+	$(NULL)
+
+include $(top_srcdir)/gtk-doc.make
+
+# Version information for marking the documentation
+EXTRA_DIST += version.xml.in

Added: trunk/doc/auth-details.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-details.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/auth-retain-always.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-retain-always.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/auth-retain-session.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-retain-session.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/auth-root.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-root.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/auth-self.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-self.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/auth-wheel-group-1.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-wheel-group-1.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/auth-wheel-group-2.png
==============================================================================
Binary files (empty file) and trunk/doc/auth-wheel-group-2.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/polkit-gnome-docs.xml
==============================================================================
--- (empty file)
+++ trunk/doc/polkit-gnome-docs.xml	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,245 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
+<!ENTITY version SYSTEM "version.xml">
+]>
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude";>
+  <bookinfo>
+    <title>PolicyKit-gnome Library Reference Manual</title>
+    <releaseinfo>Version &version;</releaseinfo>
+    <authorgroup>
+      <author>
+	<firstname>David</firstname>
+	<surname>Zeuthen</surname>
+	<affiliation>
+	  <address>
+	    <email>david fubar dk</email>
+	  </address>
+	</affiliation>
+      </author>
+    </authorgroup>
+
+    <copyright>
+      <year>2007</year>
+      <holder>The PolicyKit-gnome Authors</holder>
+    </copyright>
+
+    <legalnotice>
+      <para>
+	Permission is granted to copy, distribute and/or modify this
+	document under the terms of the <citetitle>GNU Free
+	Documentation License</citetitle>, Version 1.1 or any later
+	version published by the Free Software Foundation with no
+	Invariant Sections, no Front-Cover Texts, and no Back-Cover
+	Texts. You may obtain a copy of the <citetitle>GNU Free
+	Documentation License</citetitle> from the Free Software
+	Foundation by visiting <ulink type="http"
+	url="http://www.fsf.org";>their Web site</ulink> or by writing
+	to:
+
+	<address>
+	  The Free Software Foundation, Inc.,
+	  <street>59 Temple Place</street> - Suite 330,
+	  <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>,
+	  <country>USA</country>
+	</address>
+      </para>
+
+      <para>
+	Many of the names used by companies to distinguish their
+	products and services are claimed as trademarks. Where those
+	names appear in any GNOME documentation, and those trademarks
+	are made aware to the members of the GNOME Documentation
+	Project, the names have been printed in caps or initial caps.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+  <reference id="ref-core">
+    <title>API Reference</title>
+    <partintro>
+      <para>
+	This part presents the class and function reference for the
+	PolicyKit-gnome library, <literal>libpolkit-gnome</literal>.
+      </para>
+    </partintro>
+    <xi:include href="xml/polkit-gnome-context.xml"/>
+    <xi:include href="xml/polkit-gnome-action.xml"/>
+    <xi:include href="xml/polkit-gnome-toggle-action.xml"/>
+    <xi:include href="xml/polkit-gnome-auth.xml"/>
+  </reference>
+
+  <reference id="ref-auth-daemon">
+    <title>Authentication Agent</title>
+    <partintro>
+      <para>
+	This part discusses the GNOME/GTK+ specific Authentication
+	Agent.
+      </para>
+    </partintro>
+
+    <refsect1 id="ref-auth-daemon-overview">
+      <title>Overview</title>
+      <para>
+        The PolicyKit model provides letting an user authenticate in
+        order to gain the privilege to let a Mechanism carry work out
+        related to a specific Action on the users behalf. In the
+        PolicyKit libraries, this functionality is programmatically
+        exposed in the PolKitGrant class. As it's tedious to use this
+        low-level functionality from a GTK+ or GNOME application, the
+        high-level functionality is wrapped in a D-Bus service
+        available on the session message bus. The way it works is that
+        when an application needs privileges, it can call into this
+        D-Bus service and an authentication dialog will appear. When
+        the user is done with the authentication dialog, the
+        application recieves a reply from the D-Bus containing a
+        boolean indicating whether the user gained the privilege or
+        not.
+      </para>
+    </refsect1>
+
+    <refsect1 id="ref-auth-daemon-overview-dbus">
+      <title>D-Bus interface</title>
+      <para>
+        The D-Bus service is available on the session message bus with
+        the
+        name <literal>org.freedesktop.PolicyKit.AuthenticationAgent</literal>
+        and exports a single object <literal>/</literal> that
+        implements the
+        interface <literal>org.freedesktop.PolicyKit.AuthenticationAgent</literal>. The
+        D-Bus introspection XML looks like this
+      </para>
+      <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; href="../src/polkit-gnome-manager.xml" parse="text"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
+      <para>
+        The <literal>ObtainAuthorization()</literal> method may throw
+        an exception if another client is currently using the service
+        to show an authentication dialog. In practice this should
+        never happen because the authentication daemon grabs the X11
+        keyboard and pointer thus preventing the user from activating
+        widgets in other applications that would lead to calling into
+        the <literal>ObtainAuthorization</literal> method.
+      </para>
+    </refsect1>
+
+    <refsect1 id="ref-auth-daemon-operation">
+      <title>Operation</title>
+      <para>
+        The authentication daemon uses
+        <literal>libpolkit-grant</literal> which in turn uses PAM for
+        authentication services (however, other authentication
+        back-ends can be plugged in as required). As such, a wide
+        range of authentication mechanisms are available.
+      </para>
+      <para>
+        The authentication daemon is using D-Bus activation and exits
+        after 30 seconds of inactivity. Thus the code implementing
+        this dialog only runs when necessary.
+      </para>
+    </refsect1>
+
+    <refsect1 id="ref-auth-daemon-ui-elements">
+      <title>UI elements</title>
+      <para>
+        The appearance of the authentication dialog depends on the
+        result from PolicyKit and also whether administrator
+        authentication is defined as "authenticate as the root user"
+        or "authenticate as one of the users from UNIX group wheel" or
+        however the PolicyKit library is configured (see
+        the <literal>PolicyKit.conf(5)</literal> manual page for
+        details). Note that some of the screenshots below were made on
+        a system set up to use
+        the <ulink url="http://thinkfinger.sourceforge.net/";><citetitle>ThinkFinger</citetitle></ulink>
+        PAM module.
+      </para>
+
+      <para>
+        The text shown in the authentication dialogs stems from the
+        PolicyKit <literal>.policy</literal> XML files residing
+        in <literal>/usr/share/PolicyKit/policy</literal> and is read
+        by the authentication daemon when an applications uses
+        the <literal>ShowDialog()</literal> method. Thus, what the
+        user sees is not under application control (e.g. it's not
+        passed from the application) which rules out a class of
+        attacks where applications are trying to fool the user into
+        gaining a privilege.
+      </para>
+
+      <para>
+        Authentication dialog where the user is asked to authenticate
+        as herself:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-self.png" format="PNG"/>
+      </para>
+      <para>
+        Authentication dialog where the user is asked to authenticate
+        as an administrative user and PolicyKit is configured to use
+        the root password for this:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-root.png" format="PNG"/>
+      </para>
+      <para>
+        Authentication dialog where the user is asked to authenticate
+        as an administrative user and PolicyKit is configured to use
+        the UNIX wheel group for this:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-wheel-group-1.png" format="PNG"/>
+      </para>
+      <para>
+        Same authentication dialog, showing drop down box where the
+        user can be selected:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-wheel-group-2.png" format="PNG"/>
+      </para>
+      <para>
+        Authentication dialog showing an Action where the privilege
+        can be retained indefinitely:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-retain-always.png" format="PNG"/>
+      </para>
+      <para>
+        Authentication dialog showing an Action where the privilege
+        can be retained only for the remainer of the desktop session:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-retain-session.png" format="PNG"/>
+      </para>
+      <para>
+        The details view detailing what Action is being asked for as
+        well as what application is requesting the authentication:
+      </para>
+      <para>
+        <inlinegraphic fileref="auth-details.png" format="PNG"/>
+      </para>
+    </refsect1>
+  
+  </reference>
+
+  <!-- License -->
+
+  <appendix id="license">
+    <title>License</title>
+    <para>
+      The polkit-gnome library (polkit-gnome/*) is licensed to you
+      under the GNU Lesser General Public License version 2 or
+      later. 
+    </para>
+    <para>
+      The PolicyKit GNOME authentication D-Bus service (src/*) is
+      licensed to you under the GNU General Public License version 2
+      or later.
+    </para>
+    <para>
+      Both licenses are included here. Some individual source code
+      files and/or binaries may be under the GPL only.
+    </para>
+    <para>
+      Each source code file is marked with the proper copyright
+      information.
+    </para>
+  </appendix>
+</book>

Added: trunk/doc/polkit-gnome-example-auth-dialog-twiddle.png
==============================================================================
Binary files (empty file) and trunk/doc/polkit-gnome-example-auth-dialog-twiddle.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/polkit-gnome-example-screenshot-authorized.png
==============================================================================
Binary files (empty file) and trunk/doc/polkit-gnome-example-screenshot-authorized.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/polkit-gnome-example-screenshot.png
==============================================================================
Binary files (empty file) and trunk/doc/polkit-gnome-example-screenshot.png	Fri Apr  4 07:02:43 2008 differ

Added: trunk/doc/version.xml.in
==============================================================================
--- (empty file)
+++ trunk/doc/version.xml.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1 @@
+ VERSION@

Added: trunk/examples/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/examples/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,51 @@
+
+bin_PROGRAMS = polkit-gnome-example
+
+polkit_gnome_example_SOURCES = 				\
+	polkit-gnome-example.c
+
+polkit_gnome_example_CPPFLAGS = 			\
+	-I$(top_srcdir)					\
+	-DLIBEXECDIR=\""$(libexecdir)"\"		\
+	-DDATADIR=\""$(pkgdatadir)"\"			\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
+	$(DISABLE_DEPRECATED)				\
+	$(AM_CPPFLAGS)
+
+polkit_gnome_example_CFLAGS = 			\
+	$(GTK_CFLAGS)				\
+	$(DBUS_GLIB_CFLAGS)			\
+	$(POLKIT_DBUS_CFLAGS)			\
+	$(WARN_CFLAGS)				\
+	$(AM_CFLAGS)
+
+polkit_gnome_example_LDFLAGS = 			\
+	$(AM_LDFLAGS)
+
+polkit_gnome_example_LDADD = 				\
+	$(GTK_LIBS)					\
+	$(DBUS_GLIB_LIBS)				\
+	$(POLKIT_DBUS_LIBS)				\
+	$(POLKIT_GRANT_LIBS)				\
+	$(INTLLIBS)					\
+	$(top_builddir)/polkit-gnome/libpolkit-gnome.la
+
+# PolicyKit action definitions for this example
+#
+polkit_policydir = $(datadir)/PolicyKit/policy
+dist_polkit_policy_DATA =  polkit-gnome-example.policy
+
+# You will need a recent intltool or the patch from this bug
+# http://bugzilla.gnome.org/show_bug.cgi?id=462312
+ INTLTOOL_POLICY_RULE@
+
+check:
+	$(POLKIT_POLICY_FILE_VALIDATE) $(dist_polkit_policy_DATA)
+
+EXTRA_DIST = polkit-gnome-example.policy.in
+
+CLEANFILES = $(BUILT_SOURCES)
+DISTCLEANFILES = polkit-gnome-example.policy
+
+clean-local :
+	rm -f *~

Added: trunk/examples/polkit-gnome-example.c
==============================================================================
--- (empty file)
+++ trunk/examples/polkit-gnome-example.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,452 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * polkit-gnome-example: Simple example showing how a GTK+ application
+ * can use PolicyKit.
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <polkit-gnome/polkit-gnome.h>
+
+static GtkWidget *toplevel_window;
+static PolKitGnomeContext *pkgc;
+
+static void 
+_button_toggled (GtkToggleButton *toggle_button, PolKitGnomeAction *action)
+{
+        g_debug ("in _button_toggled for action '%s'", gtk_action_get_name (GTK_ACTION (action)));
+}
+
+static void 
+_button_clicked (GtkToggleButton *toggle_button, PolKitGnomeAction *action)
+{
+        g_debug ("in _button_clicked for '%s'", gtk_action_get_name (GTK_ACTION (action)));
+}
+
+/* This function is called when the following two conditions are true
+ *
+ *  - the user clicks one of the buttons created via the method
+ *    polkit_gnome_action_create_button() (see main() below)
+ *
+ *  - For the PolKitAction associated with the button, PolicyKit
+ *    reports either 'no' or 'yes'.
+ *
+ *  In the event the user clicks a button and he is not privileged
+ *  (e.g. PolicyKit returns one of the 'auth' results) he will be
+ *  asked to authenticate; this all happens behind the scenes; the
+ *  application _only_ gets the ::activate signal on PolKitGnomeAction
+ *  instances when PolicyKit reports that the user is privileged.
+ *
+ *  Note that for action org.gnome.policykit.examples.tweak, the
+ *  corresponding PolKitGnomeAction is configured to be sensitive (see
+ *  main() below) even when PolicyKit reports 'no'. Hence we need to
+ *  handle that case too and we do that by popping up a dialog. Note
+ *  that this can only be triggered by adding a stanza like
+ *
+ *  <match action="org.gnome.policykit.examples.tweak">
+ *    <return result="no"/>
+ *  </match>
+ *
+ *  to the /etc/PolicyKit/PolicyKit.conf file.
+ */
+static void
+activate_polkit_gnome_action (PolKitGnomeAction *action, gpointer user_data)
+{
+        PolKitCaller *pk_caller;
+        PolKitAction *pk_action;
+        PolKitResult pk_result;
+        DBusError dbus_error;
+
+        if (strcmp (gtk_action_get_name (GTK_ACTION (action)), "toggle") == 0) {
+                /* we're not supposed to run actions when the
+                 * authorization is flipped.. we're supposed to make
+                 * some UI sensitive and de-sensitive.. (one use at least) */
+                g_debug ("toggled for '%s'", gtk_action_get_name (GTK_ACTION (action)));
+                return;
+        }
+
+        g_debug ("pretending to be the mechanism for action '%s'", gtk_action_get_name (GTK_ACTION (action)));
+
+        g_object_get (action, "polkit-action", &pk_action, NULL);
+        
+        dbus_error_init (&dbus_error);        
+        pk_caller = polkit_tracker_get_caller_from_pid (pkgc->pk_tracker, 
+                                                        getpid (),
+                                                        &dbus_error);
+        if (pk_caller == NULL) {
+                g_warning ("Cannot get PolKitCaller object for ourselves (pid=%d): %s: %s",
+                           getpid (), dbus_error.name, dbus_error.message);
+                dbus_error_free (&dbus_error);
+        } else {
+                /* note how we pass #TRUE to revoke_if_one_shot - this is because we're
+                 * pretending to be the mechanism
+                 */
+                pk_result = polkit_context_is_caller_authorized (pkgc->pk_context, 
+                                                                 pk_action, 
+                                                                 pk_caller,
+                                                                 TRUE,
+                                                                 NULL);
+                
+                polkit_caller_unref (pk_caller);
+        }
+
+        polkit_action_unref (pk_action);
+
+}
+
+static void
+activate_action (GtkAction *action, gpointer user_data)
+{
+        if (g_ascii_strcasecmp (gtk_action_get_name (action), "Quit") == 0) {
+                exit (0);
+        } else if (g_ascii_strcasecmp (gtk_action_get_name (action), "About") == 0) {
+                const char *authors[] = {
+                        "David Zeuthen <david fubar dk>",
+                        NULL};
+                const char *documenters[] = {
+                        "David Zeuthen <david fubar dk>",
+                        NULL};
+
+
+                gtk_show_about_dialog (NULL,
+                                       "version", VERSION,
+                                       "copyright", _("Copyright  2007 David Zeuthen"),
+                                       "website-label", _("PolicyKit-gnome Website"),
+                                       "website", "http://hal.freedesktop.org/docs/PolicyKit-gnome/";,
+                                       "program-name", _("PolicyKit-gnome demo"),
+                                       "comments", _("PolicyKit for the GNOME desktop"),
+                                       "logo-icon-name", GTK_STOCK_DIALOG_AUTHENTICATION,
+                                       "authors", authors,
+                                       "documenters", documenters,
+                                       NULL);
+
+        }
+}
+
+static GtkActionEntry entries[] = {
+        { "FileMenu", NULL, N_("_File") },               /* name, stock id, label */
+        { "ActionsMenu", NULL, N_("_Actions") },         /* name, stock id, label */
+        { "HelpMenu", NULL, N_("_Help") },               /* name, stock id, label */
+
+        { "Quit", GTK_STOCK_QUIT,                        /* name, stock id */
+          N_("_Quit"), "<control>Q",                     /* label, accelerator */     
+          N_("Quit"),                                    /* tooltip */
+          G_CALLBACK (activate_action) },
+
+        { "About", GTK_STOCK_ABOUT,                      /* name, stock id */
+          N_("_About"), "<control>A",                    /* label, accelerator */     
+          N_("About"),                                   /* tooltip */  
+          G_CALLBACK (activate_action) },
+};
+static guint n_entries = G_N_ELEMENTS (entries);
+
+static const gchar *ui_info = 
+"<ui>"
+"  <menubar name='MenuBar'>"
+"    <menu action='FileMenu'>"
+"      <menuitem action='Quit'/>"
+"    </menu>"
+"    <menu action='ActionsMenu'>"
+"      <menuitem action='frobnicate'/>"
+"      <menuitem action='jump'/>"
+"      <menuitem action='tweak'/>"
+"      <menuitem action='twiddle'/>"
+"      <menuitem action='punch'/>"
+"      <menuitem action='toggle'/>"
+"    </menu>"
+"    <menu action='HelpMenu'>"
+"      <menuitem action='About'/>"
+"    </menu>"
+"  </menubar>"
+"  <toolbar  name='ToolBar'>"
+"    <toolitem action='Quit'/>"
+"    <toolitem action='About'/>"
+"    <separator action='Sep1'/>"
+"    <toolitem action='frobnicate'/>"
+"    <toolitem action='jump'/>"
+"    <toolitem action='tweak'/>"
+"    <toolitem action='twiddle'/>"
+"    <toolitem action='punch'/>"
+"    <toolitem action='toggle'/>"
+"  </toolbar>"
+"</ui>";
+
+int
+main (int argc, char **argv)
+{
+        GtkWidget *hbox;
+        GtkWidget *vbox;
+        GtkWidget *vbox2;
+        GtkWidget *label;
+        GMainLoop*loop;
+        PolKitAction *pk_action;
+        PolKitGnomeAction *action;
+        GtkWidget *button;
+        GtkUIManager *ui;
+        GtkActionGroup *actions;
+
+        gtk_init (&argc, &argv);
+
+        pkgc = polkit_gnome_context_get (NULL);
+
+        loop = g_main_loop_new (NULL, FALSE);
+        
+        toplevel_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+        actions = gtk_action_group_new ("Actions");
+        gtk_action_group_add_actions (actions, entries, n_entries, NULL);
+
+        ui = gtk_ui_manager_new ();
+        gtk_ui_manager_insert_action_group (ui, actions, 0);
+
+        gtk_window_add_accel_group (GTK_WINDOW (toplevel_window), 
+                                    gtk_ui_manager_get_accel_group (ui));
+
+
+        gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, NULL);
+
+        /*----------------------------------------------------------------*/
+
+        vbox = gtk_vbox_new (FALSE, 10);
+        gtk_container_add (GTK_CONTAINER (toplevel_window), vbox);
+
+        vbox2 = gtk_vbox_new (FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
+
+        /*----------------------------------------------------------------*/
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Frobnicate</b> requires the "
+                                                   "user to authenticate. The authorization is kept for "
+                                                   "the life time of the process"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.frobnicate");
+        action = polkit_gnome_action_new_default ("frobnicate", pk_action, _("Frobnicate!"), NULL);
+        polkit_action_unref (pk_action);
+        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
+        gtk_action_group_add_action (actions, GTK_ACTION (action));
+        button = polkit_gnome_action_create_button (action);
+        gtk_box_pack_start (GTK_BOX (vbox), 
+                            button, 
+                            FALSE, FALSE, 0);
+        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);
+
+        /*----------------------------------------------------------------*/
+        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+        /*----------------------------------------------------------------*/
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Jump</b> requires the "
+                                                   "user to authenticate. This is a one-shot authorization."));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.jump");
+        action = polkit_gnome_action_new_default ("jump", pk_action, _("Jump!"), NULL);
+        polkit_action_unref (pk_action);
+        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
+        gtk_action_group_add_action (actions, GTK_ACTION (action));
+        button = polkit_gnome_action_create_button (action);
+        gtk_box_pack_start (GTK_BOX (vbox), 
+                            button, 
+                            FALSE, FALSE, 0);
+        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);
+
+        /*----------------------------------------------------------------*/
+        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+        /*----------------------------------------------------------------*/
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Tweak</b> requires a system "
+                                                   "administrator to authenticate. This instance "
+                                                   "overrides the defaults set in polkit_gnome_action_new()."));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.tweak");
+        action = polkit_gnome_action_new_default ("tweak", pk_action, _("Tweak!"), NULL);
+        polkit_action_unref (pk_action);
+
+        /* For this particular GtkAction instance, we want to customize the appearence */
+        g_object_set (action,
+                      "no-visible",       TRUE,
+                      "no-sensitive",     TRUE,
+                      "no-short-label",   _("Tweak"),
+                      "no-label",         _("Tweak (long)"),
+                      "no-tooltip",       _("If your admin wasn't annoying, you could do this"),
+                      "no-icon-name",     GTK_STOCK_NO,
+                      
+                      "auth-visible",     TRUE,
+                      "auth-sensitive",   TRUE,
+                      "auth-short-label", _("Tweak..."),
+                      "auth-label",       _("Tweak... (long)"),
+                      "auth-tooltip",     _("Only card carrying tweakers can do this!"),
+                      "auth-icon-name",   GTK_STOCK_DIALOG_AUTHENTICATION,
+                      
+                      "yes-visible",      TRUE,
+                      "yes-sensitive",    TRUE,
+                      "yes-short-label",  _("Tweak!"),
+                      "yes-label",        _("Tweak! (long)"),
+                      "yes-tooltip",      _("Go ahead, tweak tweak tweak!"),
+                      "yes-icon-name",    GTK_STOCK_YES,
+                      NULL);
+
+        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
+        gtk_action_group_add_action (actions, GTK_ACTION (action));
+        button = polkit_gnome_action_create_button (action);
+        gtk_box_pack_start (GTK_BOX (vbox), 
+                            button, 
+                            FALSE, FALSE, 0);
+        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);
+
+        /*----------------------------------------------------------------*/
+        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+        /*----------------------------------------------------------------*/
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Twiddle</b> requires a system "
+                                                   "administrator to authenticate. Once authenticated, this "
+                                                   "privilege can be retained indefinitely."));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.twiddle");
+        action = polkit_gnome_action_new_default ("twiddle", pk_action, _("Twiddle!"), NULL);
+        polkit_action_unref (pk_action);
+        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
+        gtk_action_group_add_action (actions, GTK_ACTION (action));
+        button = polkit_gnome_action_create_button (action);
+        gtk_box_pack_start (GTK_BOX (vbox), 
+                            button, 
+                            FALSE, FALSE, 0);
+        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);
+
+        /*----------------------------------------------------------------*/
+        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+        /*----------------------------------------------------------------*/
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Punch</b> requires the user to "
+                                                   "authenticate. Once authenticated, this privilege can "
+                                                   "be retained for the remainder of the desktop session."));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.punch");
+        action = polkit_gnome_action_new_default ("punch", pk_action, _("Punch!"), NULL);
+        polkit_action_unref (pk_action);
+        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
+        gtk_action_group_add_action (actions, GTK_ACTION (action));
+        button = polkit_gnome_action_create_button (action);
+        gtk_box_pack_start (GTK_BOX (vbox), 
+                            polkit_gnome_action_create_button (action), 
+                            FALSE, FALSE, 0);
+        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);
+
+        /*----------------------------------------------------------------*/
+        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+        /*----------------------------------------------------------------*/
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("The <b>Toggle</b> action demonstrates the use of "
+                                                   "PolicyKit to drive a GtkToggleButton; it's an intuitive "
+                                                   "way to ask users to give up authorizations when they "
+                                                   "are done with them. E.g. the button is 'pressed in' exactly"
+                                                   "when the authorization is held. Toggling the button means "
+                                                   "obtaining resp. revoking the authorization in question."));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.toggle");
+        PolKitGnomeToggleAction *toggle_action;
+        toggle_action = polkit_gnome_toggle_action_new_default ("toggle", pk_action, 
+                                                                _("Click to make changes..."),
+                                                                _("Click to prevent changes"));
+        //g_object_set (toggle_action, "target-pid", 24887, NULL);
+        polkit_action_unref (pk_action);
+        g_signal_connect (toggle_action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
+        gtk_action_group_add_action (actions, GTK_ACTION (toggle_action));
+        GtkWidget *toggle_button;
+        toggle_button = polkit_gnome_toggle_action_create_toggle_button (toggle_action);
+        g_signal_connect (toggle_button, "toggled", G_CALLBACK (_button_toggled), toggle_action);
+        gtk_box_pack_start (GTK_BOX (vbox), 
+                            toggle_button, 
+                            FALSE, FALSE, 0);
+
+        /*----------------------------------------------------------------*/
+        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+        /*----------------------------------------------------------------*/
+
+        hbox = gtk_hbox_new (FALSE, 5);
+        gtk_box_pack_start (GTK_BOX (hbox), gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, 
+                                                                      GTK_ICON_SIZE_SMALL_TOOLBAR), FALSE, FALSE, 0);
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<i>Tip: try editing /etc/PolicyKit/Policy.conf and see the proxy widgets update in real-time.</i>."));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+        /*----------------------------------------------------------------*/
+
+        g_object_unref (actions);
+
+        gtk_box_pack_start (GTK_BOX (vbox2),
+                            gtk_ui_manager_get_widget (ui, "/MenuBar"),
+                            FALSE, FALSE, 0);
+
+        GtkWidget *toolbar;
+        toolbar = gtk_ui_manager_get_widget (ui, "/ToolBar");
+        gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);
+        gtk_box_pack_start (GTK_BOX (vbox2),
+                            toolbar,
+                            FALSE, FALSE, 0);
+
+        /*----------------------------------------------------------------*/
+
+        gtk_window_set_default_size (GTK_WINDOW (toplevel_window), 700, 0);
+        gtk_window_set_title (GTK_WINDOW (toplevel_window), _("PolicyKit-gnome demo"));
+        g_signal_connect (toplevel_window, "delete-event", (GCallback) exit, NULL);
+        gtk_widget_show_all (toplevel_window);
+
+        g_main_loop_run (loop);
+        return 0;
+}

Added: trunk/examples/polkit-gnome-example.policy.in
==============================================================================
--- (empty file)
+++ trunk/examples/polkit-gnome-example.policy.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd";>
+
+<!-- 
+Policy definitions for PolicyKit-Gnome example
+
+Copyright (c) 2007 David Zeuthen <david fubar dk>
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+
+  <action id="org.gnome.policykit.examples.jump">
+    <_description>Jump</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Jumping</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self_one_shot</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.gnome.policykit.examples.frobnicate">
+    <_description>Frobnicate</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Frobnicating</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self</allow_active>
+    </defaults>
+  </action>
+  
+  <action id="org.gnome.policykit.examples.tweak">
+    <_description>Tweak</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Tweaking</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin</allow_active>
+    </defaults>
+  </action>
+  
+  <action id="org.gnome.policykit.examples.twiddle">
+    <_description>Twiddle</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Twiddling</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep_always</allow_active>
+    </defaults>
+  </action>
+  
+  <action id="org.gnome.policykit.examples.punch">
+    <_description>Punch</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Punching</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self_keep_session</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.gnome.policykit.examples.toggle">
+    <_description>Toggle</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Toggling</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep_always</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.gnome.policykit.examples.kick-foo">
+    <_description>Kick foo</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Kicking foo</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self</allow_active>
+    </defaults>
+    <annotate key="org.gnome.policykit.examples.kick-path">foo</annotate>
+  </action>
+
+  <action id="org.gnome.policykit.examples.kick-bar">
+    <_description>Kick bar</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Kicking bar</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self</allow_active>
+    </defaults>
+    <annotate key="org.gnome.policykit.examples.kick-path">bar</annotate>
+  </action>
+
+  <action id="org.gnome.policykit.examples.kick-baz">
+    <_description>Kick baz</_description>
+    <_message>System policy prevents the PolicyKit-gnome example helper from Kicking baz</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self</allow_active>
+    </defaults>
+    <annotate key="org.gnome.policykit.examples.kick-path">baz</annotate>
+  </action>
+
+</policyconfig>

Added: trunk/gtk-doc.make
==============================================================================
--- (empty file)
+++ trunk/gtk-doc.make	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,159 @@
+# -*- mode: makefile -*-
+
+####################################
+# Everything below here is generic #
+####################################
+
+if GTK_DOC_USE_LIBTOOL
+GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS)
+else
+GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS)
+endif
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH, when it comes to
+# whether a source that is a target of one rule is then
+# searched for in VPATH/GPATH.
+#
+GPATH = $(srcdir)
+
+TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
+
+EXTRA_DIST = 				\
+	$(content_files)		\
+	$(HTML_IMAGES)			\
+	$(DOC_MAIN_SGML_FILE)		\
+	$(DOC_MODULE)-sections.txt	\
+	$(DOC_MODULE)-overrides.txt
+
+DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \
+	   $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp
+
+SCANOBJ_FILES = 		 \
+	$(DOC_MODULE).args 	 \
+	$(DOC_MODULE).hierarchy  \
+	$(DOC_MODULE).interfaces \
+	$(DOC_MODULE).prerequisites \
+	$(DOC_MODULE).signals
+
+CLEANFILES = $(SCANOBJ_FILES) $(DOC_MODULE)-unused.txt $(DOC_STAMPS)
+
+if ENABLE_GTK_DOC
+all-local: html-build.stamp
+else
+all-local:
+endif
+
+docs: html-build.stamp
+
+#### scan ####
+
+scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
+	@echo 'gtk-doc: Scanning header files'
+	@-chmod -R u+w $(srcdir)
+	cd $(srcdir) && \
+	  gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES)
+	if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
+	    CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" CFLAGS="$(GTKDOC_CFLAGS)" LDFLAGS="$(GTKDOC_LIBS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
+	else \
+	    cd $(srcdir) ; \
+	    for i in $(SCANOBJ_FILES) ; do \
+               test -f $$i || touch $$i ; \
+	    done \
+	fi
+	touch scan-build.stamp
+
+$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
+	@true
+
+#### templates ####
+
+tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
+	@echo 'gtk-doc: Rebuilding template files'
+	@-chmod -R u+w $(srcdir)
+	cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS)
+	touch tmpl-build.stamp
+
+tmpl.stamp: tmpl-build.stamp
+	@true
+
+tmpl/*.sgml:
+	@true
+
+
+#### xml ####
+
+sgml-build.stamp: tmpl.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files)
+	@echo 'gtk-doc: Building XML'
+	@-chmod -R u+w $(srcdir)
+	cd $(srcdir) && \
+	gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS)
+	touch sgml-build.stamp
+
+sgml.stamp: sgml-build.stamp
+	@true
+
+#### html ####
+
+html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files)
+	@echo 'gtk-doc: Building HTML'
+	@-chmod -R u+w $(srcdir)
+	rm -rf $(srcdir)/html 
+	mkdir $(srcdir)/html
+	cd $(srcdir)/html && gtkdoc-mkhtml $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+	test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html )
+	@echo 'gtk-doc: Fixing cross-references' 
+	cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
+	touch html-build.stamp
+
+##############
+
+clean-local:
+	rm -f *~ *.bak
+	rm -rf .libs
+
+maintainer-clean-local: clean
+	cd $(srcdir) && rm -rf xml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+
+install-data-local:
+	installfiles=`echo $(srcdir)/html/*`; \
+	if test "$$installfiles" = '$(srcdir)/html/*'; \
+	then echo '-- Nothing to install' ; \
+	else \
+	  $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \
+	  for i in $$installfiles; do \
+	    echo '-- Installing '$$i ; \
+	    $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \
+	  done; \
+	  echo '-- Installing $(srcdir)/html/index.sgml' ; \
+	  $(INSTALL_DATA) $(srcdir)/html/index.sgml $(DESTDIR)$(TARGET_DIR) || :; \
+	fi
+
+uninstall-local:
+	rm -f $(DESTDIR)$(TARGET_DIR)/*
+
+#
+# Require gtk-doc when making dist
+#
+if ENABLE_GTK_DOC
+dist-check-gtkdoc:
+else
+dist-check-gtkdoc:
+	@echo "*** gtk-doc must be installed and enabled in order to make dist"
+	@false
+endif
+
+dist-hook: dist-check-gtkdoc dist-hook-local
+	mkdir $(distdir)/tmpl
+	mkdir $(distdir)/xml
+	mkdir $(distdir)/html
+	-cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl
+	-cp $(srcdir)/xml/*.xml $(distdir)/xml
+	cp $(srcdir)/html/* $(distdir)/html
+	if test -f $(srcdir)/$(DOC_MODULE).types; then \
+	  cp $(srcdir)/$(DOC_MODULE).types $(distdir)/$(DOC_MODULE).types; \
+	fi
+
+.PHONY : dist-hook-local docs

Added: trunk/po/LINGUAS
==============================================================================
--- (empty file)
+++ trunk/po/LINGUAS	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,4 @@
+# please keep this list sorted alphabetically
+#
+da
+

Added: trunk/po/POTFILES.in
==============================================================================
--- (empty file)
+++ trunk/po/POTFILES.in	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,14 @@
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+[encoding: UTF-8]
+data/polkit-gnome-authorization.desktop.in
+examples/polkit-gnome-example.c
+examples/polkit-gnome-example.policy.in
+polkit-gnome/polkit-gnome-action.c
+polkit-gnome/polkit-gnome-auth.c
+polkit-gnome/polkit-gnome-context.c
+polkit-gnome/polkit-gnome-toggle-action.c
+src/main.c
+src/polkit-gnome-auth-dialog.c
+src/polkit-gnome-manager.c
+tools/polkit-gnome-authorization.c

Added: trunk/polkit-gnome/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,51 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+	-I$(top_builddir) -I$(top_srcdir) \
+	-DPACKAGE_LIBEXECDIR=\""$(libexecdir)"\" \
+	-DPACKAGE_SYSCONFDIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATADIR=\""$(datadir)"\" \
+	-DPACKAGE_BINDIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DPACKAGE_LOCALEDIR=\""$(localedir)"\" \
+	-DPACKAGE_LIBDIR=\""$(libdir)"\" \
+	-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT	\
+	-DPOLKIT_GNOME_COMPILATION
+
+lib_LTLIBRARIES=libpolkit-gnome.la
+
+libpolkit_gnomeincludedir=$(includedir)/PolicyKit/polkit-gnome
+
+libpolkit_gnomeinclude_HEADERS =              				\
+	polkit-gnome.h							\
+	polkit-gnome-context.h						\
+	polkit-gnome-action.h						\
+	polkit-gnome-toggle-action.h					\
+	polkit-gnome-auth.h
+
+libpolkit_gnome_la_SOURCES =                                		\
+	polkit-gnome-context.h		polkit-gnome-context.c		\
+	polkit-gnome-action.h		polkit-gnome-action.c		\
+	polkit-gnome-toggle-action.h	polkit-gnome-toggle-action.c	\
+	polkit-gnome-auth.h		polkit-gnome-auth.c
+
+libpolkit_gnome_la_CFLAGS = 	\
+	$(GTK_CFLAGS)		\
+	$(DBUS_GLIB_CFLAGS)	\
+	$(POLKIT_DBUS_CFLAGS)	\
+	$(POLKIT_GRANT_CFLAGS)	\
+	$(WARN_CFLAGS)		\
+	$(AM_CFLAGS)
+
+libpolkit_gnome_la_LIBADD = 	\
+	$(GTK_LIBS)		\
+	$(DBUS_GLIB_LIBS)	\
+	$(POLKIT_DBUS_LIBS)	\
+	$(POLKIT_GRANT_LIBS)	\
+	$(INTLLIBS)
+
+libpolkit_gnome_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+
+clean-local :
+	rm -f *~ $(BUILT_SOURCES)
+

Added: trunk/polkit-gnome/polkit-gnome-action.c
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-action.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,2125 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-action.c : 
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+#include "polkit-gnome-context.h"
+#include "polkit-gnome-action.h"
+#include "polkit-gnome-auth.h"
+
+/**
+ * SECTION:polkit-gnome-action
+ * @short_description: A GtkAction subclass where instances can be tied to a specific PolicyKit action.
+ *
+ * Actions in GTK+ represent operations that the user can be perform,
+ * along with some information how it should be presented in the
+ * interface. Each action provides methods to create icons, menu items
+ * and toolbar items representing itself. Each action can have one or
+ * more proxy menu item, toolbar button or other proxy
+ * widgets. Proxies mirror the state of the action (text label,
+ * tooltip, icon, visible, sensitive, etc), and should change when the
+ * action's state changes. When the proxy is activated, it should
+ * activate its action.
+ *
+ * Instances of #PolKitGnomeAction class updates the label, tooltip,
+ * icon-name, visible and properties of the parent #GtkAction instance
+ * according to what result PolicyKit gives about a given
+ * #PolKitAction object. The #PolKitGnomeContext class is used
+ * internally to track changes. This means that external events (such
+ * as the editing of the /etc/PolicyKit/PolicyKit.conf file,
+ * ConsoleKit session activity changes or if the user gains a
+ * privilege via authentication) will trigger the action, and thus
+ * connected proxy widgets, to be updated.
+ *
+ * In addition, the #PolKitGnomeAction class intercepts the ::activate
+ * signal defined in #GtkAction. When the result from PolicyKit is
+ * yes, the signal is propagated. If the result is auth,
+ * polkit_gnome_auth_show_dialog() will be used to bring up an
+ * authentication dialog for the given #PolKitAction. If the user
+ * succesfully gained the privilege, a ::activate signal will be
+ * synthesized. If the result is no, the signal is also propagated.
+ *
+ * As a result, everything happens under the covers; the application
+ * programmer using #PolKitGnomeAction will only get the ::activate
+ * signal when the answer from PolicyKit is yes and as such don't have
+ * to worry about bringing up authentication dialogs if the property
+ * "no-sensitive" is set to #FALSE.
+ *
+ * When an authentication dialog is show, the #PolKitGnomeAction class
+ * will pass the XID of the top-level window that the proxy widget
+ * causing the activation to polkit_gnome_auth_show_dialog().
+ *
+ * An example of how to use #PolKitGnomeAction follows. First, build
+ * the following program
+ * 
+ * <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; href="../../examples/polkit-gnome-example.c" parse="text"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
+ *
+ * with
+ *
+ * <programlisting>gcc -o polkit-gnome-example `pkg-config --cflags --libs polkit-gnome` polkit-gnome-example.c</programlisting>
+ *
+ * Then, put the following content
+ *
+ * <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; href="../../examples/polkit-gnome-example.policy" parse="text"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
+ *
+ * into a file
+ * <literal>/usr/share/PolicyKit/policy/polkit-gnome-example.policy</literal>. Finally,
+ * run <literal>polkit-gnome-example</literal>. It should display a
+ * window like this:
+ *
+ * <inlinegraphic fileref="polkit-gnome-example-screenshot.png" format="PNG"/>
+ *
+ * If the "Twiddle!" button is pressed, an authentication dialog
+ * should pop up
+ *
+ * <inlinegraphic fileref="polkit-gnome-example-auth-dialog-twiddle.png" format="PNG"/>
+ *
+ * Here is how what the application looks like if the user gains
+ * authorization for all the actions:
+ *
+ * <inlinegraphic fileref="polkit-gnome-example-screenshot-authorized.png" format="PNG"/>
+ *
+ * Regarding how to build an example mechanism that this GTK+
+ * application can take advantage of, please refer to the
+ * #PolKitContext class for examples.
+ **/
+
+#define POLKIT_GNOME_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), POLKIT_GNOME_TYPE_ACTION, PolKitGnomeActionPrivate))
+
+static void polkit_gnome_action_activate (PolKitGnomeAction *action);
+static void _auth_start (PolKitGnomeAction *action);
+
+static void polkit_gnome_action_set_polkit_action         (PolKitGnomeAction *action, PolKitAction *pk_action);
+static void polkit_gnome_action_set_polkit_action_sufficient (PolKitGnomeAction *action, const GValue *pk_action_array);
+
+static void polkit_gnome_action_set_self_blocked_visible     (PolKitGnomeAction *action, gboolean visible);
+static void polkit_gnome_action_set_self_blocked_sensitive   (PolKitGnomeAction *action, gboolean sensitive);
+static void polkit_gnome_action_set_self_blocked_short_label (PolKitGnomeAction *action, const gchar *short_label);
+static void polkit_gnome_action_set_self_blocked_label       (PolKitGnomeAction *action, const gchar *label);
+static void polkit_gnome_action_set_self_blocked_tooltip     (PolKitGnomeAction *action, const gchar *tooltip);
+static void polkit_gnome_action_set_self_blocked_icon_name   (PolKitGnomeAction *action, const gchar *icon_name);
+
+static void polkit_gnome_action_set_no_visible               (PolKitGnomeAction *action, gboolean visible);
+static void polkit_gnome_action_set_no_sensitive             (PolKitGnomeAction *action, gboolean sensitive);
+static void polkit_gnome_action_set_no_short_label           (PolKitGnomeAction *action, const gchar *short_label);
+static void polkit_gnome_action_set_no_label                 (PolKitGnomeAction *action, const gchar *label);
+static void polkit_gnome_action_set_no_tooltip               (PolKitGnomeAction *action, const gchar *tooltip);
+static void polkit_gnome_action_set_no_icon_name             (PolKitGnomeAction *action, const gchar *icon_name);
+
+static void polkit_gnome_action_set_auth_visible             (PolKitGnomeAction *action, gboolean visible);
+static void polkit_gnome_action_set_auth_sensitive           (PolKitGnomeAction *action, gboolean sensitive);
+static void polkit_gnome_action_set_auth_short_label         (PolKitGnomeAction *action, const gchar *short_label);
+static void polkit_gnome_action_set_auth_label               (PolKitGnomeAction *action, const gchar *label);
+static void polkit_gnome_action_set_auth_tooltip             (PolKitGnomeAction *action, const gchar *tooltip);
+static void polkit_gnome_action_set_auth_icon_name           (PolKitGnomeAction *action, const gchar *icon_name);
+
+static void polkit_gnome_action_set_yes_visible              (PolKitGnomeAction *action, gboolean visible);
+static void polkit_gnome_action_set_yes_sensitive            (PolKitGnomeAction *action, gboolean sensitive);
+static void polkit_gnome_action_set_yes_short_label          (PolKitGnomeAction *action, const gchar *short_label);
+static void polkit_gnome_action_set_yes_label                (PolKitGnomeAction *action, const gchar *label);
+static void polkit_gnome_action_set_yes_tooltip              (PolKitGnomeAction *action, const gchar *tooltip);
+static void polkit_gnome_action_set_yes_icon_name            (PolKitGnomeAction *action, const gchar *icon_name);
+
+static void polkit_gnome_action_set_target_pid               (PolKitGnomeAction *action, guint target_pid);
+
+static void _pk_config_changed (PolKitGnomeContext *pk_g_context, PolKitGnomeAction  *action);
+static void _pk_console_kit_db_changed (PolKitGnomeContext *pk_g_context, PolKitGnomeAction  *action);
+
+struct _PolKitGnomeActionPrivate 
+{
+        gboolean self_blocked_visible;
+        gboolean self_blocked_sensitive;
+        gchar *self_blocked_short_label;
+        gchar *self_blocked_label;
+        gchar *self_blocked_tooltip;
+        gchar *self_blocked_icon_name;
+
+        gboolean no_visible;
+        gboolean no_sensitive;
+        gchar *no_short_label;
+        gchar *no_label;
+        gchar *no_tooltip;
+        gchar *no_icon_name;
+
+        gboolean auth_visible;
+        gboolean auth_sensitive;
+        gchar *auth_short_label;
+        gchar *auth_label;
+        gchar *auth_tooltip;
+        gchar *auth_icon_name;
+
+        gboolean yes_visible;
+        gboolean yes_sensitive;
+        gchar *yes_short_label;
+        gchar *yes_label;
+        gchar *yes_tooltip;
+        gchar *yes_icon_name;
+
+        gboolean master_visible;
+        gboolean master_sensitive;
+
+        PolKitAction *polkit_action;
+        GSList *polkit_action_sufficient;
+
+        gboolean polkit_action_set_once;
+
+        guint target_pid;
+
+        /* the current PolicyKit result for the given polkit_action_id */
+        PolKitResult pk_result;
+
+        PolKitGnomeContext *pk_g_context;
+
+        gulong config_changed_handler_id;
+        gulong console_kit_db_changed_handler_id;
+};
+
+enum 
+{
+        AUTH_START_SIGNAL,
+        AUTH_END_SIGNAL,
+        POLKIT_RESULT_CHANGED_SIGNAL,
+        LAST_SIGNAL
+};
+
+enum
+{
+        PROP_0,
+        PROP_POLKIT_ACTION_OBJ,
+        PROP_POLKIT_ACTION_OBJ_SUFFICIENT,
+
+        PROP_POLKIT_SELF_BLOCKED_VISIBLE,
+        PROP_POLKIT_SELF_BLOCKED_SENSITIVE,
+        PROP_POLKIT_SELF_BLOCKED_SHORT_LABEL,
+        PROP_POLKIT_SELF_BLOCKED_LABEL,
+        PROP_POLKIT_SELF_BLOCKED_TOOLTIP,
+        PROP_POLKIT_SELF_BLOCKED_ICON_NAME,
+
+        PROP_POLKIT_NO_VISIBLE,
+        PROP_POLKIT_NO_SENSITIVE,
+        PROP_POLKIT_NO_SHORT_LABEL,
+        PROP_POLKIT_NO_LABEL,
+        PROP_POLKIT_NO_TOOLTIP,
+        PROP_POLKIT_NO_ICON_NAME,
+
+        PROP_POLKIT_AUTH_VISIBLE,
+        PROP_POLKIT_AUTH_SENSITIVE,
+        PROP_POLKIT_AUTH_SHORT_LABEL,
+        PROP_POLKIT_AUTH_LABEL,
+        PROP_POLKIT_AUTH_TOOLTIP,
+        PROP_POLKIT_AUTH_ICON_NAME,
+
+        PROP_POLKIT_YES_VISIBLE,
+        PROP_POLKIT_YES_SENSITIVE,
+        PROP_POLKIT_YES_SHORT_LABEL,
+        PROP_POLKIT_YES_LABEL,
+        PROP_POLKIT_YES_TOOLTIP,
+        PROP_POLKIT_YES_ICON_NAME,
+
+        PROP_POLKIT_MASTER_VISIBLE,
+        PROP_POLKIT_MASTER_SENSITIVE,
+
+        PROP_POLKIT_TARGET_PID,
+};
+
+G_DEFINE_TYPE (PolKitGnomeAction, polkit_gnome_action, GTK_TYPE_ACTION)
+
+static void set_property                   (GObject         *object,
+					    guint            prop_id,
+					    const GValue    *value,
+					    GParamSpec      *pspec);
+static void get_property                   (GObject         *object,
+					    guint            prop_id,
+					    GValue          *value,
+					    GParamSpec      *pspec);
+
+static GObjectClass *parent_class = NULL;
+static guint         signals[LAST_SIGNAL] = { 0 };
+
+static void
+polkit_gnome_action_init (PolKitGnomeAction *action)
+{
+        action->priv = POLKIT_GNOME_ACTION_GET_PRIVATE (action);
+
+
+}
+
+
+static void
+free_pk_action_sufficient (PolKitGnomeAction *action)
+{
+        if (action->priv->polkit_action_sufficient != NULL) {
+                GSList *l;
+
+                for (l = action->priv->polkit_action_sufficient; l != NULL; l = g_slist_next (l)) {
+                        polkit_action_unref ((PolKitAction *) l->data);
+                }
+                g_slist_free (action->priv->polkit_action_sufficient);
+                action->priv->polkit_action_sufficient = NULL;
+        }
+}
+
+static void
+polkit_gnome_action_finalize (GObject *object)
+{
+        PolKitGnomeAction *action;
+
+        action = POLKIT_GNOME_ACTION (object);
+
+        if (action->priv->polkit_action != NULL)
+                polkit_action_unref (action->priv->polkit_action);
+
+        g_free (action->priv->self_blocked_short_label);
+        g_free (action->priv->self_blocked_label);
+        g_free (action->priv->self_blocked_tooltip);
+        g_free (action->priv->self_blocked_icon_name);
+
+        g_free (action->priv->no_short_label);
+        g_free (action->priv->no_label);
+        g_free (action->priv->no_tooltip);
+        g_free (action->priv->no_icon_name);
+
+        g_free (action->priv->auth_short_label);
+        g_free (action->priv->auth_label);
+        g_free (action->priv->auth_tooltip);
+        g_free (action->priv->auth_icon_name);
+
+        g_free (action->priv->yes_short_label);
+        g_free (action->priv->yes_label);
+        g_free (action->priv->yes_tooltip);
+        g_free (action->priv->yes_icon_name);
+
+        free_pk_action_sufficient (action);
+
+        if (action->priv->pk_g_context != NULL) {
+                g_signal_handler_disconnect (action->priv->pk_g_context, action->priv->config_changed_handler_id);
+                g_signal_handler_disconnect (action->priv->pk_g_context, action->priv->console_kit_db_changed_handler_id);
+                g_object_unref (action->priv->pk_g_context);
+        }
+
+        G_OBJECT_CLASS (polkit_gnome_action_parent_class)->finalize (object);
+}
+
+static void
+_ensure_pk_g_context (PolKitGnomeAction *action)
+{
+        if (action->priv->pk_g_context == NULL) {
+                action->priv->pk_g_context = polkit_gnome_context_get (NULL);
+                
+                action->priv->config_changed_handler_id = g_signal_connect (
+                        action->priv->pk_g_context,
+                        "config-changed",
+                        G_CALLBACK (_pk_config_changed),
+                        action);
+                
+                action->priv->console_kit_db_changed_handler_id = g_signal_connect (
+                        action->priv->pk_g_context,
+                        "console-kit-db-changed",
+                        G_CALLBACK (_pk_console_kit_db_changed),
+                        action);
+        }
+}
+
+static GObject *
+polkit_gnome_action_constructor (GType                  type,
+                                 guint                  n_construct_properties,
+                                 GObjectConstructParam *construct_properties)
+{
+        PolKitGnomeAction      *action;
+        PolKitGnomeActionClass *klass;
+
+        klass = POLKIT_GNOME_ACTION_CLASS (g_type_class_peek (POLKIT_GNOME_TYPE_ACTION));
+
+        action = POLKIT_GNOME_ACTION (G_OBJECT_CLASS (parent_class)->constructor (type,
+                                                                                   n_construct_properties,
+                                                                                   construct_properties));
+
+        action->priv->master_visible = TRUE;
+        action->priv->master_sensitive = TRUE;
+
+        return G_OBJECT (action);
+}
+
+
+static void
+polkit_gnome_action_class_init (PolKitGnomeActionClass *klass)
+{
+        GObjectClass *gobject_class;
+        GtkActionClass *action_class;
+
+        parent_class = g_type_class_peek_parent (klass);
+        gobject_class = G_OBJECT_CLASS (klass);
+        action_class = GTK_ACTION_CLASS (klass);
+
+        gobject_class->constructor = polkit_gnome_action_constructor;
+        gobject_class->set_property = set_property;
+        gobject_class->get_property = get_property;
+        gobject_class->finalize = polkit_gnome_action_finalize;
+
+        action_class->activate = (void (*)(GtkAction*)) polkit_gnome_action_activate;
+
+        klass->auth_start = _auth_start;
+
+        g_object_class_install_property (gobject_class,
+                                         PROP_POLKIT_ACTION_OBJ,
+                                         g_param_spec_pointer ("polkit-action",
+                                                               "The PolKitAction object this GTK+ action is tracking",
+                                                               "The PolKitAction object this GTK+ action is tracking",
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+        g_object_class_install_property (gobject_class,
+                                         PROP_POLKIT_ACTION_OBJ_SUFFICIENT,
+                                         g_param_spec_value_array (
+                                                 "polkit-action-sufficient",
+                                                 "An array of PolKitAction objects that are sufficient to have authorizations for.",
+                                                 "An array of PolKitAction objects that are sufficient to have authorizations for.",
+                                                 g_param_spec_pointer (
+                                                         "polkit-action-sufficient-member",
+                                                         "PolKitAction member of polkit-action-sufficient",
+                                                         "PolKitAction member of polkit-action-sufficient",
+                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT),
+                                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+        /*------------------------------*/
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_SELF_BLOCKED_VISIBLE,
+                g_param_spec_boolean (
+                        "self-blocked-visible",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, whether the action will be visible",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, whether the action will be visible",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_SELF_BLOCKED_SENSITIVE,
+                g_param_spec_boolean (
+                        "self-blocked-sensitive",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, whether the action will be sensitive",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, whether the action will be sensitive",
+                        FALSE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_SELF_BLOCKED_SHORT_LABEL,
+                g_param_spec_string (
+                        "self-blocked-short-label",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this short-label",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this short-label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_SELF_BLOCKED_LABEL,
+                g_param_spec_string (
+                        "self-blocked-label",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this label",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_SELF_BLOCKED_TOOLTIP,
+                g_param_spec_string (
+                        "self-blocked-tooltip",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this tooltip",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this tooltip",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_SELF_BLOCKED_ICON_NAME,
+                g_param_spec_string (
+                        "self-blocked-icon-name",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this icon-name",
+                        "If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this icon-name",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        /*------------------------------*/
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_NO_VISIBLE,
+                g_param_spec_boolean (
+                        "no-visible",
+                        "If PolicyKit evaluates the result as 'no', whether the action will be visible",
+                        "If PolicyKit evaluates the result as 'no', whether the action will be visible",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_NO_SENSITIVE,
+                g_param_spec_boolean (
+                        "no-sensitive",
+                        "If PolicyKit evaluates the result as 'no', whether the action will be sensitive",
+                        "If PolicyKit evaluates the result as 'no', whether the action will be sensitive",
+                        FALSE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_NO_SHORT_LABEL,
+                g_param_spec_string (
+                        "no-short-label",
+                        "If PolicyKit evaluates the result as 'no', use this short-label",
+                        "If PolicyKit evaluates the result as 'no', use this short-label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_NO_LABEL,
+                g_param_spec_string (
+                        "no-label",
+                        "If PolicyKit evaluates the result as 'no', use this label",
+                        "If PolicyKit evaluates the result as 'no', use this label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_NO_TOOLTIP,
+                g_param_spec_string (
+                        "no-tooltip",
+                        "If PolicyKit evaluates the result as 'no', use this tooltip",
+                        "If PolicyKit evaluates the result as 'no', use this tooltip",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_NO_ICON_NAME,
+                g_param_spec_string (
+                        "no-icon-name",
+                        "If PolicyKit evaluates the result as 'no', use this icon-name",
+                        "If PolicyKit evaluates the result as 'no', use this icon-name",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        /*------------------------------*/
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_VISIBLE,
+                g_param_spec_boolean (
+                        "auth-visible",
+                        "If PolicyKit evaluates the result as 'auth', whether the action will be visible",
+                        "If PolicyKit evaluates the result as 'auth', whether the action will be visible",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_SENSITIVE,
+                g_param_spec_boolean (
+                        "auth-sensitive",
+                        "If PolicyKit evaluates the result as 'auth', whether the action will be sensitive",
+                        "If PolicyKit evaluates the result as 'auth', whether the action will be sensitive",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_SHORT_LABEL,
+                g_param_spec_string (
+                        "auth-short-label",
+                        "If PolicyKit evaluates the result as 'auth', use this short-label",
+                        "If PolicyKit evaluates the result as 'auth', use this short-label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_LABEL,
+                g_param_spec_string (
+                        "auth-label",
+                        "If PolicyKit evaluates the result as 'auth', use this label",
+                        "If PolicyKit evaluates the result as 'auth', use this label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_TOOLTIP,
+                g_param_spec_string (
+                        "auth-tooltip",
+                        "If PolicyKit evaluates the result as 'auth', use this tooltip",
+                        "If PolicyKit evaluates the result as 'auth', use this tooltip",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_ICON_NAME,
+                g_param_spec_string (
+                        "auth-icon-name",
+                        "If PolicyKit evaluates the result as 'auth', use this icon-name",
+                        "If PolicyKit evaluates the result as 'auth', use this icon-name",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        /*------------------------------*/
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_YES_VISIBLE,
+                g_param_spec_boolean (
+                        "yes-visible",
+                        "If PolicyKit evaluates the result as 'yes', whether the action will be visible",
+                        "If PolicyKit evaluates the result as 'yes', whether the action will be visible",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_YES_SENSITIVE,
+                g_param_spec_boolean (
+                        "yes-sensitive",
+                        "If PolicyKit evaluates the result as 'yes', whether the action will be sensitive",
+                        "If PolicyKit evaluates the result as 'yes', whether the action will be sensitive",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_YES_SHORT_LABEL,
+                g_param_spec_string (
+                        "yes-short-label",
+                        "If PolicyKit evaluates the result as 'yes', use this short-label",
+                        "If PolicyKit evaluates the result as 'yes', use this short-label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_YES_LABEL,
+                g_param_spec_string (
+                        "yes-label",
+                        "If PolicyKit evaluates the result as 'yes', use this label",
+                        "If PolicyKit evaluates the result as 'yes', use this label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_YES_TOOLTIP,
+                g_param_spec_string (
+                        "yes-tooltip",
+                        "If PolicyKit evaluates the result as 'yes', use this tooltip",
+                        "If PolicyKit evaluates the result as 'yes', use this tooltip",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_YES_ICON_NAME,
+                g_param_spec_string (
+                        "yes-icon-name",
+                        "If PolicyKit evaluates the result as 'yes', use this icon-name",
+                        "If PolicyKit evaluates the result as 'yes', use this icon-name",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        /*------------------------------*/
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_MASTER_VISIBLE,
+                g_param_spec_boolean (
+                        "master-visible",
+                        "Can be set to FALSE to force invisibility no matter what PolicyKit reports",
+                        "Can be set to FALSE to force invisibility no matter what PolicyKit reports",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_MASTER_SENSITIVE,
+                g_param_spec_boolean (
+                        "master-sensitive",
+                        "Can be set to FALSE to force insensitivity no matter what PolicyKit reports",
+                        "Can be set to FALSE to force insensitivity no matter what PolicyKit reports",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_TARGET_PID,
+                g_param_spec_uint (
+                        "target-pid",
+                        "The target process id to receive the authorization; if 0 it is the current process",
+                        "The target process id to receive the authorization; if 0 it is the current process",
+                        0,
+                        G_MAXUINT,
+                        0,
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+        /**
+         * PolKitGnomeAction::auth-start:
+         * @action: the object
+         *
+         * The ::auth-start signal is emitted when an authentication
+         * session starts.
+         **/
+        signals [AUTH_START_SIGNAL] =
+                g_signal_new ("auth-start",
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (PolKitGnomeActionClass, auth_start),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+
+        /**
+         * PolKitGnomeAction::auth-end:
+         * @action: the object
+         * @gained_privilege: whether the privilege was gained
+         *
+         * The ::auth-end signal is emitted when the an authentication
+         * session ends and carries information about whether the
+         * privilege was obtained or not.
+         **/
+        signals [AUTH_END_SIGNAL] =
+                g_signal_new ("auth-end",
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (PolKitGnomeActionClass, auth_end),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__BOOLEAN,
+                              G_TYPE_NONE,
+                              1, G_TYPE_BOOLEAN);
+
+        /**
+         * PolKitGnomeAction::polkit-result-changed:
+         * @action: the object
+         * @current_result: current #PolKitResult from PolicyKit regarding given #PolKitAction object
+         *
+         * The ::polkit-result-changed signal is emitted when the
+         * PolicyKit result changes. This can happen when external
+         * factors (config file, ConsoleKit, privilege granted /
+         * revoked) change since the #PolKitGnomeAction class listens
+         * for events using the #PolKitGnomeContext class.
+         **/
+        signals [POLKIT_RESULT_CHANGED_SIGNAL] =
+                g_signal_new ("polkit-result-changed",
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (PolKitGnomeActionClass, polkit_result_changed),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__INT,
+                              G_TYPE_NONE,
+                              1, G_TYPE_INT);
+
+
+        g_type_class_add_private (gobject_class, sizeof (PolKitGnomeActionPrivate));
+}
+
+static pid_t
+_get_target_pid (PolKitGnomeAction *action)
+{
+        pid_t pid;
+
+        if (action != NULL && action->priv->target_pid != 0)
+                pid = action->priv->target_pid;
+        else
+                pid = getpid ();
+
+        return pid;
+}
+
+static PolKitResult
+_compute_polkit_result_direct  (PolKitGnomeAction *action)
+{
+        PolKitCaller *pk_caller;
+        PolKitResult pk_result;
+        DBusError dbus_error;
+
+        _ensure_pk_g_context (action);
+
+        dbus_error_init (&dbus_error);        
+        pk_caller = polkit_tracker_get_caller_from_pid (action->priv->pk_g_context->pk_tracker, 
+                                                        _get_target_pid (action),
+                                                        &dbus_error);
+        if (pk_caller == NULL) {
+                g_warning ("Cannot get PolKitCaller object for target (pid=%d): %s: %s",
+                           _get_target_pid (action), dbus_error.name, dbus_error.message);
+                dbus_error_free (&dbus_error);
+
+                /* this is bad so cop-out to UKNOWN */
+                pk_result = POLKIT_RESULT_UNKNOWN;
+        } else {
+                pk_result = polkit_context_is_caller_authorized (action->priv->pk_g_context->pk_context, 
+                                                                 action->priv->polkit_action, 
+                                                                 pk_caller,
+                                                                 FALSE,
+                                                                 NULL);
+                if (pk_result != POLKIT_RESULT_YES) {
+                        GSList *i;
+
+                        /* no dice.. see if one if the sufficient actions, if any, yields a YES */
+                        for (i = action->priv->polkit_action_sufficient; i != NULL; i = g_slist_next (i)) {
+                                PolKitResult r;
+                                PolKitAction *a = (PolKitAction *) i->data;
+
+                                r = polkit_context_is_caller_authorized (action->priv->pk_g_context->pk_context, 
+                                                                         a, 
+                                                                         pk_caller,
+                                                                         FALSE,
+                                                                         NULL);
+
+                                if (r == POLKIT_RESULT_YES) {
+                                        pk_result = r;
+                                        break;
+                                }
+                        }
+                }
+        }
+
+        if (pk_caller != NULL)
+                polkit_caller_unref (pk_caller);
+
+        return pk_result;
+}
+
+/* returns TRUE if the result changed */
+static gboolean
+_compute_polkit_result (PolKitGnomeAction *action)
+{
+        PolKitResult old_result;
+
+        old_result = action->priv->pk_result;
+        action->priv->pk_result = POLKIT_RESULT_UNKNOWN;
+
+        if (action->priv->polkit_action == NULL) {
+                action->priv->pk_result = POLKIT_RESULT_YES;
+        } else {
+                action->priv->pk_result = _compute_polkit_result_direct (action);
+        }
+
+        return old_result != action->priv->pk_result;
+}
+
+static void
+_update_action (PolKitGnomeAction *action)
+{
+        PolKitGnomeContext *pkgc;
+        PolKitAuthorizationDB *authdb;
+                                
+        pkgc = polkit_gnome_context_get (NULL);
+        authdb = polkit_context_get_authorization_db (pkgc->pk_context);
+
+        switch (action->priv->pk_result) {
+        default:
+        case POLKIT_RESULT_UNKNOWN:
+        case POLKIT_RESULT_NO:
+                /* TODO: see if we're self-blocked */
+
+                if (action->priv->polkit_action != NULL && 
+                    polkit_authorization_db_is_uid_blocked_by_self (authdb, 
+                                                                    action->priv->polkit_action,
+                                                                    getuid (),
+                                                                    NULL)) {
+                        g_object_set (action, 
+                                      "visible", action->priv->self_blocked_visible && action->priv->master_visible,
+                                      "sensitive", action->priv->self_blocked_sensitive && action->priv->master_sensitive,
+                                      "short-label", action->priv->self_blocked_short_label,
+                                      "label", action->priv->self_blocked_label,
+                                      "tooltip", action->priv->self_blocked_tooltip,
+                                      "icon-name", action->priv->self_blocked_icon_name, 
+                                      NULL);
+                } else {
+                        g_object_set (action, 
+                                      "visible", action->priv->no_visible && action->priv->master_visible,
+                                      "sensitive", action->priv->no_sensitive && action->priv->master_sensitive,
+                                      "short-label", action->priv->no_short_label,
+                                      "label", action->priv->no_label,
+                                      "tooltip", action->priv->no_tooltip,
+                                      "icon-name", action->priv->no_icon_name, 
+                                      NULL);
+                }
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                g_object_set (action, 
+                              "visible", action->priv->auth_visible && action->priv->master_visible,
+                              "sensitive", action->priv->auth_sensitive && action->priv->master_sensitive,
+                              "short-label", action->priv->auth_short_label,
+                              "label", action->priv->auth_label,
+                              "tooltip", action->priv->auth_tooltip,
+                              "icon-name", action->priv->auth_icon_name, 
+                              NULL);
+                break;
+
+        case POLKIT_RESULT_YES:
+                g_object_set (action, 
+                              "visible", action->priv->yes_visible && action->priv->master_visible,
+                              "sensitive", action->priv->yes_sensitive && action->priv->master_sensitive,
+                              "short-label", action->priv->yes_short_label,
+                              "label", action->priv->yes_label,
+                              "tooltip", action->priv->yes_tooltip,
+                              "icon-name", action->priv->yes_icon_name,
+                              NULL);
+                break;
+        }
+}
+
+static void
+_pk_config_changed (PolKitGnomeContext *pk_g_context, PolKitGnomeAction  *action)
+{
+        gboolean result_changed;
+        result_changed = _compute_polkit_result (action);
+        _update_action (action);
+        if (result_changed) {
+                g_signal_emit (action, signals [POLKIT_RESULT_CHANGED_SIGNAL], 0, action->priv->pk_result);
+        }
+}
+
+static void
+_pk_console_kit_db_changed (PolKitGnomeContext *pk_g_context, PolKitGnomeAction  *action)
+{
+        /* for now, just use the same code as above... */
+        _pk_config_changed (pk_g_context, action);
+}
+
+
+/**
+ * polkit_gnome_action_new:
+ * @name: A unique name for the action
+ *
+ * Creates a new #PolKitGnomeAction object. The typical use for this
+ * function is for specialized use where
+ * polkit_gnome_action_new_default() does not meet the needs of the
+ * application. A short example of the usage of this contructor
+ * follows.
+ *
+ * If the 'polkit-action' property is #NULL the behavior is similar to
+ * as if a #PolKitAction returned #POLKIT_RESULT_YES.
+ *
+ * One can set the 'polkit-action-sufficient' property to a
+ * #GValueArray of pointers to #PolKitAction objects. The semantics of
+ * this property is that if the user is authorized for any of the
+ * given actions in 'polkit-action-sufficient' then the behavior is
+ * the same as if they're authorized for the action denoted by
+ * 'polkit-action'. This is useful in a setup where you have two
+ * similar actions and one implies the other. For example, in
+ * gnome-system-monitor there are two actions
+ * <literal>org.gnome.system-monitor.increase-own-priority</literal>
+ * (Increase the priority of a process owned by yourself) and
+ * <literal>org.gnome.system-monitor.change-priorty</literal> (Change
+ * priority of any process). As the latter clearly implies the former,
+ * one would set the latter in the 'polkit-action-sufficient'
+ * property when constructing a #PolKitAction for the former.
+ *
+ * <programlisting>
+ * PolKitAction *polkit_action;
+ * PolKitGnomeAction *action;
+ *
+ * polkit_action = polkit_action_new ();
+ * polkit_action_set_action_id (polkit_action, "org.example.some-policykit-action");
+ *
+ * action = polkit_gnome_action_new ("blabla", NULL);
+ * g_object_set (action,
+ *               "polkit-action",    polkit_action,
+ *               "no-visible",       TRUE,
+ *               "no-sensitive",     FALSE,
+ *               "no-short-label",   "The Action no can do!",
+ *               "no-label",         "The Action is not permitted!",
+ *               "no-tooltip",       "The Tooltip (no)",
+ *               "no-icon-name",     GTK_STOCK_NO,
+ *
+ *               "auth-visible",     TRUE,
+ *               "auth-sensitive",   TRUE,
+ *               "auth-short-label", "The Action requires auth...",
+ *               "auth-label",       "The Action requires auth...",
+ *               "auth-tooltip",     "The Tooltip (auth)",
+ *               "auth-icon-name",   GTK_STOCK_DIALOG_AUTHENTICATION,
+ *
+ *               "yes-visible",      TRUE,
+ *               "yes-sensitive",    TRUE,
+ *               "yes-short-label",  "Action!",
+ *               "yes-label",        "Just do the Action!",
+ *               "yes-tooltip",      "The Tooltip (yes)",
+ *               "yes-icon-name",    GTK_STOCK_YES,
+ *               NULL);
+ * </programlisting>
+ *
+ * Returns: a new #PolKitGnomeAction or #NULL if error is set
+ */
+PolKitGnomeAction *
+polkit_gnome_action_new (const gchar *name)
+{
+        PolKitGnomeAction *action = NULL;
+
+        action = g_object_new (POLKIT_GNOME_TYPE_ACTION,
+                               "name", name,
+                               NULL);
+
+        return action;
+}
+
+/**
+ * polkit_gnome_action_new_default:
+ * @name: A unique name for the action
+ * @polkit_action: the #PolKitAction to track
+ * @label: the label to use (will also apply to short-label)
+ * @tooltip: the tool tip to use
+ *
+ * Creates a new #PolKitGnomeAction object with the default
+ * behavior for a given #PolKitAction object.
+ *
+ * Default behavior is defined by the label and tooltip being
+ * identical across all three four states, the action being visible in
+ * all four states, and the action being insensitive only in the state
+ * where the result from PolicyKit is no and self-blocked. Only when
+ * PolicyKit returns one of the 'auth*' results, the icon_name
+ * property will be set to #GTK_STOCK_DIALOG_AUTHENTICATION.
+ *
+ * The caller can always modify individual aspects of the action after
+ * creation, e.g. change the tooltip for the self-blocked, no, auth
+ * and yes states.
+ *
+ * If the given polkit_action is #NULL the behavior is similar to as
+ * if a #PolKitAction returned #POLKIT_RESULT_YES.
+ *
+ * Returns: a new #PolKitGnomeAction or #NULL if error is set
+ */
+PolKitGnomeAction *
+polkit_gnome_action_new_default (const gchar  *name, 
+                                 PolKitAction *polkit_action, 
+                                 const gchar  *label, 
+                                 const gchar  *tooltip)
+{
+        PolKitGnomeAction *action;
+
+        action = g_object_new (POLKIT_GNOME_TYPE_ACTION,
+                               "name", name,
+                               "polkit-action", polkit_action,
+
+                               "self-blocked-visible",       TRUE,
+                               "self-blocked-sensitive",     FALSE,
+                               "self-blocked-short-label",   label,
+                               "self-blocked-label",         label,
+                               "self-blocked-tooltip",       tooltip,
+                               "self-blocked-icon-name",     NULL,
+
+                               "no-visible",       TRUE,
+                               "no-sensitive",     FALSE,
+                               "no-short-label",   label,
+                               "no-label",         label,
+                               "no-tooltip",       tooltip,
+                               "no-icon-name",     NULL,
+                               
+                               "auth-visible",     TRUE,
+                               "auth-sensitive",   TRUE,
+                               "auth-short-label", label,
+                               "auth-label",       label,
+                               "auth-tooltip",     tooltip,
+                               "auth-icon-name",   GTK_STOCK_DIALOG_AUTHENTICATION,
+                               
+                               "yes-visible",      TRUE,
+                               "yes-sensitive",    TRUE,
+                               "yes-short-label",  label,
+                               "yes-label",        label,
+                               "yes-tooltip",      tooltip,
+                               "yes-icon-name",    NULL,
+                               
+                               "master-visible",   TRUE,
+                               "master-sensitive", TRUE,
+                               NULL);
+
+        return action;
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+/**
+ * polkit_gnome_action_set_polkit_action:
+ * @action: The #PolKitGnomeAction object
+ * @pk_action: The #PolKitAction object
+ *
+ * Sets the #PolKitAction object to track for updating the GTK+ action.
+ */
+static void
+polkit_gnome_action_set_polkit_action (PolKitGnomeAction *action, PolKitAction *pk_action)
+{
+
+        /* Don't bother updating polkit_action if it's the same
+         * value.. it will just cause a lot of unnecessary work as
+         * we'll recompute the answer via PolicyKit.. 
+         *
+         * unless it's on the initial call (where priv->polkit_action
+         * is alread NULL) because we need that initial update;
+         */
+        if (!action->priv->polkit_action_set_once || action->priv->polkit_action != pk_action) {
+
+                action->priv->polkit_action_set_once = TRUE;
+
+                if (action->priv->polkit_action != NULL)
+                        polkit_action_unref (action->priv->polkit_action);
+
+                action->priv->polkit_action = pk_action != NULL ? polkit_action_ref (pk_action) : NULL;
+                
+                _compute_polkit_result (action);
+                _update_action (action);
+        }
+}
+
+static void 
+polkit_gnome_action_set_polkit_action_sufficient (PolKitGnomeAction *action, const GValue *pk_action_array)
+{
+        unsigned int n;
+        GValueArray *value_array;
+
+        free_pk_action_sufficient (action);
+
+        if (pk_action_array == NULL)
+                goto out;
+
+	value_array = g_value_get_boxed (pk_action_array);
+        if (value_array == NULL)
+                goto out;
+
+	for (n = 0; n < value_array->n_values; n++) {
+                PolKitAction *pk_action;
+
+                pk_action = (PolKitAction *) g_value_get_pointer (& (value_array->values[n]));
+		action->priv->polkit_action_sufficient = g_slist_prepend (action->priv->polkit_action_sufficient, 
+                                                                          polkit_action_ref (pk_action));
+                char *s;
+                polkit_action_get_action_id (pk_action, &s);
+                g_warning ("Setting sufficient %d: %s", n, s);
+	}
+
+out:
+        _compute_polkit_result (action);
+        _update_action (action);
+}
+
+
+/**
+ * polkit_gnome_action_get_polkit_result:
+ * @action: The #PolKitGnomeAction object
+ *
+ * Gets the #PolKitResult that indicates whether the user is
+ * privileged to do the #PolKitAction associated with this
+ * #PolKitGnomeAction object.
+ *
+ * Returns: The #PolKitAction object. The caller shall not unref this object.
+ */
+PolKitResult
+polkit_gnome_action_get_polkit_result (PolKitGnomeAction *action)
+{
+        _compute_polkit_result (action);
+        _update_action (action);
+        return action->priv->pk_result;
+}
+
+/**
+ * polkit_gnome_action_get_sensitive:
+ * @action: The #PolKitGnomeAction object
+ *
+ * Get the master sensitivity, see PolKitGnomeAction:master-sensitive:
+ * for details.
+ * 
+ * Returns: the master sensitivity
+ */
+gboolean
+polkit_gnome_action_get_sensitive (PolKitGnomeAction *action)
+{
+        return action->priv->master_sensitive;
+}
+
+/**
+ * polkit_gnome_action_set_sensitive:
+ * @action: The #PolKitGnomeAction object
+ * @sensitive: master sensitivity
+ *
+ * Set the master sensitivity, see PolKitGnomeAction:master-sensitive:
+ * for details.
+ */
+void
+polkit_gnome_action_set_sensitive (PolKitGnomeAction *action, gboolean sensitive)
+{
+        if (action->priv->master_sensitive == sensitive)
+                return;
+        action->priv->master_sensitive = sensitive;
+        _update_action (action);
+}
+
+static void 
+polkit_gnome_action_set_target_pid (PolKitGnomeAction *action, guint target_pid)
+{
+        action->priv->target_pid = target_pid;
+        _compute_polkit_result (action);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_get_visible:
+ * @action: The #PolKitGnomeAction object
+ *
+ * Get the master visibility, see PolKitGnomeAction:master-visible:
+ * for details.
+ * 
+ * Returns: the master visibility
+ */
+gboolean
+polkit_gnome_action_get_visible (PolKitGnomeAction *action)
+{
+        return action->priv->master_visible;
+}
+
+/**
+ * polkit_gnome_action_set_visible:
+ * @action: The #PolKitGnomeAction object
+ * @visible: master visibility
+ *
+ * Set the master visibility, see PolKitGnomeAction:master-visible:
+ * for details.
+ */
+void
+polkit_gnome_action_set_visible (PolKitGnomeAction *action, gboolean visible)
+{
+        if (action->priv->master_visible == visible)
+                return;
+        action->priv->master_visible = visible;
+        _update_action (action);
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+/**
+ * polkit_gnome_action_set_self_blocked_visible:
+ * @action: The #PolKitGnomeAction object
+ * @visible: new value
+ *
+ * Sets the value of visible to use when PolicyKit returns the answer
+ * no (and the reason is that the user has a self-granted negative
+ * authorization) for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_self_blocked_visible (PolKitGnomeAction *action, gboolean visible)
+{
+        action->priv->self_blocked_visible = visible;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_self_blocked_sensitive:
+ * @action: The #PolKitGnomeAction object
+ * @sensitive: new value
+ *
+ * Sets the value of sensitive to use when PolicyKit returns the
+ * answer no (and the reason is that the user has a self-granted
+ * negative authorization) for the current #PolKitAction being
+ * tracked.
+ */
+static void
+polkit_gnome_action_set_self_blocked_sensitive (PolKitGnomeAction *action, gboolean sensitive)
+{
+        action->priv->self_blocked_sensitive = sensitive;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_self_blocked_short_label:
+ * @action: The #PolKitGnomeAction object
+ * @short_label: new value
+ *
+ * Sets the value of short-label to use when PolicyKit returns the
+ * answer no (and the reason is that the user has a self-granted
+ * negative authorization) for the current #PolKitAction being
+ * tracked.
+ */
+static void
+polkit_gnome_action_set_self_blocked_short_label (PolKitGnomeAction *action, const gchar *short_label)
+{
+        g_free (action->priv->self_blocked_short_label);
+        action->priv->self_blocked_short_label = g_strdup (short_label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_self_blocked_label:
+ * @action: The #PolKitGnomeAction object
+ * @label: new value
+ *
+ * Sets the value of label to use when PolicyKit returns the answer
+ * no (and the reason is that the user has a self-granted
+ * negative authorization) for the current #PolKitAction being
+ * tracked.
+ */
+static void
+polkit_gnome_action_set_self_blocked_label (PolKitGnomeAction *action, const gchar *label)
+{
+        g_free (action->priv->self_blocked_label);
+        action->priv->self_blocked_label = g_strdup (label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_self_blocked_tooltip:
+ * @action: The #PolKitGnomeAction object
+ * @tooltip: new value
+ *
+ * Sets the value of tooltip to use when PolicyKit returns the answer
+ * no (and the reason is that the user has a self-granted negative
+ * authorization) for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_self_blocked_tooltip (PolKitGnomeAction *action, const gchar *tooltip)
+{
+        g_free (action->priv->self_blocked_tooltip);
+        action->priv->self_blocked_tooltip = g_strdup (tooltip);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_self_blocked_icon_name:
+ * @action: The #PolKitGnomeAction object
+ * @icon_name: new value
+ *
+ * Sets the value of icon_name to use when PolicyKit returns the
+ * answer no (and the reason is that the user has a self-granted
+ * negative authorization) for the current #PolKitAction being
+ * tracked.
+ */
+static void
+polkit_gnome_action_set_self_blocked_icon_name (PolKitGnomeAction *action, const gchar *icon_name)
+{
+        g_free (action->priv->self_blocked_icon_name);
+        action->priv->self_blocked_icon_name = g_strdup (icon_name);
+        _update_action (action);
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+/**
+ * polkit_gnome_action_set_no_visible:
+ * @action: The #PolKitGnomeAction object
+ * @visible: new value
+ *
+ * Sets the value of visible to use when PolicyKit returns the answer
+ * no for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_no_visible (PolKitGnomeAction *action, gboolean visible)
+{
+        action->priv->no_visible = visible;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_no_sensitive:
+ * @action: The #PolKitGnomeAction object
+ * @sensitive: new value
+ *
+ * Sets the value of sensitive to use when PolicyKit returns the answer
+ * no for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_no_sensitive (PolKitGnomeAction *action, gboolean sensitive)
+{
+        action->priv->no_sensitive = sensitive;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_no_short_label:
+ * @action: The #PolKitGnomeAction object
+ * @short_label: new value
+ *
+ * Sets the value of short-label to use when PolicyKit returns the
+ * answer no for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_no_short_label (PolKitGnomeAction *action, const gchar *short_label)
+{
+        g_free (action->priv->no_short_label);
+        action->priv->no_short_label = g_strdup (short_label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_no_label:
+ * @action: The #PolKitGnomeAction object
+ * @label: new value
+ *
+ * Sets the value of label to use when PolicyKit returns the answer no
+ * for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_no_label (PolKitGnomeAction *action, const gchar *label)
+{
+        g_free (action->priv->no_label);
+        action->priv->no_label = g_strdup (label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_no_tooltip:
+ * @action: The #PolKitGnomeAction object
+ * @tooltip: new value
+ *
+ * Sets the value of tooltip to use when PolicyKit returns the answer
+ * no for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_no_tooltip (PolKitGnomeAction *action, const gchar *tooltip)
+{
+        g_free (action->priv->no_tooltip);
+        action->priv->no_tooltip = g_strdup (tooltip);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_no_icon_name:
+ * @action: The #PolKitGnomeAction object
+ * @icon_name: new value
+ *
+ * Sets the value of icon_name to use when PolicyKit returns the
+ * answer no for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_no_icon_name (PolKitGnomeAction *action, const gchar *icon_name)
+{
+        g_free (action->priv->no_icon_name);
+        action->priv->no_icon_name = g_strdup (icon_name);
+        _update_action (action);
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+/**
+ * polkit_gnome_action_set_auth_visible:
+ * @action: The #PolKitGnomeAction object
+ * @visible: new value
+ *
+ * Sets the value of visible to use when PolicyKit returns the answer
+ * auth* for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_auth_visible (PolKitGnomeAction *action, gboolean visible)
+{
+        action->priv->auth_visible = visible;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_auth_sensitive:
+ * @action: The #PolKitGnomeAction object
+ * @sensitive: new value
+ *
+ * Sets the value of sensitive to use when PolicyKit returns the answer
+ * auth* for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_auth_sensitive (PolKitGnomeAction *action, gboolean sensitive)
+{
+        action->priv->auth_sensitive = sensitive;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_auth_short_label:
+ * @action: The #PolKitGnomeAction object
+ * @short_label: new value
+ *
+ * Sets the value of short-label to use when PolicyKit returns the
+ * answer auth for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_auth_short_label (PolKitGnomeAction *action, const gchar *short_label)
+{
+        g_free (action->priv->auth_short_label);
+        action->priv->auth_short_label = g_strdup (short_label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_auth_label:
+ * @action: The #PolKitGnomeAction object
+ * @label: new value
+ *
+ * Sets the value of label to use when PolicyKit returns the answer auth*
+ * for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_auth_label (PolKitGnomeAction *action, const gchar *label)
+{
+        g_free (action->priv->auth_label);
+        action->priv->auth_label = g_strdup (label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_auth_tooltip:
+ * @action: The #PolKitGnomeAction object
+ * @tooltip: new value
+ *
+ * Sets the value of tooltip to use when PolicyKit returns the answer
+ * auth* for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_auth_tooltip (PolKitGnomeAction *action, const gchar *tooltip)
+{
+        g_free (action->priv->auth_tooltip);
+        action->priv->auth_tooltip = g_strdup (tooltip);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_auth_icon_name:
+ * @action: The #PolKitGnomeAction object
+ * @icon_name: new value
+ *
+ * Sets the value of icon_name to use when PolicyKit returns the
+ * answer auth* for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_auth_icon_name (PolKitGnomeAction *action, const gchar *icon_name)
+{
+        g_free (action->priv->auth_icon_name);
+        action->priv->auth_icon_name = g_strdup (icon_name);
+        _update_action (action);
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+/**
+ * polkit_gnome_action_set_yes_visible:
+ * @action: The #PolKitGnomeAction object
+ * @visible: new value
+ *
+ * Sets the value of visible to use when PolicyKit returns the answer
+ * yes for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_yes_visible (PolKitGnomeAction *action, gboolean visible)
+{
+        action->priv->yes_visible = visible;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_yes_sensitive:
+ * @action: The #PolKitGnomeAction object
+ * @sensitive: new value
+ *
+ * Sets the value of sensitive to use when PolicyKit returns the answer
+ * yes for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_yes_sensitive (PolKitGnomeAction *action, gboolean sensitive)
+{
+        action->priv->yes_sensitive = sensitive;
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_yes_short_label:
+ * @action: The #PolKitGnomeAction object
+ * @short_label: new value
+ *
+ * Sets the value of short-label to use when PolicyKit returns the
+ * answer yes for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_yes_short_label (PolKitGnomeAction *action, const gchar *short_label)
+{
+        g_free (action->priv->yes_short_label);
+        action->priv->yes_short_label = g_strdup (short_label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_yes_label:
+ * @action: The #PolKitGnomeAction object
+ * @label: new value
+ *
+ * Sets the value of label to use when PolicyKit returns the answer yes
+ * for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_yes_label (PolKitGnomeAction *action, const gchar *label)
+{
+        g_free (action->priv->yes_label);
+        action->priv->yes_label = g_strdup (label);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_yes_tooltip:
+ * @action: The #PolKitGnomeAction object
+ * @tooltip: new value
+ *
+ * Sets the value of tooltip to use when PolicyKit returns the answer
+ * yes for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_yes_tooltip (PolKitGnomeAction *action, const gchar *tooltip)
+{
+        g_free (action->priv->yes_tooltip);
+        action->priv->yes_tooltip = g_strdup (tooltip);
+        _update_action (action);
+}
+
+/**
+ * polkit_gnome_action_set_yes_icon_name:
+ * @action: The #PolKitGnomeAction object
+ * @icon_name: new value
+ *
+ * Sets the value of icon_name to use when PolicyKit returns the
+ * answer yes for the current #PolKitAction being tracked.
+ */
+static void
+polkit_gnome_action_set_yes_icon_name (PolKitGnomeAction *action, const gchar *icon_name)
+{
+        g_free (action->priv->yes_icon_name);
+        action->priv->yes_icon_name = g_strdup (icon_name);
+        _update_action (action);
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+static void
+get_property (GObject     *object,
+	      guint        prop_id,
+	      GValue      *value,
+	      GParamSpec  *pspec)
+{
+        PolKitGnomeAction *action = POLKIT_GNOME_ACTION (object);
+        
+        switch (prop_id)
+        {
+        case PROP_POLKIT_ACTION_OBJ:
+                g_value_set_pointer (value, action->priv->polkit_action != NULL ? polkit_action_ref (action->priv->polkit_action) : NULL);
+                break;
+
+        case PROP_POLKIT_ACTION_OBJ_SUFFICIENT:
+                //TODO: g_value_set_pointer (value, action->priv->polkit_action != NULL ? polkit_action_ref (action->priv->polkit_action) : NULL);
+                break;
+
+        case PROP_POLKIT_SELF_BLOCKED_VISIBLE:
+                g_value_set_boolean (value, action->priv->self_blocked_visible);
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_SENSITIVE:
+                g_value_set_boolean (value, action->priv->self_blocked_sensitive);
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_SHORT_LABEL:
+                g_value_set_string (value, action->priv->self_blocked_short_label);
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_LABEL:
+                g_value_set_string (value, action->priv->self_blocked_label);
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_TOOLTIP:
+                g_value_set_string (value, action->priv->self_blocked_tooltip);
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_ICON_NAME:
+                g_value_set_string (value, action->priv->self_blocked_icon_name);
+                break;
+
+        case PROP_POLKIT_NO_VISIBLE:
+                g_value_set_boolean (value, action->priv->no_visible);
+                break;
+        case PROP_POLKIT_NO_SENSITIVE:
+                g_value_set_boolean (value, action->priv->no_sensitive);
+                break;
+        case PROP_POLKIT_NO_SHORT_LABEL:
+                g_value_set_string (value, action->priv->no_short_label);
+                break;
+        case PROP_POLKIT_NO_LABEL:
+                g_value_set_string (value, action->priv->no_label);
+                break;
+        case PROP_POLKIT_NO_TOOLTIP:
+                g_value_set_string (value, action->priv->no_tooltip);
+                break;
+        case PROP_POLKIT_NO_ICON_NAME:
+                g_value_set_string (value, action->priv->no_icon_name);
+                break;
+
+        case PROP_POLKIT_AUTH_VISIBLE:
+                g_value_set_boolean (value, action->priv->auth_visible);
+                break;
+        case PROP_POLKIT_AUTH_SENSITIVE:
+                g_value_set_boolean (value, action->priv->auth_sensitive);
+                break;
+        case PROP_POLKIT_AUTH_SHORT_LABEL:
+                g_value_set_string (value, action->priv->auth_short_label);
+                break;
+        case PROP_POLKIT_AUTH_LABEL:
+                g_value_set_string (value, action->priv->auth_label);
+                break;
+        case PROP_POLKIT_AUTH_TOOLTIP:
+                g_value_set_string (value, action->priv->auth_tooltip);
+                break;
+        case PROP_POLKIT_AUTH_ICON_NAME:
+                g_value_set_string (value, action->priv->auth_icon_name);
+                break;
+
+        case PROP_POLKIT_YES_VISIBLE:
+                g_value_set_boolean (value, action->priv->yes_visible);
+                break;
+        case PROP_POLKIT_YES_SENSITIVE:
+                g_value_set_boolean (value, action->priv->yes_sensitive);
+                break;
+        case PROP_POLKIT_YES_SHORT_LABEL:
+                g_value_set_string (value, action->priv->yes_short_label);
+                break;
+        case PROP_POLKIT_YES_LABEL:
+                g_value_set_string (value, action->priv->yes_label);
+                break;
+        case PROP_POLKIT_YES_TOOLTIP:
+                g_value_set_string (value, action->priv->yes_tooltip);
+                break;
+        case PROP_POLKIT_YES_ICON_NAME:
+                g_value_set_string (value, action->priv->yes_icon_name);
+                break;
+
+        case PROP_POLKIT_MASTER_VISIBLE:
+                g_value_set_boolean (value, action->priv->master_visible);
+                break;
+        case PROP_POLKIT_MASTER_SENSITIVE:
+                g_value_set_boolean (value, action->priv->master_sensitive);
+                break;
+
+        case PROP_POLKIT_TARGET_PID:
+                g_value_set_uint (value, action->priv->target_pid);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+set_property (GObject      *object,
+	      guint         prop_id,
+	      const GValue *value,
+	      GParamSpec   *pspec)
+{
+        PolKitGnomeAction *action = POLKIT_GNOME_ACTION (object);
+        
+        switch (prop_id)
+        {
+        case PROP_POLKIT_ACTION_OBJ:
+                polkit_gnome_action_set_polkit_action (action, g_value_get_pointer (value));
+                break;
+
+        case PROP_POLKIT_ACTION_OBJ_SUFFICIENT:
+                polkit_gnome_action_set_polkit_action_sufficient (action, value);
+                break;
+
+        case PROP_POLKIT_SELF_BLOCKED_VISIBLE:
+                polkit_gnome_action_set_self_blocked_visible (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_SENSITIVE:
+                polkit_gnome_action_set_self_blocked_sensitive (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_SHORT_LABEL:
+                polkit_gnome_action_set_self_blocked_short_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_LABEL:
+                polkit_gnome_action_set_self_blocked_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_TOOLTIP:
+                polkit_gnome_action_set_self_blocked_tooltip (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_SELF_BLOCKED_ICON_NAME:
+                polkit_gnome_action_set_self_blocked_icon_name (action, g_value_get_string (value));
+                break;
+
+        case PROP_POLKIT_NO_VISIBLE:
+                polkit_gnome_action_set_no_visible (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_NO_SENSITIVE:
+                polkit_gnome_action_set_no_sensitive (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_NO_SHORT_LABEL:
+                polkit_gnome_action_set_no_short_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_NO_LABEL:
+                polkit_gnome_action_set_no_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_NO_TOOLTIP:
+                polkit_gnome_action_set_no_tooltip (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_NO_ICON_NAME:
+                polkit_gnome_action_set_no_icon_name (action, g_value_get_string (value));
+                break;
+
+        case PROP_POLKIT_AUTH_VISIBLE:
+                polkit_gnome_action_set_auth_visible (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_AUTH_SENSITIVE:
+                polkit_gnome_action_set_auth_sensitive (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_AUTH_SHORT_LABEL:
+                polkit_gnome_action_set_auth_short_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_AUTH_LABEL:
+                polkit_gnome_action_set_auth_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_AUTH_TOOLTIP:
+                polkit_gnome_action_set_auth_tooltip (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_AUTH_ICON_NAME:
+                polkit_gnome_action_set_auth_icon_name (action, g_value_get_string (value));
+                break;
+
+        case PROP_POLKIT_YES_VISIBLE:
+                polkit_gnome_action_set_yes_visible (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_YES_SENSITIVE:
+                polkit_gnome_action_set_yes_sensitive (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_YES_SHORT_LABEL:
+                polkit_gnome_action_set_yes_short_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_YES_LABEL:
+                polkit_gnome_action_set_yes_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_YES_TOOLTIP:
+                polkit_gnome_action_set_yes_tooltip (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_YES_ICON_NAME:
+                polkit_gnome_action_set_yes_icon_name (action, g_value_get_string (value));
+                break;
+
+        case PROP_POLKIT_MASTER_VISIBLE:
+                polkit_gnome_action_set_visible (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_MASTER_SENSITIVE:
+                polkit_gnome_action_set_sensitive (action, g_value_get_boolean (value));
+                break;
+
+        case PROP_POLKIT_TARGET_PID:
+                polkit_gnome_action_set_target_pid (action, g_value_get_uint (value));
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static XID
+_get_xid_from_proxy_widgets (PolKitGnomeAction *action)
+{
+        XID xid;
+        GSList *i;
+        GSList *proxies;
+
+        /* unfortunately there's no way to get the proxy that caused
+         * the ::activate signal.. so go through proxies and pick the
+         * first one.. */
+
+        /* TODO: this won't work for menus (mclasen) */
+
+        xid = 0;
+
+        proxies = gtk_action_get_proxies (GTK_ACTION (action));
+
+        for (i = proxies; i != NULL; i = i->next) {
+                GtkWidget *top_level;
+                GtkWidget *proxy = i->data;
+
+                top_level = gtk_widget_get_toplevel (proxy);
+
+                if (top_level == NULL)
+                        continue;
+
+                if (! (GTK_WIDGET_TOPLEVEL (top_level) && GTK_IS_WINDOW (top_level)))
+                        continue;
+
+                if (top_level->window == NULL)
+                        continue;
+
+                xid = gdk_x11_drawable_get_xid (GDK_WINDOW (top_level->window));
+
+                if (xid != 0)
+                        break;
+        }
+
+        return xid;
+}
+
+static void
+_show_dialog_cb (PolKitAction *pk_action, 
+                 gboolean      gained_privilege, 
+                 GError       *error, 
+                 gpointer      user_data)
+{
+        PolKitGnomeAction *action = POLKIT_GNOME_ACTION (user_data);
+
+        if (gained_privilege) {
+                /* better make sure our local pk_result is up-to-date.. */
+                _compute_polkit_result (action);
+
+                //g_debug ("end auth, obtained it");
+
+                /* now emit the 'activate' signal again.. */
+                gtk_action_activate (GTK_ACTION (action));
+
+        } else {
+                //g_debug ("end auth, didn't obtain it");
+
+                if (error != NULL) {
+                        g_warning ("Caught error: %s", error->message);
+                        g_error_free (error);
+                }
+        }
+
+        g_signal_emit (action, signals [AUTH_END_SIGNAL], 0, gained_privilege);
+}
+
+static void 
+_auth_start (PolKitGnomeAction *action)
+{
+        GError *error = NULL;
+
+        //g_debug ("starting auth");
+        if (!polkit_gnome_auth_obtain (action->priv->polkit_action, 
+                                       (guint) _get_xid_from_proxy_widgets (action),
+                                       (guint) _get_target_pid (action),
+                                       _show_dialog_cb, 
+                                       action, 
+                                       &error)) {
+                g_warning ("Caught error: %s", error->message);
+                g_error_free (error);
+        }
+}
+
+static void
+polkit_gnome_action_activate (PolKitGnomeAction *action)
+{
+        switch (action->priv->pk_result) {
+        case POLKIT_RESULT_YES:
+                /* If PolicyKit says yes.. then let 'activate' signal
+                 * propagate
+                 */
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                /* Otherwise, if the action needs auth..  stop the emission
+                 * and start auth process.. 
+                 */
+
+                g_signal_stop_emission_by_name (action, "activate");
+
+                if (action->priv->polkit_action != NULL) {
+                        g_signal_emit (action, signals [AUTH_START_SIGNAL], 0);
+                }
+                break;
+
+        default:
+        case POLKIT_RESULT_NO:
+                /* If PolicyKit says no... and we got here.. it means
+                 * that the user set the property "no-sensitive" to
+                 * TRUE.. Otherwise we couldn't be handling this signal.
+                 *
+                 * Hence, they probably have a good reason for doing
+                 * this so do let the 'activate' signal propagate.. 
+                 */
+                break;
+        }
+}
+
+static void
+_update_tooltips (PolKitGnomeAction *action, GParamSpec *arg1, GtkWidget *widget)
+{
+        GtkTooltips *tips;
+        GtkTooltipsData *ttd;
+        gchar *tip_str;
+
+        ttd = gtk_tooltips_data_get (widget);
+
+        if (ttd == NULL) {
+                tips = gtk_tooltips_new ();
+        } else {
+                tips = ttd->tooltips;
+        }
+
+        tip_str = NULL;
+        g_object_get (action, "tooltip", &tip_str, NULL);
+
+        /* TODO: if there is no tooltip the tip_str is NULL.
+         * Unfortunately it seems that the tooltip isn't
+         * cleared.. mmm.. gtk+ bug?
+         */
+        gtk_tooltips_set_tip (tips, widget, tip_str, tip_str);
+        g_free (tip_str);
+}
+
+static void
+_update_label (PolKitGnomeAction *action, GParamSpec *arg1, GtkWidget *widget)
+{
+        char *label;
+
+        label = NULL;
+        g_object_get (action, "label", &label, NULL);
+        gtk_button_set_label (GTK_BUTTON (widget), label);
+        g_free (label);
+}
+
+static void
+_update_icon_name (PolKitGnomeAction *action, GParamSpec *arg1, GtkWidget *widget)
+{
+        gtk_button_set_image (GTK_BUTTON (widget), gtk_action_create_icon (GTK_ACTION (action), GTK_ICON_SIZE_BUTTON));
+}
+
+static void 
+_button_clicked (GtkButton *button, PolKitGnomeAction *action)
+{
+        /* g_debug ("in _button_clicked"); */
+
+        switch (action->priv->pk_result) {
+        case POLKIT_RESULT_YES:
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                /* g_debug ("blocking clicked"); */
+                g_signal_stop_emission_by_name (button, "clicked");
+                break;
+
+        default:
+        case POLKIT_RESULT_NO:
+                break;
+        }
+}
+
+static void 
+_button_auth_end (PolKitGnomeAction *action, gboolean gained_privilege, GtkWidget *button)
+{
+        /* g_debug ("in _button_auth_end gained_privilege=%d", gained_privilege); */
+        if (gained_privilege) {
+                /* g_debug ("emitting clicked"); */
+                gtk_action_block_activate_from (GTK_ACTION (action), button);
+                g_signal_emit_by_name (button, "clicked");
+                gtk_action_unblock_activate_from (GTK_ACTION (action), button);
+        }
+}
+
+/**
+ * polkit_gnome_action_create_button:
+ * @action: The #PolKitGnomeAction object
+ *
+ * Create a button for the given action that displays the label,
+ * tooltip and icon_name corresponding to whether the state, according
+ * to PolicyKit, is no, auth or yes.
+ * 
+ * Returns: A #GtkButton instance connected to the action
+ */
+GtkWidget *
+polkit_gnome_action_create_button (PolKitGnomeAction *action)
+{
+        GtkWidget *button;
+
+        button = gtk_button_new ();
+
+        gtk_action_connect_proxy (GTK_ACTION (action), button);
+
+        _update_label (action, NULL, button);
+        _update_tooltips (action, NULL, button);
+        _update_icon_name (action, NULL, button);
+
+        g_signal_connect (action, "notify::tooltip", G_CALLBACK (_update_tooltips), button);
+        g_signal_connect (action, "notify::label", G_CALLBACK (_update_label), button);
+        g_signal_connect (action, "notify::icon-name", G_CALLBACK (_update_icon_name), button);
+
+        /* hook into the ::clicked signal and block it unless
+         * PolicyKit says it's good to go. This is necessary when the
+         * button is embedded in e.g. a GtkDialog since that class
+         * hooks in ::clicked signals from GtkButton instances...
+         *
+         * Also, hook into ::auth_end signal from the
+         * PolKitGnomeAction and synthesize ::clicked the signal if
+         * the privilege was gained..
+         */
+        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);
+        g_signal_connect (action, "auth-end", G_CALLBACK (_button_auth_end), button);
+
+        return button;
+}

Added: trunk/polkit-gnome/polkit-gnome-action.h
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-action.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-action.h : 
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#if !defined (POLKIT_GNOME_COMPILATION) && !defined(_POLKIT_GNOME_INSIDE_POLKIT_GNOME_H)
+#error "Only <polkit-gnome/polkit-gnome.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_GNOME_ACTION_H__
+#define __POLKIT_GNOME_ACTION_H__
+
+#include <gtk/gtk.h>
+#include <polkit/polkit.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_GNOME_TYPE_ACTION            (polkit_gnome_action_get_type ())
+#define POLKIT_GNOME_ACTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), POLKIT_GNOME_TYPE_ACTION, PolKitGnomeAction))
+#define POLKIT_GNOME_ACTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), POLKIT_GNOME_TYPE_ACTION, PolKitGnomeActionClass))
+#define POLKIT_GNOME_IS_ACTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POLKIT_GNOME_TYPE_ACTION))
+#define POLKIT_GNOME_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), POLKIT_GNOME_TYPE_ACTION))
+#define POLKIT_GNOME_ACTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), POLKIT_GNOME_TYPE_ACTION, PolKitGnomeActionClass))
+
+typedef struct _PolKitGnomeAction        PolKitGnomeAction;
+typedef struct _PolKitGnomeActionPrivate PolKitGnomeActionPrivate;
+typedef struct _PolKitGnomeActionClass   PolKitGnomeActionClass;
+
+/**
+ * PolKitGnomeAction:
+ *
+ * The PolKitGnomeAction struct contains only private data members and should not be accessed directly.
+ */
+struct _PolKitGnomeAction
+{
+        /*< private >*/
+        GtkAction parent;        
+        PolKitGnomeActionPrivate *priv;
+};
+
+struct _PolKitGnomeActionClass
+{
+        GtkActionClass parent_class;
+
+        /* Signals */
+        void (* auth_start) (PolKitGnomeAction *action);
+        void (* auth_end) (PolKitGnomeAction *action, gboolean gained_privilege);
+        void (* polkit_result_changed) (PolKitGnomeAction *action, PolKitResult current_result);
+
+        /* Padding for future expansion */
+        void (*_reserved1) (void);
+        void (*_reserved2) (void);
+        void (*_reserved3) (void);
+        void (*_reserved4) (void);
+};
+
+GType              polkit_gnome_action_get_type          (void) G_GNUC_CONST;
+PolKitGnomeAction *polkit_gnome_action_new               (const gchar           *name);
+PolKitGnomeAction *polkit_gnome_action_new_default       (const gchar           *name, 
+                                                          PolKitAction          *polkit_action, 
+                                                          const gchar           *label, 
+                                                          const gchar           *tooltip);
+PolKitResult       polkit_gnome_action_get_polkit_result (PolKitGnomeAction     *action);
+
+gboolean           polkit_gnome_action_get_sensitive          (PolKitGnomeAction     *action);
+void               polkit_gnome_action_set_sensitive          (PolKitGnomeAction     *action,
+                                                               gboolean               sensitive);
+
+gboolean           polkit_gnome_action_get_visible            (PolKitGnomeAction     *action);
+void               polkit_gnome_action_set_visible            (PolKitGnomeAction     *action,
+                                                               gboolean               visible);
+
+GtkWidget         *polkit_gnome_action_create_button        (PolKitGnomeAction     *action);
+
+G_END_DECLS
+
+#endif  /* __POLKIT_GNOME_ACTION_H__ */

Added: trunk/polkit-gnome/polkit-gnome-auth.c
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-auth.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,167 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-auth.c : Show authentication dialogs to gain privileges
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "polkit-gnome-auth.h"
+
+/**
+ * SECTION:polkit-gnome-auth
+ * @title: Authentication Dialogs
+ * @short_description: Show authentication dialogs to gain privileges
+ *
+ * Show authentication dialogs to gain privileges.
+ *
+ **/
+
+
+typedef struct {
+        PolKitAction *action;
+        PolKitGnomeAuthCB callback;
+        gpointer user_data;
+} CallClosure;
+
+static void
+_notify_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
+{
+        GError *error;
+        CallClosure *c = (CallClosure *) user_data;
+        gboolean gained_privilege;
+
+        error = NULL;
+        if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_BOOLEAN, &gained_privilege, G_TYPE_INVALID)) {
+                gained_privilege = FALSE;
+        }
+
+        /* perform the callback */
+        c->callback (c->action, gained_privilege, error, c->user_data);
+
+        g_object_unref (proxy);
+        polkit_action_unref (c->action);
+}
+
+/**
+ * polkit_gnome_auth_obtain:
+ * @action: The #PolKitAction to make the user authenticate for
+ * @xid: X11 window ID for the window that the dialog will be transient for. If there is no window, pass 0.
+ * @pid: Process ID of process to grant authorization to. Normally one wants to pass result of getpid().
+ * @callback: Function to call when authentication is done
+ * @user_data: Data to pass to the callback function
+ * @error: Return location for error
+ *
+ * Applications can use this function to show a dialog for the user
+ * asking her to authenticate in order to gain privileges to do the
+ * given action. The authentication, for security reasons, happens in
+ * a separate process; this function is merely a wrapper around a
+ * D-Bus call across the session message bus to the
+ * <literal>org.freedesktop.PolicyKit.AuthenticationAgent</literal>
+ * service. Depending on the setup, this may be the Authentication
+ * Agent shipped with PolicyKit-gnome or it may be another
+ * implementation. For example, if the user is in KDE it may be an
+ * Authentication Agent using the Qt toolkit.
+ *
+ * The Authentication Agent shipped with PolicyKit-gnome is described
+ * in <link linkend="ref-auth-daemon">this section</link>.
+ *
+ * This function is similar to the polkit_auth_obtain() function
+ * supplied in <literal>libpolkit-dbus</literal> except that this
+ * function is asynchronous.
+ *
+ * Returns: #TRUE if the authentication session was scheduled to
+ * start. #FALSE if error is set (and no callback will be made).
+ */
+gboolean 
+polkit_gnome_auth_obtain (PolKitAction *action, 
+                          guint xid,
+                          pid_t pid,
+                          PolKitGnomeAuthCB callback, 
+                          gpointer user_data, 
+                          GError **error)
+{
+        char *polkit_action_id;
+        gboolean ret;
+        CallClosure *c;
+        DBusGConnection *session_bus;
+        DBusGProxy *polkit_gnome_proxy;
+
+        ret = FALSE;
+
+        if ((session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, error)) == NULL) {
+                goto error;
+        }
+
+        /* TODO: this can fail.. */
+        polkit_action_get_action_id (action, &polkit_action_id);
+
+	polkit_gnome_proxy = dbus_g_proxy_new_for_name (session_bus,
+                                                        "org.freedesktop.PolicyKit.AuthenticationAgent", /* bus name */
+                                                        "/",                                             /* object */
+                                                        "org.freedesktop.PolicyKit.AuthenticationAgent");/* interface */
+
+        c = g_new0 (CallClosure, 1);
+        c->action = polkit_action_ref (action);
+        c->callback = callback;
+        c->user_data = user_data;
+
+        dbus_g_proxy_begin_call_with_timeout (polkit_gnome_proxy,
+                                              "ObtainAuthorization",
+                                              _notify_callback,
+                                              c,
+                                              g_free,
+                                              INT_MAX,
+                                              /* parameters: */
+                                              G_TYPE_STRING, polkit_action_id,  /* action_id */
+                                              G_TYPE_UINT, xid,                 /* X11 window ID */
+                                              G_TYPE_UINT, pid,                 /* process id */
+                                              G_TYPE_INVALID);
+
+        ret = TRUE;
+error:
+        return ret;
+}
+

Added: trunk/polkit-gnome/polkit-gnome-auth.h
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-auth.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-auth.h : Show authentication dialogs to gain privileges
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#if !defined (POLKIT_GNOME_COMPILATION) && !defined(_POLKIT_GNOME_INSIDE_POLKIT_GNOME_H)
+#error "Only <polkit-gnome/polkit-gnome.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_GNOME_AUTH_H
+#define __POLKIT_GNOME_AUTH_H
+
+#include <polkit/polkit.h>
+
+/**
+ * PolKitGnomeAuthCB:
+ * @action: the #PolKitAction passed in polkit_gnome_auth_show_dialog()
+ * @gained_privilege: whether the user gained the privilege. Set to
+ * #FALSE if error is set. If set to #TRUE, error will not be set.
+ * @error: if the call failed, this parameter will be non-#NULL. The
+ * callee shall free the error.
+ * @user_data: user data
+ *
+ * The type of the callback function for
+ * polkit_gnome_auth_show_dialog().
+ */
+typedef void (*PolKitGnomeAuthCB) (PolKitAction *action, gboolean gained_privilege, GError *error, gpointer user_data);
+
+gboolean polkit_gnome_auth_obtain (PolKitAction *action, 
+                                   guint xid, 
+                                   pid_t pid,
+                                   PolKitGnomeAuthCB callback, 
+                                   gpointer user_data, 
+                                   GError **error);
+
+#endif /* __POLKIT_GNOME_AUTH_H */

Added: trunk/polkit-gnome/polkit-gnome-context.c
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-context.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,370 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-context.c : Convenience functions for using PolicyKit
+ * from GTK+ and GNOME applications.
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+#include "polkit-gnome-context.h"
+
+/**
+ * SECTION:polkit-gnome-context
+ * @short_description: Convenience functions for using PolicyKit from GTK+ and GNOME applications.
+ *
+ * This class provides convenience functions for using PolicyKit from
+ * GTK+ and GNOME applications including setting up main loop
+ * integration and system bus connections. Rather than using
+ * callbacks, GObject signals are provided when external factors
+ * change (e.g. the PolicyKit.conf configuration file changes or
+ * ConsoleKit reports activity changes).
+ *
+ * Actual usage of PolicyKit is still through the main PolicyKit API
+ * through the public pk_context and pk_tracker variables.
+ *
+ * This class is implemented as a singleton meaning that several
+ * callers will share the underlying #PolKitContext and #PolKitTracker
+ * objects. Do not use any of the life cycle methods of these objects;
+ * only use them to gather information.
+ **/
+
+#define POLKIT_GNOME_CONTEXT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), POLKIT_GNOME_TYPE_CONTEXT, PolKitGnomeContextPrivate))
+
+struct _PolKitGnomeContextPrivate 
+{
+        DBusGConnection *system_bus;
+};
+
+enum 
+{
+        CONFIG_CHANGED,
+        CONSOLE_KIT_DB_CHANGED,
+        LAST_SIGNAL
+};
+
+/* our static singleton instance */
+static PolKitGnomeContext *_singleton = NULL;
+
+G_DEFINE_TYPE (PolKitGnomeContext, polkit_gnome_context, G_TYPE_OBJECT)
+
+static GObjectClass *parent_class = NULL;
+static guint         signals[LAST_SIGNAL] = { 0 };
+
+static void
+polkit_gnome_context_init (PolKitGnomeContext *context)
+{
+        context->priv = POLKIT_GNOME_CONTEXT_GET_PRIVATE (context);
+}
+
+static void
+polkit_gnome_context_finalize (GObject *object)
+{
+        PolKitGnomeContext *context;
+
+        context = POLKIT_GNOME_CONTEXT (object);
+
+        /* Remove the match rules we added; pass NULL for error so we
+         * don't block; we can't really properly handle the error
+         * anyway...
+         */
+	dbus_bus_remove_match (dbus_g_connection_get_connection (_singleton->priv->system_bus),
+                               "type='signal'"
+                               ",interface='"DBUS_INTERFACE_DBUS"'"
+                               ",sender='"DBUS_SERVICE_DBUS"'"
+                               ",member='NameOwnerChanged'",
+                               NULL);
+	dbus_bus_remove_match (dbus_g_connection_get_connection (_singleton->priv->system_bus),
+                               "type='signal',sender='org.freedesktop.ConsoleKit'",
+                               NULL);
+
+        if (context->pk_context != NULL) {
+                polkit_context_unref (context->pk_context);
+        }
+
+        if (context->pk_tracker != NULL) {
+                polkit_tracker_unref (context->pk_tracker);
+        }
+
+        _singleton = NULL;
+
+        G_OBJECT_CLASS (polkit_gnome_context_parent_class)->finalize (object);
+}
+
+static void
+polkit_gnome_context_class_init (PolKitGnomeContextClass *klass)
+{
+        GObjectClass *gobject_class;
+
+        parent_class = g_type_class_peek_parent (klass);
+        gobject_class = G_OBJECT_CLASS (klass);
+
+        gobject_class->finalize = polkit_gnome_context_finalize;
+
+        /**
+         * PolKitGnomeContext::config-changed:
+         * @context: the object
+         *
+         * The ::config-changed signal is emitted when PolicyKit
+         * configuration (e.g. /etc/PolicyKit/PolicyKit.conf or
+         * .policy files) changes content.
+         *
+         * As this is one contributing factor to what answer PolicyKit
+         * will return, the caller should act on this signal and query
+         * PolicyKit for any actions it cares about.
+         **/
+        signals [CONFIG_CHANGED] =
+                g_signal_new ("config-changed",
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (PolKitGnomeContextClass, config_changed),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+
+        /**
+         * PolKitGnomeContext::console-kit-db-changed:
+         * @context: the object
+         *
+         * The ::console-kit-db-changed signal is emitted when
+         * ConsoleKit configuration changes; e.g. when a session
+         * becomes active or inactive.
+         *
+         * As this is one contributing factor to what answer PolicyKit
+         * will return, the caller should act on this signal and query
+         * PolicyKit for any actions it cares about.
+         **/
+        signals [CONSOLE_KIT_DB_CHANGED] =
+                g_signal_new ("console-kit-db-changed",
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (PolKitGnomeContextClass, console_kit_db_changed),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+
+        g_type_class_add_private (gobject_class, sizeof (PolKitGnomeContextPrivate));
+}
+
+
+static gboolean
+io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+        int fd;
+        PolKitContext *pk_context = user_data;
+        fd = g_io_channel_unix_get_fd (channel);
+        polkit_context_io_func (pk_context, fd);
+        return TRUE;
+}
+
+static int 
+io_add_watch (PolKitContext *pk_context, int fd)
+{
+        guint id = 0;
+        GIOChannel *channel;
+        channel = g_io_channel_unix_new (fd);
+        if (channel == NULL)
+                goto out;
+        id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, pk_context);
+        if (id == 0) {
+                g_io_channel_unref (channel);
+                goto out;
+        }
+        g_io_channel_unref (channel);
+out:
+        return id;
+}
+
+static void 
+io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+        g_source_remove (watch_id);
+}
+
+
+static void
+pk_config_changed (PolKitContext *pk_context, void *user_data)
+{
+        PolKitGnomeContext *context = POLKIT_GNOME_CONTEXT (user_data);
+
+        /* g_debug ("ggg PolicyKit config changed"); */
+        g_signal_emit (context, signals [CONFIG_CHANGED], 0);
+}
+
+
+static DBusHandlerResult
+_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+        PolKitGnomeContext *context = POLKIT_GNOME_CONTEXT (user_data);
+
+        /*  pass NameOwnerChanged signals from the bus and ConsoleKit to PolKitTracker */
+        if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged") ||
+            (dbus_message_get_interface (message) != NULL &&
+             g_str_has_prefix (dbus_message_get_interface (message), "org.freedesktop.ConsoleKit"))) {
+                if (polkit_tracker_dbus_func (context->pk_tracker, message)) {
+                        /* The ConsoleKit database has changed */
+                        /* g_debug ("ggg ConsoleKit database changed"); */
+                        g_signal_emit (context, signals [CONSOLE_KIT_DB_CHANGED], 0);
+                }
+        }
+
+        /* other filters might want to process this message too */
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/**
+ * polkit_gnome_context_get:
+ * @error: return location for error
+ *
+ * Returns a #PolKitGnomeContext object. The context is a global
+ * singleton that may be shared with other callers of this function.
+ *
+ * This operation can fail if the system message bus is not available.
+ *
+ * When done with using this object, call g_object_unref(). This is
+ * such that resources can be freed when all callers have unreffed it.
+ *
+ * Returns: a new #PolKitGnomeContext or NULL if error is set
+ */
+PolKitGnomeContext *
+polkit_gnome_context_get (GError **error)
+{
+        DBusError dbus_error;
+        PolKitError *pk_error;
+
+        if (_singleton != NULL)
+                return g_object_ref (_singleton);
+
+        /* g_debug ("Constructing singleton"); */
+
+        _singleton = g_object_new (POLKIT_GNOME_TYPE_CONTEXT, NULL);
+
+        if ((_singleton->priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, error)) == NULL) {
+                goto error;
+        }
+
+        _singleton->pk_context = polkit_context_new ();
+        polkit_context_set_io_watch_functions (_singleton->pk_context, io_add_watch, io_remove_watch);
+        polkit_context_set_config_changed (_singleton->pk_context, pk_config_changed, _singleton);
+
+        pk_error = NULL;
+        if (!polkit_context_init (_singleton->pk_context, &pk_error)) {
+                g_warning ("Failed to initialize PolicyKit context: %s", polkit_error_get_error_message (pk_error));
+                if (error != NULL) {
+                        *error = g_error_new_literal (POLKIT_GNOME_CONTEXT_ERROR,
+                                                      POLKIT_GNOME_CONTEXT_ERROR_FAILED,
+                                                      polkit_error_get_error_message (pk_error));
+                }
+                polkit_error_free (pk_error);
+                goto error;
+        }
+
+        /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
+         * we can't say we're interested in all signals from all
+         * members on all interfaces for a given service... So we do
+         * this..
+         */
+
+        dbus_error_init (&dbus_error);
+
+        /* need to listen to NameOwnerChanged */
+	dbus_bus_add_match (dbus_g_connection_get_connection (_singleton->priv->system_bus),
+			    "type='signal'"
+			    ",interface='"DBUS_INTERFACE_DBUS"'"
+			    ",sender='"DBUS_SERVICE_DBUS"'"
+			    ",member='NameOwnerChanged'",
+			    &dbus_error);
+
+        if (dbus_error_is_set (&dbus_error)) {
+                dbus_set_g_error (error, &dbus_error);
+                dbus_error_free (&dbus_error);
+                goto error;
+        }
+
+        /* need to listen to ConsoleKit signals */
+	dbus_bus_add_match (dbus_g_connection_get_connection (_singleton->priv->system_bus),
+			    "type='signal',sender='org.freedesktop.ConsoleKit'",
+			    &dbus_error);
+
+        if (dbus_error_is_set (&dbus_error)) {
+                dbus_set_g_error (error, &dbus_error);
+                dbus_error_free (&dbus_error);
+                goto error;
+        }
+
+        if (!dbus_connection_add_filter (dbus_g_connection_get_connection (_singleton->priv->system_bus), 
+                                         _filter, 
+                                         _singleton, 
+                                         NULL)) {
+                *error = g_error_new_literal (POLKIT_GNOME_CONTEXT_ERROR,
+                                              POLKIT_GNOME_CONTEXT_ERROR_FAILED,
+                                              "Cannot add D-Bus filter");
+                goto error;
+        }        
+
+        _singleton->pk_tracker = polkit_tracker_new ();
+        polkit_tracker_set_system_bus_connection (_singleton->pk_tracker, 
+                                                  dbus_g_connection_get_connection (_singleton->priv->system_bus));
+        polkit_tracker_init (_singleton->pk_tracker);
+
+        return _singleton;
+
+error:
+        g_object_unref (_singleton);
+        return NULL;
+}
+
+GQuark
+polkit_gnome_context_error_quark (void)
+{
+        return g_quark_from_static_string ("polkit-gnome-context-error-quark");
+}

Added: trunk/polkit-gnome/polkit-gnome-context.h
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-context.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,111 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-context.h : Convenience functions for using PolicyKit
+ * from GTK+ and GNOME applications.
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#if !defined (POLKIT_GNOME_COMPILATION) && !defined(_POLKIT_GNOME_INSIDE_POLKIT_GNOME_H)
+#error "Only <polkit-gnome/polkit-gnome.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_GNOME_CONTEXT_H__
+#define __POLKIT_GNOME_CONTEXT_H__
+
+#include <glib-object.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_GNOME_TYPE_CONTEXT            (polkit_gnome_context_get_type ())
+#define POLKIT_GNOME_CONTEXT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), POLKIT_GNOME_TYPE_CONTEXT, PolKitGnomeContext))
+#define POLKIT_GNOME_CONTEXT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), POLKIT_GNOME_TYPE_CONTEXT, PolKitGnomeContextClass))
+#define POLKIT_GNOME_IS_CONTEXT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POLKIT_GNOME_TYPE_CONTEXT))
+#define POLKIT_GNOME_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), POLKIT_GNOME_TYPE_CONTEXT))
+#define POLKIT_GNOME_CONTEXT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), POLKIT_GNOME_TYPE_CONTEXT, PolKitGnomeContextClass))
+
+/**
+ * POLKIT_GNOME_CONTEXT_ERROR:
+ *
+ * Error domain for using the GNOME PolicyKit context. Errors in this
+ * domain will be from the #PolKitGnomeContextError enumeration. See
+ * #GError for information on error domains.
+ */
+#define POLKIT_GNOME_CONTEXT_ERROR polkit_gnome_context_error_quark ()
+
+/**
+ * PolKitGnomeContextError:
+ * @POLKIT_GNOME_CONTEXT_ERROR_FAILED: General error
+ *
+ * Error codes describing how #PolKitGnomeContext can fail.
+ */
+typedef enum
+{
+        POLKIT_GNOME_CONTEXT_ERROR_FAILED
+} PolKitGnomeContextError;
+
+
+typedef struct _PolKitGnomeContext        PolKitGnomeContext;
+typedef struct _PolKitGnomeContextPrivate PolKitGnomeContextPrivate;
+typedef struct _PolKitGnomeContextClass   PolKitGnomeContextClass;
+
+/**
+ * PolKitGnomeContext:
+ * @pk_context: for interfacing with PolicyKit; e.g. typically polkit_context_can_caller_do_action()
+ * @pk_tracker: this is used for effieciently obtaining #PolKitCaller objects
+ *
+ * Provide access to #PolKitContext and #PolKitTracker instances
+ * shared among many callers.
+ */
+struct _PolKitGnomeContext
+{
+        /*< private >*/
+        GObject parent;
+
+        PolKitGnomeContextPrivate *priv;
+
+        /*< public >*/
+        PolKitContext *pk_context;
+        PolKitTracker *pk_tracker;
+};
+
+struct _PolKitGnomeContextClass
+{
+        GObjectClass parent_class;
+
+        void (* config_changed) (PolKitGnomeContext *context);
+        void (* console_kit_db_changed) (PolKitGnomeContext *context);
+
+        /* Padding for future expansion */
+        void (*_reserved1) (void);
+        void (*_reserved2) (void);
+        void (*_reserved3) (void);
+        void (*_reserved4) (void);
+};
+
+GType               polkit_gnome_context_get_type (void) G_GNUC_CONST;
+PolKitGnomeContext *polkit_gnome_context_get      (GError **error);
+
+GQuark polkit_gnome_context_error_quark (void);
+
+G_END_DECLS
+
+#endif  /* __POLKIT_GNOME_CONTEXT_H__ */

Added: trunk/polkit-gnome/polkit-gnome-toggle-action.c
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-toggle-action.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,929 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-toggle-action.c : 
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * Based loosely on gtk/gtktoggleaction.c from GTK+ written by James
+ * Henstridge <james daa com au>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+#include "polkit-gnome-toggle-action.h"
+
+/**
+ * SECTION:polkit-gnome-toggle-action
+ * @short_description: A GtkAction that can be toggled to
+ * obtain and give up PolicyKit authorizations.
+ *
+ * For an example of how to use this class, see the documentation for
+ * #PolKitGnomeAction.
+ **/
+
+#define POLKIT_GNOME_TOGGLE_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), POLKIT_GNOME_TYPE_TOGGLE_ACTION, PolKitGnomeToggleActionPrivate))
+
+struct _PolKitGnomeToggleActionPrivate 
+{
+        gboolean active;
+        gboolean am_authenticating;
+
+        gboolean auth_underway_visible;
+        gboolean auth_underway_sensitive;
+        gchar *auth_underway_short_label;
+        gchar *auth_underway_label;
+        gchar *auth_underway_tooltip;
+        gchar *auth_underway_icon_name;
+};
+
+enum 
+{
+        TOGGLED_SIGNAL,
+        LAST_SIGNAL
+};
+
+enum
+{
+        PROP_0,
+        PROP_POLKIT_AUTH_UNDERWAY_VISIBLE,
+        PROP_POLKIT_AUTH_UNDERWAY_SENSITIVE,
+        PROP_POLKIT_AUTH_UNDERWAY_SHORT_LABEL,
+        PROP_POLKIT_AUTH_UNDERWAY_LABEL,
+        PROP_POLKIT_AUTH_UNDERWAY_TOOLTIP,
+        PROP_POLKIT_AUTH_UNDERWAY_ICON_NAME,
+};
+
+G_DEFINE_TYPE (PolKitGnomeToggleAction, polkit_gnome_toggle_action, POLKIT_GNOME_TYPE_ACTION)
+
+static void set_property                   (GObject         *object,
+					    guint            prop_id,
+					    const GValue    *value,
+					    GParamSpec      *pspec);
+static void get_property                   (GObject         *object,
+					    guint            prop_id,
+					    GValue          *value,
+					    GParamSpec      *pspec);
+
+static GObjectClass *parent_class = NULL;
+static guint         signals[LAST_SIGNAL] = { 0 };
+
+static void
+polkit_gnome_toggle_action_init (PolKitGnomeToggleAction *toggle_action)
+{
+        toggle_action->priv = POLKIT_GNOME_TOGGLE_ACTION_GET_PRIVATE (toggle_action);
+
+}
+
+static void
+polkit_gnome_toggle_action_finalize (GObject *object)
+{
+        PolKitGnomeToggleAction *toggle_action;
+
+        toggle_action = POLKIT_GNOME_TOGGLE_ACTION (object);
+
+        G_OBJECT_CLASS (polkit_gnome_toggle_action_parent_class)->finalize (object);
+}
+
+static GObject *
+polkit_gnome_toggle_action_constructor (GType                  type,
+                                        guint                  n_construct_properties,
+                                        GObjectConstructParam *construct_properties)
+{
+        PolKitGnomeToggleAction      *toggle_action;
+        PolKitGnomeToggleActionClass *klass;
+
+        klass = POLKIT_GNOME_TOGGLE_ACTION_CLASS (g_type_class_peek (POLKIT_GNOME_TYPE_TOGGLE_ACTION));
+
+        toggle_action = POLKIT_GNOME_TOGGLE_ACTION (G_OBJECT_CLASS (parent_class)->constructor (type,
+                                                                                   n_construct_properties,
+                                                                                   construct_properties));
+
+        if (polkit_gnome_action_get_polkit_result (POLKIT_GNOME_ACTION (toggle_action)) == POLKIT_RESULT_YES)
+                toggle_action->priv->active = TRUE;
+        else
+                toggle_action->priv->active = FALSE;
+
+        return G_OBJECT (toggle_action);
+}
+
+static void polkit_gnome_toggle_action_auth_end (PolKitGnomeToggleAction *toggle_action, gboolean gained_privilege);
+static void polkit_gnome_toggle_polkit_result_changed (PolKitGnomeToggleAction *toggle_action, PolKitResult current_result);
+static void polkit_gnome_toggle_action_activate (PolKitGnomeToggleAction *toggle_action);
+static void polkit_gnome_toggle_action_real_toggled (PolKitGnomeToggleAction *action);
+static void connect_proxy                  (GtkAction       *action,
+					    GtkWidget       *proxy);
+static void disconnect_proxy               (GtkAction       *action,
+					    GtkWidget       *proxy);
+
+
+static void
+polkit_gnome_toggle_action_class_init (PolKitGnomeToggleActionClass *klass)
+{
+        GObjectClass *gobject_class;
+        GtkActionClass *action_class;
+        PolKitGnomeActionClass *polkit_gnome_action_class;
+
+        parent_class = g_type_class_peek_parent (klass);
+        gobject_class = G_OBJECT_CLASS (klass);
+        action_class = GTK_ACTION_CLASS (klass);
+        polkit_gnome_action_class = POLKIT_GNOME_ACTION_CLASS (klass);
+
+        gobject_class->constructor = polkit_gnome_toggle_action_constructor;
+        gobject_class->set_property = set_property;
+        gobject_class->get_property = get_property;
+        gobject_class->finalize = polkit_gnome_toggle_action_finalize;
+
+        action_class->menu_item_type = GTK_TYPE_CHECK_MENU_ITEM;
+        action_class->toolbar_item_type = GTK_TYPE_TOGGLE_TOOL_BUTTON;
+
+        action_class->connect_proxy = connect_proxy;
+        action_class->disconnect_proxy = disconnect_proxy;
+
+        klass->toggled = polkit_gnome_toggle_action_real_toggled;
+
+        action_class->activate = (void (*)(GtkAction*)) polkit_gnome_toggle_action_activate;
+
+        polkit_gnome_action_class->auth_end = 
+                (void (*)(PolKitGnomeAction *, gboolean)) polkit_gnome_toggle_action_auth_end;
+
+        polkit_gnome_action_class->polkit_result_changed = 
+                (void (*) (PolKitGnomeAction *, PolKitResult)) polkit_gnome_toggle_polkit_result_changed;
+
+        /*------------------------------*/
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_UNDERWAY_VISIBLE,
+                g_param_spec_boolean (
+                        "auth-underway-visible",
+                        "When authentication is underway, whether the action will be visible",
+                        "When authentication is underway, whether the action will be visible",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_UNDERWAY_SENSITIVE,
+                g_param_spec_boolean (
+                        "auth-underway-sensitive",
+                        "When authentication is underway, whether the action will be sensitive",
+                        "When authentication is underway, whether the action will be sensitive",
+                        TRUE,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_UNDERWAY_SHORT_LABEL,
+                g_param_spec_string (
+                        "auth-underway-short-label",
+                        "When authentication is underway, use this short-label",
+                        "When authentication is underway, use this short-label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_UNDERWAY_LABEL,
+                g_param_spec_string (
+                        "auth-underway-label",
+                        "When authentication is underway, use this label",
+                        "When authentication is underway, use this label",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_UNDERWAY_TOOLTIP,
+                g_param_spec_string (
+                        "auth-underway-tooltip",
+                        "When authentication is underway, use this tooltip",
+                        "When authentication is underway, use this tooltip",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        g_object_class_install_property (
+                gobject_class,
+                PROP_POLKIT_AUTH_UNDERWAY_ICON_NAME,
+                g_param_spec_string (
+                        "auth-underway-icon-name",
+                        "When authentication is underway, use this icon-name",
+                        "When authentication is underway, use this icon-name",
+                        NULL,
+                        G_PARAM_READWRITE));
+
+        /*------------------------------*/
+
+
+        /**
+         * PolKitGnomeToggleAction::toggled:
+         * @toggle_action: the object
+         *
+         * The ::toggled signal is emitted when the button is toggled.
+         **/
+        signals [TOGGLED_SIGNAL] =
+                g_signal_new ("toggled",
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (PolKitGnomeToggleActionClass, toggled),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+
+        g_type_class_add_private (gobject_class, sizeof (PolKitGnomeToggleActionPrivate));
+}
+
+
+/**
+ * polkit_gnome_toggle_action_new:
+ * @name: A unique name for the toggle_action
+ * @error: Return location for error
+ *
+ * Creates a new #PolKitGnomeToggleAction object. The typical use for
+ * this function is for specialized use where
+ * polkit_gnome_toggle_action_new_default() does not meet the needs of
+ * the application.
+ *
+ * If the 'polkit-toggle_action' property is #NULL the behavior is similar to
+ * as if a #PolKitAction returned #POLKIT_RESULT_YES.
+ *
+ * Returns: a new #PolKitGnomeToggleAction or #NULL if error is set
+ */
+PolKitGnomeToggleAction *
+polkit_gnome_toggle_action_new (const gchar *name)
+{
+        PolKitGnomeToggleAction *toggle_action = NULL;
+
+        toggle_action = g_object_new (POLKIT_GNOME_TYPE_TOGGLE_ACTION,
+                                      "name", name,
+                                      NULL);
+        return toggle_action;
+}
+
+/**
+ * polkit_gnome_toggle_action_new_default:
+ * @name: A unique name for the toggle_action
+ * @polkit_action: the #PolKitAction to track
+ * @locked_label: The label to show when the user do not possess the
+ * authorization, e.g. "Click to make changes"
+ * @unlocked_label: The label to show when the user does posses the
+ * authorization; e.g. "Click to prevent changes"
+ *
+ * Creates a new #PolKitGnomeToggleAction object with the default
+ * behavior for a given #PolKitAction object. The toggle represents
+ * whether the user is authorized for the given #PolKitAction. If the
+ * user is not authorized, clicking on a proxy widget (if it's
+ * sensitive) will cause an authentication dialog to appear. If the
+ * user is authorized, clicking on a proxy widget will cause all
+ * authorizations to be given up (aka revoked). The ::toggled signal
+ * is only emitted when such transitions occur. Thus, the user of this
+ * class will never have to deal with bringing up authentication
+ * dialogs; it's all handled behind the scenes.
+ *
+ * As such, the typical use case for this action is an UI where the
+ * user is encouraged to give up authorizations.
+ *
+ * There's also support for the corner case where the user is
+ * authorized because of implicit authorizations. In this case,
+ * toggling the action will "grant" a negative authorization for the
+ * user. By toggling the action again, the negative authorization will
+ * be revoked.
+ *
+ * Default behavior is defined as having the icon_name be 'stock_lock'
+ * by default except for the YES PolicyKit answer where it's set to
+ * 'stock_lock-open'. No tooltips are set. The label and short-label
+ * will be 'locked_label' everywhere except in the YES state where
+ * it's set to 'unlocked-label'. When authentication is underway, the
+ * label will be "Authenticating..." and icon_name is untouched. If
+ * the PolicyKit answer is NO, sensitivity is set to
+ * #FALSE. Visibility is always set to #TRUE.
+ *
+ * The caller can always modify individual aspects of the
+ * toggle_action after creation, e.g. change the tooltip for the no,
+ * auth and yes states; see the parent class #PolKitGnomeAction. In
+ * addition to the properties in the parent class, this subclass
+ * sports six new properties, "auth-underway-*" to control the look
+ * of proxy widgets when authentication is underway.
+ *
+ * If the given polkit_toggle_action is #NULL the behavior is similar to as
+ * if a #PolKitAction returned #POLKIT_RESULT_YES.
+ *
+ * Returns: a new #PolKitGnomeToggleAction or #NULL if error is set
+ */
+PolKitGnomeToggleAction *
+polkit_gnome_toggle_action_new_default (const gchar  *name, 
+                                        PolKitAction *polkit_action, 
+                                        const gchar  *locked_label, 
+                                        const gchar  *unlocked_label)
+{
+        PolKitGnomeToggleAction *toggle_action;
+
+        toggle_action = g_object_new (POLKIT_GNOME_TYPE_TOGGLE_ACTION,
+                                      "name",             name,
+                                      "polkit-action",    polkit_action,
+                                      
+                                      "self-blocked-visible",     TRUE,
+                                      "self-blocked-sensitive",   TRUE,
+                                      "self-blocked-short-label", locked_label,
+                                      "self-blocked-label",       locked_label,
+                                      "self-blocked-tooltip",     NULL,
+                                      "self-blocked-icon-name",   "stock_lock",
+
+                                      "no-visible",       TRUE,
+                                      "no-sensitive",     FALSE,
+                                      "no-short-label",   locked_label,
+                                      "no-label",         locked_label,
+                                      "no-tooltip",       NULL,
+                                      "no-icon-name",     "stock_lock",
+                                      
+                                      "auth-visible",     TRUE,
+                                      "auth-sensitive",   TRUE,
+                                      "auth-short-label", locked_label,
+                                      "auth-label",       locked_label,
+                                      "auth-tooltip",     NULL,
+                                      "auth-icon-name",   "stock_lock",
+                                      
+                                      "yes-visible",      TRUE,
+                                      "yes-sensitive",    TRUE,
+                                      "yes-short-label",  unlocked_label,
+                                      "yes-label",        unlocked_label,
+                                      "yes-tooltip",      NULL,
+                                      "yes-icon-name",    "stock_lock-open",
+
+                                      "auth-underway-visible",      TRUE,
+                                      "auth-underway-sensitive",    TRUE,
+                                      "auth-underway-short-label",  _("Authenticating..."),
+                                      "auth-underway-label",        _("Authenticating..."),
+                                      "auth-underway-tooltip",      NULL,
+                                      "auth-underway-icon-name",    "stock_lock",
+                                      
+                                      "master-visible",   TRUE,
+                                      "master-sensitive", TRUE,
+                                      NULL);
+        return toggle_action;
+}
+
+/*----------------------------------------------------------------------------------------------------*/
+
+static void
+polkit_gnome_toggle_action_set_auth_underway_visible (PolKitGnomeToggleAction *action, gboolean visible)
+{
+        action->priv->auth_underway_visible = visible;
+}
+
+static void
+polkit_gnome_toggle_action_set_auth_underway_sensitive (PolKitGnomeToggleAction *action, gboolean sensitive)
+{
+        action->priv->auth_underway_sensitive = sensitive;
+}
+
+static void
+polkit_gnome_toggle_action_set_auth_underway_short_label (PolKitGnomeToggleAction *action, const gchar *short_label)
+{
+        g_free (action->priv->auth_underway_short_label);
+        action->priv->auth_underway_short_label = g_strdup (short_label);
+}
+
+static void
+polkit_gnome_toggle_action_set_auth_underway_label (PolKitGnomeToggleAction *action, const gchar *label)
+{
+        g_free (action->priv->auth_underway_label);
+        action->priv->auth_underway_label = g_strdup (label);
+}
+
+static void
+polkit_gnome_toggle_action_set_auth_underway_tooltip (PolKitGnomeToggleAction *action, const gchar *tooltip)
+{
+        g_free (action->priv->auth_underway_tooltip);
+        action->priv->auth_underway_tooltip = g_strdup (tooltip);
+}
+
+static void
+polkit_gnome_toggle_action_set_auth_underway_icon_name (PolKitGnomeToggleAction *action, const gchar *icon_name)
+{
+        g_free (action->priv->auth_underway_icon_name);
+        action->priv->auth_underway_icon_name = g_strdup (icon_name);
+}
+
+static void
+get_property (GObject     *object,
+	      guint        prop_id,
+	      GValue      *value,
+	      GParamSpec  *pspec)
+{
+        PolKitGnomeToggleAction *action = POLKIT_GNOME_TOGGLE_ACTION (object);
+        
+        switch (prop_id)
+        {
+
+        case PROP_POLKIT_AUTH_UNDERWAY_VISIBLE:
+                g_value_set_boolean (value, action->priv->auth_underway_visible);
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_SENSITIVE:
+                g_value_set_boolean (value, action->priv->auth_underway_sensitive);
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_SHORT_LABEL:
+                g_value_set_string (value, action->priv->auth_underway_short_label);
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_LABEL:
+                g_value_set_string (value, action->priv->auth_underway_label);
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_TOOLTIP:
+                g_value_set_string (value, action->priv->auth_underway_tooltip);
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_ICON_NAME:
+                g_value_set_string (value, action->priv->auth_underway_icon_name);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+set_property (GObject      *object,
+	      guint         prop_id,
+	      const GValue *value,
+	      GParamSpec   *pspec)
+{
+        PolKitGnomeToggleAction *action = POLKIT_GNOME_TOGGLE_ACTION (object);
+        
+        switch (prop_id)
+        {
+
+        case PROP_POLKIT_AUTH_UNDERWAY_VISIBLE:
+                polkit_gnome_toggle_action_set_auth_underway_visible (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_SENSITIVE:
+                polkit_gnome_toggle_action_set_auth_underway_sensitive (action, g_value_get_boolean (value));
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_SHORT_LABEL:
+                polkit_gnome_toggle_action_set_auth_underway_short_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_LABEL:
+                polkit_gnome_toggle_action_set_auth_underway_label (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_TOOLTIP:
+                polkit_gnome_toggle_action_set_auth_underway_tooltip (action, g_value_get_string (value));
+                break;
+        case PROP_POLKIT_AUTH_UNDERWAY_ICON_NAME:
+                polkit_gnome_toggle_action_set_auth_underway_icon_name (action, g_value_get_string (value));
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+_set_proxy_state (PolKitGnomeToggleAction *toggle_action)
+{
+        GSList *i;
+
+        for (i = gtk_action_get_proxies (GTK_ACTION (toggle_action)); i; i = i->next) {
+                GtkWidget *proxy = i->data;
+                
+                gtk_action_block_activate_from (GTK_ACTION (toggle_action), proxy);
+                if (GTK_IS_CHECK_MENU_ITEM (proxy))
+                        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
+                                                        toggle_action->priv->active);
+                else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
+                        gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
+                                                           toggle_action->priv->active);
+                else if (GTK_IS_TOGGLE_BUTTON (proxy))
+                        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
+                                                      toggle_action->priv->active);
+                else {
+                        g_warning ("Don't know how to toggle `%s' widgets",
+                                   G_OBJECT_TYPE_NAME (proxy));
+                }
+                gtk_action_unblock_activate_from (GTK_ACTION (toggle_action), proxy);
+        }
+}
+
+static void
+_update_toggled (PolKitGnomeToggleAction *toggle_action)
+{
+        gboolean is_active;
+        
+        g_return_if_fail (POLKIT_GNOME_IS_TOGGLE_ACTION (toggle_action));
+
+        if (polkit_gnome_action_get_polkit_result (POLKIT_GNOME_ACTION (toggle_action)) == POLKIT_RESULT_YES)
+                is_active = TRUE;
+        else
+                is_active = FALSE;
+
+        if (toggle_action->priv->active != is_active) {
+                toggle_action->priv->active = is_active;
+
+                _set_proxy_state (toggle_action);
+
+                g_signal_emit (toggle_action, signals[TOGGLED_SIGNAL], 0);
+        }
+}
+
+static void 
+polkit_gnome_toggle_polkit_result_changed (PolKitGnomeToggleAction *toggle_action, PolKitResult current_result)
+{
+        _update_toggled (toggle_action);
+}
+
+static void 
+polkit_gnome_toggle_action_auth_end (PolKitGnomeToggleAction *toggle_action, gboolean gained_privilege)
+{
+        _update_toggled (toggle_action);
+        toggle_action->priv->am_authenticating = FALSE;
+}
+
+static polkit_bool_t
+_auth_foreach_revoke (PolKitAuthorizationDB *authdb,
+                      PolKitAuthorization   *auth, 
+                      void                  *user_data)
+{
+        PolKitError *pk_error;
+        int *num_auths_revoked = (int *) user_data;
+
+        pk_error = NULL;
+        if (!polkit_authorization_db_revoke_entry (authdb, auth, &pk_error)) {
+                g_warning ("Error revoking authorization: %s: %s\n", 
+                           polkit_error_get_error_name (pk_error),
+                           polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+        }
+
+        if (num_auths_revoked != NULL)
+                *num_auths_revoked += 1;
+        
+        return FALSE;
+}
+
+static void
+polkit_gnome_toggle_action_activate (PolKitGnomeToggleAction *toggle_action)
+{
+        PolKitError *pk_error;
+        PolKitAction *pk_action;
+        PolKitGnomeContext *pkgc;
+        PolKitAuthorizationDB *authdb;
+        PolKitResult pk_result;
+        polkit_bool_t do_not_grant_negative;
+                                
+        pkgc = polkit_gnome_context_get (NULL);
+        authdb = polkit_context_get_authorization_db (pkgc->pk_context);
+
+        pk_action = NULL;
+        g_object_get (toggle_action, "polkit-action", &pk_action, NULL);
+
+        g_return_if_fail (POLKIT_GNOME_IS_TOGGLE_ACTION (toggle_action));
+
+        pk_result = polkit_gnome_action_get_polkit_result (POLKIT_GNOME_ACTION (toggle_action));
+
+        do_not_grant_negative = FALSE;
+reevaluate:
+
+        switch (pk_result) {
+        case POLKIT_RESULT_YES:
+
+                if (!toggle_action->priv->am_authenticating) {
+                        /* If we already got the authorization.. revoke it! */
+                        
+                        if (pk_action != NULL && authdb != NULL) {
+                                int num_auths_revoked;
+                                
+                                pk_error = NULL;
+                                num_auths_revoked = 0;
+                                polkit_authorization_db_foreach_for_action_for_uid (authdb,
+                                                                                    pk_action,
+                                                                                    getuid (),
+                                                                                    _auth_foreach_revoke,
+                                                                                    &num_auths_revoked,
+                                                                                    &pk_error);
+                                if (pk_error != NULL) {
+                                        g_warning ("Error removing authorizations: code=%d: %s",
+                                                   polkit_error_get_error_code (pk_error),
+                                                   polkit_error_get_error_message (pk_error));
+                                        polkit_error_free (pk_error);
+                                }
+
+                                if (pk_error == NULL && num_auths_revoked == 0 && !do_not_grant_negative) {
+                                        /* no authorizations, yet we are authorized.. "grant" a
+                                         * negative authorization...
+                                         */
+                                        
+                                        if (!polkit_authorization_db_grant_negative_to_uid (
+                                                    authdb, 
+                                                    pk_action, 
+                                                    getuid (), 
+                                                    NULL, /* no constraints */
+                                                    &pk_error)) {
+                                                g_warning ("Error granting negative auth: %s: %s\n", 
+                                                           polkit_error_get_error_name (pk_error),
+                                                           polkit_error_get_error_message (pk_error));
+                                                polkit_error_free (pk_error);
+                                        }
+                                }
+                                
+                        }
+
+                        _update_toggled (toggle_action);
+                }
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+
+                g_signal_stop_emission_by_name (toggle_action, "activate");
+
+                if (pk_action != NULL) {
+                        toggle_action->priv->am_authenticating = TRUE;
+
+                        g_object_set (
+                                toggle_action, 
+                                "visible", toggle_action->priv->auth_underway_visible && 
+                                           polkit_gnome_action_get_visible (POLKIT_GNOME_ACTION (toggle_action)),
+                                "sensitive", toggle_action->priv->auth_underway_sensitive &&
+                                             polkit_gnome_action_get_sensitive (POLKIT_GNOME_ACTION (toggle_action)),
+                                "short-label", toggle_action->priv->auth_underway_short_label,
+                                "label", toggle_action->priv->auth_underway_label,
+                                "tooltip", toggle_action->priv->auth_underway_tooltip,
+                                "icon-name", toggle_action->priv->auth_underway_icon_name,
+                                NULL);
+
+                        g_signal_emit_by_name (toggle_action, "auth-start", 0);
+                }
+                break;
+
+        default:
+        case POLKIT_RESULT_NO:
+                if (pk_action != NULL && authdb != NULL) {
+                        if (polkit_authorization_db_is_uid_blocked_by_self (authdb, 
+                                                                            pk_action,
+                                                                            getuid (),
+                                                                            NULL)) {
+                                int num_auths_revoked;
+
+                                /* block granted by self.. revoke it then.. */
+                                pk_error = NULL;
+                                num_auths_revoked = 0;
+                                polkit_authorization_db_foreach_for_action_for_uid (authdb,
+                                                                                    pk_action,
+                                                                                    getuid (),
+                                                                                    _auth_foreach_revoke,
+                                                                                    &num_auths_revoked,
+                                                                                    &pk_error);
+                                if (pk_error != NULL) {
+                                        g_warning ("Error removing authorizations: code=%d: %s",
+                                                   polkit_error_get_error_code (pk_error),
+                                                   polkit_error_get_error_message (pk_error));
+                                        polkit_error_free (pk_error);
+                                }
+
+                                if (pk_error == NULL && num_auths_revoked > 0) {
+                                        PolKitResult pk_result_new;
+
+                                        /* we managed to revoke something... so with this change the
+                                         * result should now change to AUTH_*... so go ahead and just
+                                         * reevaluate the result... also remember to avoid granting
+                                         * another negative auth!
+                                         */
+
+                                        polkit_context_force_reload (pkgc->pk_context);
+                                        pk_result_new = polkit_gnome_action_get_polkit_result (POLKIT_GNOME_ACTION (toggle_action));
+                                        if (pk_result_new != pk_result) {
+                                                pk_result = pk_result_new;
+                                                do_not_grant_negative = TRUE;
+                                                goto reevaluate;
+                                        }
+
+                                }
+
+                        }
+                }
+
+                /* If PolicyKit says no... and we got here.. it means
+                 * that the user set the property "no-sensitive" to
+                 * TRUE.. Otherwise we couldn't be handling this signal.
+                 *
+                 * Hence, they probably have a good reason for doing
+                 * this so do let the 'activate' signal propagate.. 
+                 */
+                break;
+        }
+
+        _set_proxy_state (toggle_action);
+
+        if (pk_action != NULL)
+                polkit_action_unref (pk_action);
+}
+
+static void
+polkit_gnome_toggle_action_real_toggled (PolKitGnomeToggleAction *action)
+{
+        GSList *i;
+        
+        g_return_if_fail (POLKIT_GNOME_IS_TOGGLE_ACTION (action));
+        
+        for (i = gtk_action_get_proxies (GTK_ACTION (action)); i; i = i->next) {
+                GtkWidget *proxy = i->data;
+                
+                gtk_action_block_activate_from (GTK_ACTION (action), proxy);
+                if (GTK_IS_CHECK_MENU_ITEM (proxy))
+                        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
+                                                        action->priv->active);
+                else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
+                        gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
+                                                           action->priv->active);
+                else if (GTK_IS_TOGGLE_BUTTON (proxy))
+                        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
+                                                      action->priv->active);
+                else {
+                        g_warning ("Don't know how to toggle `%s' widgets",
+                                   G_OBJECT_TYPE_NAME (proxy));
+                }
+                gtk_action_unblock_activate_from (GTK_ACTION (action), proxy);
+        }
+}
+
+static void
+connect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+        PolKitGnomeToggleAction *toggle_action;
+        
+        toggle_action = POLKIT_GNOME_TOGGLE_ACTION (action);
+        
+        /* do this before hand, so that we don't call the "activate" handler */
+        if (GTK_IS_CHECK_MENU_ITEM (proxy))
+                gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
+                                                toggle_action->priv->active);
+        else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
+                gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
+                                                   toggle_action->priv->active);
+        else if (GTK_IS_TOGGLE_BUTTON (proxy))
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
+                                              toggle_action->priv->active);
+        
+        (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+
+static void
+disconnect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+        (* GTK_ACTION_CLASS (parent_class)->disconnect_proxy) (action, proxy);
+}
+
+static void
+_update_tooltips (PolKitGnomeToggleAction *action, GParamSpec *arg1, GtkWidget *widget)
+{
+        GtkTooltips *tips;
+        GtkTooltipsData *ttd;
+        gchar *tip_str;
+
+        ttd = gtk_tooltips_data_get (widget);
+
+        if (ttd == NULL) {
+                tips = gtk_tooltips_new ();
+        } else {
+                tips = ttd->tooltips;
+        }
+
+        tip_str = NULL;
+        g_object_get (action, "tooltip", &tip_str, NULL);
+
+        /* TODO: if there is no tooltip the tip_str is NULL.
+         * Unfortunately it seems that the tooltip isn't
+         * cleared.. mmm.. gtk+ bug?
+         */
+        gtk_tooltips_set_tip (tips, widget, tip_str, tip_str);
+        g_free (tip_str);
+}
+
+static void
+_update_label (PolKitGnomeToggleAction *action, GParamSpec *arg1, GtkWidget *widget)
+{
+        char *label;
+
+        label = NULL;
+        g_object_get (action, "label", &label, NULL);
+        gtk_button_set_label (GTK_BUTTON (widget), label);
+        g_free (label);
+}
+
+static void
+_update_icon_name (PolKitGnomeToggleAction *action, GParamSpec *arg1, GtkWidget *widget)
+{
+        gtk_button_set_image (GTK_BUTTON (widget), gtk_action_create_icon (GTK_ACTION (action), GTK_ICON_SIZE_BUTTON));
+}
+
+static void 
+_button_toggled (GtkToggleButton *button, PolKitGnomeToggleAction *action)
+{
+        /* g_debug ("in _button_toggled"); */
+
+        switch (polkit_gnome_action_get_polkit_result (POLKIT_GNOME_ACTION (action))) {
+        case POLKIT_RESULT_YES:
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                /* g_debug ("blocking toggled"); */
+                g_signal_stop_emission_by_name (button, "toggled");
+                break;
+
+        default:
+        case POLKIT_RESULT_NO:
+                break;
+        }
+}
+
+/**
+ * polkit_gnome_toggle_action_create_toggle_button:
+ * @action: The #PolKitGnomeToggleAction object
+ *
+ * Create a toggle button for the given action that displays the
+ * label, tooltip and icon_name corresponding to whether the state,
+ * according to PolicyKit, is no, auth or yes.
+ * 
+ * Returns: A #GtkToggleButton instance connected to the action
+ */
+GtkWidget *
+polkit_gnome_toggle_action_create_toggle_button (PolKitGnomeToggleAction *action)
+{
+        GtkWidget *button;
+
+        button = gtk_toggle_button_new ();
+
+        gtk_action_connect_proxy (GTK_ACTION (action), button);
+
+        _update_label (action, NULL, button);
+        _update_tooltips (action, NULL, button);
+        _update_icon_name (action, NULL, button);
+
+        g_signal_connect (action, "notify::tooltip", G_CALLBACK (_update_tooltips), button);
+        g_signal_connect (action, "notify::label", G_CALLBACK (_update_label), button);
+        g_signal_connect (action, "notify::icon-name", G_CALLBACK (_update_icon_name), button);
+
+        /* hook into the ::toggled signal and block it unless
+         * PolicyKit says it's good to go. 
+         */
+        g_signal_connect (button, "toggled", G_CALLBACK (_button_toggled), action);
+
+        return button;
+}

Added: trunk/polkit-gnome/polkit-gnome-toggle-action.h
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome-toggle-action.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome-action.h : 
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#if !defined (POLKIT_GNOME_COMPILATION) && !defined(_POLKIT_GNOME_INSIDE_POLKIT_GNOME_H)
+#error "Only <polkit-gnome/polkit-gnome.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_GNOME_TOGGLE_ACTION_H__
+#define __POLKIT_GNOME_TOGGLE_ACTION_H__
+
+#include <gtk/gtk.h>
+#include <polkit/polkit.h>
+#include <polkit-gnome/polkit-gnome.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_GNOME_TYPE_TOGGLE_ACTION            (polkit_gnome_toggle_action_get_type ())
+#define POLKIT_GNOME_TOGGLE_ACTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), POLKIT_GNOME_TYPE_TOGGLE_ACTION, PolKitGnomeToggleAction))
+#define POLKIT_GNOME_TOGGLE_ACTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), POLKIT_GNOME_TYPE_TOGGLE_ACTION, PolKitGnomeToggleActionClass))
+#define POLKIT_GNOME_IS_TOGGLE_ACTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POLKIT_GNOME_TYPE_TOGGLE_ACTION))
+#define POLKIT_GNOME_IS_TOGGLE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), POLKIT_GNOME_TYPE_TOGGLE_ACTION))
+#define POLKIT_GNOME_TOGGLE_ACTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), POLKIT_GNOME_TYPE_TOGGLE_ACTION, PolKitGnomeToggleActionClass))
+
+typedef struct _PolKitGnomeToggleAction        PolKitGnomeToggleAction;
+typedef struct _PolKitGnomeToggleActionPrivate PolKitGnomeToggleActionPrivate;
+typedef struct _PolKitGnomeToggleActionClass   PolKitGnomeToggleActionClass;
+
+/**
+ * PolKitGnomeToggleAction:
+ *
+ * The PolKitGnomeToggleAction struct contains only private data members and should not be accessed directly.
+ */
+struct _PolKitGnomeToggleAction
+{
+        /*< private >*/
+        PolKitGnomeAction parent;
+        PolKitGnomeToggleActionPrivate *priv;
+};
+
+struct _PolKitGnomeToggleActionClass
+{
+        PolKitGnomeActionClass parent_class;
+
+        void (* toggled) (PolKitGnomeToggleAction *toggle_action);
+
+        /* Padding for future expansion */
+        void (*_reserved1) (void);
+        void (*_reserved2) (void);
+        void (*_reserved3) (void);
+        void (*_reserved4) (void);
+};
+
+GType                    polkit_gnome_toggle_action_get_type          (void) G_GNUC_CONST;
+PolKitGnomeToggleAction *polkit_gnome_toggle_action_new               (const gchar *name);
+PolKitGnomeToggleAction *polkit_gnome_toggle_action_new_default (const gchar  *name, 
+                                                                 PolKitAction *polkit_action, 
+                                                                 const gchar  *locked_label, 
+                                                                 const gchar  *unlocked_label);
+
+GtkWidget *polkit_gnome_toggle_action_create_toggle_button (PolKitGnomeToggleAction *action);
+
+G_END_DECLS
+
+#endif  /* __POLKIT_GNOME_TOGGLE_ACTION_H__ */

Added: trunk/polkit-gnome/polkit-gnome.h
==============================================================================
--- (empty file)
+++ trunk/polkit-gnome/polkit-gnome.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-gnome.h : PolicyKit add-on library to make it easy to use
+ * PolicyKit from GNOME and GTK+ applications.
+ *
+ * Copyright (C) 2007 David Zeuthen, <david fubar dk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ **************************************************************************/
+
+#ifndef __POLKIT_GNOME_H
+#define __POLKIT_GNOME_H
+
+#define _POLKIT_GNOME_INSIDE_POLKIT_GNOME_H 1
+#include <polkit-gnome/polkit-gnome-context.h>
+#include <polkit-gnome/polkit-gnome-action.h>
+#include <polkit-gnome/polkit-gnome-toggle-action.h>
+#include <polkit-gnome/polkit-gnome-auth.h>
+#undef _POLKIT_GNOME_INSIDE_POLKIT_GNOME_H
+
+
+#endif /* __POLKIT_GNOME_H */

Added: trunk/src/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,51 @@
+
+BUILT_SOURCES =							\
+	polkit-gnome-manager-glue.h
+
+polkit-gnome-manager-glue.h: polkit-gnome-manager.xml Makefile.am
+	dbus-binding-tool --prefix=polkit_gnome_manager --mode=glib-server --output=polkit-gnome-manager-glue.h polkit-gnome-manager.xml
+
+libexec_PROGRAMS = polkit-gnome-manager
+
+polkit_gnome_manager_SOURCES = 						\
+	polkit-gnome-manager.h		polkit-gnome-manager.c		\
+	polkit-gnome-auth-dialog.h	polkit-gnome-auth-dialog.c	\
+	main.c								\
+	$(BUILT_SOURCES)
+
+polkit_gnome_manager_CPPFLAGS = 			\
+	-I$(top_srcdir)					\
+	-DG_LOG_DOMAIN=\"PolicyKitGnome\"		\
+	-DDATADIR=\""$(pkgdatadir)"\"			\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
+	$(DISABLE_DEPRECATED)				\
+	$(AM_CPPFLAGS)
+
+polkit_gnome_manager_CFLAGS = 				\
+	$(GTK_CFLAGS)					\
+	$(SEXY_CFLAGS)					\
+	$(GNOME_VFS_CFLAGS)				\
+	$(DBUS_GLIB_CFLAGS)				\
+	$(POLKIT_DBUS_CFLAGS)				\
+	$(POLKIT_GRANT_CFLAGS)				\
+	$(WARN_CFLAGS)					\
+	$(AM_CFLAGS)
+
+polkit_gnome_manager_LDFLAGS = 				\
+	$(AM_LDFLAGS)
+
+polkit_gnome_manager_LDADD = 				\
+	$(GTK_LIBS)					\
+	$(SEXY_LIBS)					\
+	$(GNOME_VFS_LIBS)				\
+	$(DBUS_GLIB_LIBS)				\
+	$(POLKIT_DBUS_LIBS)				\
+	$(POLKIT_GRANT_LIBS)				\
+	$(INTLLIBS)
+
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = polkit-gnome-manager.xml
+
+clean-local :
+	rm -f *~

Added: trunk/src/inotify_local.h
==============================================================================
--- (empty file)
+++ trunk/src/inotify_local.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,192 @@
+/*
+ * inotify_local.h - wrapping of libc features and kernel defines
+ *
+ * Copyright (C) 2005-2006 Kay Sievers <kay.sievers at vrfy.org>
+ *
+ *	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 version 2 of the License.
+ * 
+ *	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.,
+ *	675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _INOTIFY_LOCAL_H_
+#define _INOTIFY_LOCAL_H_
+
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+
+/* needed until Inotify! syscalls reach glibc */
+#include <sys/syscall.h>
+#ifndef __NR_inotify_init
+#if defined(__i386__)
+# define __NR_inotify_init	291
+# define __NR_inotify_add_watch	292
+# define __NR_inotify_rm_watch	293
+#elif defined(__x86_64__)
+# define __NR_inotify_init	253
+# define __NR_inotify_add_watch	254
+# define __NR_inotify_rm_watch	255
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init	275
+# define __NR_inotify_add_watch	276
+# define __NR_inotify_rm_watch	277
+#elif defined (__ia64__)
+# define __NR_inotify_init	1277
+# define __NR_inotify_add_watch	1278
+# define __NR_inotify_rm_watch	1279
+#elif defined (__s390__)
+# define __NR_inotify_init	284
+# define __NR_inotify_add_watch	285
+# define __NR_inotify_rm_watch	286
+#elif defined (__mc68000__)
+# define __NR_inotify_init	284
+# define __NR_inotify_add_watch	285
+# define __NR_inotify_rm_watch	286
+#elif defined (__alpha__)
+# define __NR_inotify_init	444
+# define __NR_inotify_add_watch	445
+# define __NR_inotify_rm_watch	446
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init	151
+# define __NR_inotify_add_watch	152
+# define __NR_inotify_rm_watch	156
+#elif defined (__arm__)
+# define __NR_inotify_init	__NR_SYSCALL_BASE+316
+# define __NR_inotify_add_watch	__NR_SYSCALL_BASE+317
+# define __NR_inotify_rm_watch	__NR_SYSCALL_BASE+318
+#elif defined (__sh__)
+# define __NR_inotify_init	290
+# define __NR_inotify_add_watch	291
+# define __NR_inotify_rm_watch	292
+#elif defined (__m32r__)
+# define __NR_inotify_init      290
+# define __NR_inotify_add_watch 291
+# define __NR_inotify_rm_watch  292
+#elif defined (__hppa__)
+# define __NR_inotify_init      269
+# define __NR_inotify_add_watch 270
+# define __NR_inotify_rm_watch  271
+#elif defined (__mips__)
+# include <sgidefs.h>
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+#  define __NR_Linux             4000
+#  define __NR_inotify_init      (__NR_Linux + 284)
+#  define __NR_inotify_add_watch (__NR_Linux + 285)
+#  define __NR_inotify_rm_watch  (__NR_Linux + 286)
+# elif _MIPS_SIM == _MIPS_SIM_ABI64
+#  define __NR_Linux             5000
+#  define __NR_inotify_init      (__NR_Linux + 243)
+#  define __NR_inotify_add_watch (__NR_Linux + 244)
+#  define __NR_inotify_rm_watch  (__NR_Linux + 245)
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
+#  define __NR_Linux             6000
+#  define __NR_inotify_init      (__NR_Linux + 247)
+#  define __NR_inotify_add_watch (__NR_Linux + 248)
+#  define __NR_inotify_rm_watch  (__NR_Linux + 249)
+# endif
+#else
+# warning "inotify unsupported on this architecture!"
+#endif
+#endif /* __NR_inotify_init */
+
+/* dummy if we don't have the syscalls defined */
+#ifndef __NR_inotify_init
+static inline int inotify_init(void)
+{
+	return -1;
+}
+
+static inline int inotify_add_watch(int fd, const char *name, uint32_t mask)
+{
+	return -1;
+}
+
+static inline int inotify_rm_watch(int fd, uint32_t wd)
+{
+	return -1;
+}
+#else
+static inline int inotify_init(void)
+{
+	return syscall(__NR_inotify_init);
+}
+
+static inline int inotify_add_watch(int fd, const char *name, uint32_t mask)
+{
+	return syscall(__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int inotify_rm_watch(int fd, uint32_t wd)
+{
+	return syscall(__NR_inotify_rm_watch, fd, wd);
+}
+#endif /* __NR_inotify_init */
+
+#ifndef IN_CREATE
+#define IN_CREATE		0x00000100	/* Subfile was created */
+#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define IN_DELETE		0x00000200	/* Subfile was deleted */
+#define IN_CLOSE_WRITE		0x00000008	/* Writtable file was closed */
+#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+#endif /* IN_CREATE */
+
+struct inotify_event {
+	int      wd;
+	uint32_t mask;
+	uint32_t cookie;
+	uint32_t len;
+	char     name[];
+};
+
+/* the following are legal, implemented events that user-space can watch for */
+#define IN_ACCESS		0x00000001	/* File was accessed */
+#define IN_MODIFY		0x00000002	/* File was modified */
+#define IN_ATTRIB		0x00000004	/* Metadata changed */
+#define IN_CLOSE_WRITE		0x00000008	/* Writtable file was closed */
+#define IN_CLOSE_NOWRITE	0x00000010	/* Unwrittable file closed */
+#define IN_OPEN			0x00000020	/* File was opened */
+#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define IN_CREATE		0x00000100	/* Subfile was created */
+#define IN_DELETE		0x00000200	/* Subfile was deleted */
+#define IN_DELETE_SELF		0x00000400	/* Self was deleted */
+#define IN_MOVE_SELF		0x00000800	/* Self was moved */
+
+/* the following are legal events.  they are sent as needed to any watch */
+#define IN_UNMOUNT		0x00002000	/* Backing fs was unmounted */
+#define IN_Q_OVERFLOW		0x00004000	/* Event queued overflowed */
+#define IN_IGNORED		0x00008000	/* File was ignored */
+
+/* helper events */
+#define IN_CLOSE		(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
+#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+
+/* special flags */
+#define IN_ONLYDIR		0x01000000	/* only watch the path if it is a directory */
+#define IN_DONT_FOLLOW		0x02000000	/* don't follow a sym link */
+#define IN_MASK_ADD		0x20000000	/* add to the mask of an already existing watch */
+#define IN_ISDIR		0x40000000	/* event occurred against dir */
+#define IN_ONESHOT		0x80000000	/* only send event once */
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility.  Apps will get only the
+ * events that they originally wanted.  Be sure to add new events here!
+ */
+#define IN_ALL_EVENTS	(IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
+			 IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
+			 IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
+			 IN_MOVE_SELF)
+
+#endif /* _INOTIFY_LOCAL_H_ */

Added: trunk/src/main.c
==============================================================================
--- (empty file)
+++ trunk/src/main.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "polkit-gnome-manager.h"
+
+static DBusGProxy *
+get_bus_proxy (DBusGConnection *connection)
+{
+        DBusGProxy *bus_proxy;
+
+	bus_proxy = dbus_g_proxy_new_for_name (connection,
+                                               DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS);
+        return bus_proxy;
+}
+
+static gboolean
+acquire_name_on_proxy (DBusGProxy *bus_proxy, const char *name)
+{
+        GError     *error;
+        guint       result;
+        gboolean    res;
+        gboolean    ret;
+
+        ret = FALSE;
+
+        if (bus_proxy == NULL) {
+                goto out;
+        }
+
+        error = NULL;
+	res = dbus_g_proxy_call (bus_proxy,
+                                 "RequestName",
+                                 &error,
+                                 G_TYPE_STRING, name,
+                                 G_TYPE_UINT, 0,
+                                 G_TYPE_INVALID,
+                                 G_TYPE_UINT, &result,
+                                 G_TYPE_INVALID);
+        if (! res) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", name, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", name);
+                }
+                goto out;
+	}
+
+ 	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", name, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", name);
+                }
+                goto out;
+        }
+
+        ret = TRUE;
+
+ out:
+        return ret;
+}
+
+static DBusGConnection *
+get_session_bus (void)
+{
+        GError          *error;
+        DBusGConnection *bus;
+        DBusConnection  *connection;
+
+        error = NULL;
+        bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+        if (bus == NULL) {
+                g_warning ("Couldn't connect to session bus: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        connection = dbus_g_connection_get_connection (bus);
+ out:
+        return bus;
+}
+
+int
+main (int argc, char **argv)
+{
+        GMainLoop           *loop;
+        PolKitGnomeManager  *manager;
+        GOptionContext      *context;
+        DBusGProxy          *bus_proxy;
+        DBusGConnection     *connection;
+        int                  ret;
+        static gboolean     no_exit      = FALSE;
+        static GOptionEntry entries []   = {
+                { "no-exit", 0, 0, G_OPTION_ARG_NONE, &no_exit, N_("Don't exit after 30 seconds of inactivity"), NULL },
+                { NULL }
+        };
+
+        ret = 1;
+
+        g_type_init ();
+        gtk_init (&argc, &argv);
+
+        context = g_option_context_new (_("PolicyKit GNOME session daemon"));
+        g_option_context_add_main_entries (context, entries, NULL);
+        g_option_context_parse (context, &argc, &argv, NULL);
+        g_option_context_free (context);
+
+        connection = get_session_bus ();
+        if (connection == NULL) {
+                goto out;
+        }
+
+        bus_proxy = get_bus_proxy (connection);
+        if (bus_proxy == NULL) {
+                g_warning ("Could not construct bus_proxy object; bailing out");
+                goto out;
+        }
+
+        if (!acquire_name_on_proxy (bus_proxy, "org.gnome.PolicyKit") ) {
+                g_warning ("Could not acquire name; bailing out");
+                goto out;
+        }
+
+        if (!acquire_name_on_proxy (bus_proxy, "org.freedesktop.PolicyKit.AuthenticationAgent") ) {
+                g_warning ("Could not acquire name; bailing out");
+                goto out;
+        }
+
+        g_debug (_("Starting PolicyKit GNOME session daemon version %s"), VERSION);
+
+        manager = polkit_gnome_manager_new (no_exit);
+
+        if (manager == NULL) {
+                goto out;
+        }
+
+        loop = g_main_loop_new (NULL, FALSE);
+
+        g_main_loop_run (loop);
+
+        g_object_unref (manager);
+        g_main_loop_unref (loop);
+        ret = 0;
+
+out:
+        return ret;
+}

Added: trunk/src/polkit-gnome-auth-dialog.c
==============================================================================
--- (empty file)
+++ trunk/src/polkit-gnome-auth-dialog.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,934 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <errno.h>
+#include <libsexy/sexy.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "polkit-gnome-auth-dialog.h"
+
+struct _PolkitGnomeAuthDialogPrivate
+{
+	GtkWidget *keep_privilege_check_button;
+	GtkWidget *keep_privilege_session_only_check_button;
+	GtkWidget *message_label;
+	GtkWidget *message_label_secondary;
+	GtkWidget *user_combobox;
+	GtkWidget *app_desc_label;
+	GtkWidget *privilege_desc_label;
+	GtkWidget *privilege_vendor_label;
+	GtkWidget *prompt_label;
+        GtkWidget *password_entry;
+	GtkWidget *icon;
+	char *message;
+
+	char *vendor;
+	char *vendor_url;
+
+	gboolean can_do_always;
+	gboolean can_do_session;
+
+	GtkListStore *store;
+};
+
+G_DEFINE_TYPE (PolkitGnomeAuthDialog, polkit_gnome_auth_dialog, GTK_TYPE_DIALOG);
+
+enum {
+	USER_SELECTED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+	PROP_0,
+	PROP_PROGRAM,
+	PROP_ACTION_ID,
+	PROP_VENDOR,
+	PROP_VENDOR_URL,
+	PROP_ICON_NAME,
+	PROP_MESSAGE,
+};
+
+enum {
+	PIXBUF_COL,
+	TEXT_COL,
+	USERNAME_COL,
+	N_COL
+};
+
+static void
+user_combobox_set_sensitive (GtkCellLayout   *cell_layout,
+			     GtkCellRenderer *cell,
+			     GtkTreeModel    *tree_model,
+			     GtkTreeIter     *iter,
+			     gpointer         user_data)
+{
+	GtkTreePath *path;
+	gint *indices;
+	gboolean sensitive;
+	
+	path = gtk_tree_model_get_path (tree_model, iter);
+	indices = gtk_tree_path_get_indices (path);
+	if (indices[0] == 0)
+		sensitive = FALSE;
+	else
+		sensitive = TRUE;
+	gtk_tree_path_free (path);
+	
+	g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+
+void
+polkit_gnome_auth_dialog_select_admin_user (PolkitGnomeAuthDialog *auth_dialog, const char *admin_user)
+{
+	GtkTreeIter iter;
+	gboolean done;
+	gboolean valid;
+
+	/* make the password and "Keep.." widgets sensitive again */
+	gtk_widget_set_sensitive (auth_dialog->priv->prompt_label, TRUE);
+	gtk_widget_set_sensitive (auth_dialog->priv->password_entry, TRUE);
+	gtk_widget_set_sensitive (auth_dialog->priv->keep_privilege_check_button, TRUE);
+	gtk_widget_set_sensitive (auth_dialog->priv->keep_privilege_session_only_check_button, TRUE);
+
+	/* select appropriate item in combobox */
+	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (auth_dialog->priv->store), &iter);
+	done = FALSE;
+	while (valid && !done) {
+		char *str_data;
+		gtk_tree_model_get (GTK_TREE_MODEL (auth_dialog->priv->store), 
+				    &iter, 
+				    USERNAME_COL, &str_data,
+				    -1);
+		if (str_data != NULL && strcmp (admin_user, str_data) == 0) {
+			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (auth_dialog->priv->user_combobox),
+						       &iter);
+			done = TRUE;
+		}
+		g_free (str_data);
+      
+		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (auth_dialog->priv->store), &iter);
+	}
+}
+
+static void
+user_combobox_changed (GtkComboBox *widget,
+		       gpointer     user_data)
+{
+	char *user_name;
+	PolkitGnomeAuthDialog *auth_dialog = POLKIT_GNOME_AUTH_DIALOG (user_data);
+	GtkTreeIter iter;
+
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+		gtk_tree_model_get (GTK_TREE_MODEL (auth_dialog->priv->store), &iter, USERNAME_COL, &user_name, -1);
+		g_signal_emit (auth_dialog, signals[USER_SELECTED], 0, user_name);
+
+		polkit_gnome_auth_dialog_select_admin_user (auth_dialog, user_name);
+
+		g_free (user_name);
+	}
+}
+
+static void
+create_user_combobox (PolkitGnomeAuthDialog *auth_dialog, char **admin_users)
+{
+	int n;
+	GtkComboBox *combo;
+	GtkTreeIter iter;
+	GtkCellRenderer *renderer;
+
+	/* if we've already built the list of admin users once, then avoid
+	 * doing it again.. (this is mainly used when the user entered the
+	 * wrong password and the dialog is recycled)
+	 */
+	if (auth_dialog->priv->store != NULL)
+		return;
+
+	combo = GTK_COMBO_BOX (auth_dialog->priv->user_combobox);
+	auth_dialog->priv->store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
+
+	gtk_list_store_append (auth_dialog->priv->store, &iter);
+	gtk_list_store_set (auth_dialog->priv->store, &iter,
+			    PIXBUF_COL, NULL,
+			    TEXT_COL, _("Select user..."),
+			    USERNAME_COL, NULL,
+			    -1);
+       	
+
+	/* For each user */
+	for (n = 0; admin_users[n] != NULL; n++) {
+		char *real_name;
+		GdkPixbuf *pixbuf;
+		struct passwd *passwd;
+
+		/* we're single threaded so this is fine */
+		errno = 0;
+		passwd = getpwnam (admin_users[n]);
+		if (passwd == NULL) {
+			g_warning ("Error doing getpwnam(\"%s\"): %s", admin_users[n], strerror (errno));
+			continue;
+		}
+
+		/* Real name */
+		if (passwd->pw_gecos != NULL && strlen (passwd->pw_gecos) > 0)
+			real_name = g_strdup_printf (_("%s (%s)"), passwd->pw_gecos, admin_users[n]);
+		else
+			real_name = g_strdup (admin_users[n]);
+
+		/* Load users face */
+		pixbuf = NULL;
+		if (passwd->pw_dir != NULL) {
+			char *path;
+			path = g_strdup_printf ("%s/.face", passwd->pw_dir);
+			/* TODO: we probably shouldn't hard-code the size to 24x24*/
+			pixbuf = gdk_pixbuf_new_from_file_at_scale (path, 24, 24, TRUE, NULL);
+			g_free (path);
+		}
+
+		/* fall back to stock_person icon */
+		if (pixbuf == NULL)
+			pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+							   "stock_person", GTK_ICON_SIZE_MENU, 0, NULL);
+
+		gtk_list_store_append (auth_dialog->priv->store, &iter);
+		gtk_list_store_set (auth_dialog->priv->store, &iter,
+				    PIXBUF_COL, pixbuf,
+				    TEXT_COL, real_name,
+				    USERNAME_COL, admin_users[n],
+				    -1);
+
+		g_free (real_name);
+		g_object_unref (pixbuf);
+
+	}
+	
+	gtk_combo_box_set_model (combo, GTK_TREE_MODEL (auth_dialog->priv->store));
+
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+					"pixbuf", PIXBUF_COL,
+					NULL);
+	gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
+					    renderer,
+					    user_combobox_set_sensitive,
+					    NULL, NULL);
+	
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+					"text", TEXT_COL,
+					NULL);
+	gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
+					    renderer,
+					    user_combobox_set_sensitive,
+					    NULL, NULL);
+
+	/* Initially select the "Select user..." ... */
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+
+	/* Listen when a new user is selected */
+	g_signal_connect (GTK_WIDGET (combo), "changed",
+			  G_CALLBACK (user_combobox_changed), auth_dialog);
+
+	/* ... and make the password and "Keep.." widgets insensitive */
+	gtk_widget_set_sensitive (auth_dialog->priv->prompt_label, FALSE);
+	gtk_widget_set_sensitive (auth_dialog->priv->password_entry, FALSE);
+	gtk_widget_set_sensitive (auth_dialog->priv->keep_privilege_check_button, FALSE);
+	gtk_widget_set_sensitive (auth_dialog->priv->keep_privilege_session_only_check_button, FALSE);
+}
+
+void
+polkit_gnome_auth_dialog_set_options (PolkitGnomeAuthDialog *auth_dialog, 
+				      gboolean session, 
+				      gboolean always,
+				      gboolean requires_admin,
+				      char **admin_users)
+{
+	const char *message_markup_secondary;
+
+	auth_dialog->priv->can_do_always = always;
+	auth_dialog->priv->can_do_session = session;
+
+	if (auth_dialog->priv->can_do_session) {
+		gtk_button_set_label (GTK_BUTTON (auth_dialog->priv->keep_privilege_check_button), 
+				      _("_Remember authorization for this session"));
+
+		gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_check_button, FALSE);
+		gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_session_only_check_button, TRUE);
+	} else if (auth_dialog->priv->can_do_always) {
+		gtk_button_set_label (GTK_BUTTON (auth_dialog->priv->keep_privilege_check_button), 
+				      _("_Remember authorization"));
+
+		gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_check_button, FALSE);
+		gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_session_only_check_button, FALSE);
+
+	} else {
+		gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_check_button, TRUE);
+		gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_session_only_check_button, TRUE);
+	}
+
+	gtk_widget_set_no_show_all (auth_dialog->priv->user_combobox, TRUE);
+		
+	if (requires_admin) {
+		if (admin_users != NULL) {
+			message_markup_secondary =
+				_("An application is attempting to perform an action that requires privileges. Authentication as one of the users below is required to perform this action.");
+
+			create_user_combobox (auth_dialog, admin_users);
+			gtk_widget_set_no_show_all (auth_dialog->priv->user_combobox, FALSE);
+
+		} else {
+			message_markup_secondary =
+				_("An application is attempting to perform an action that requires privileges. Authentication as the super user is required to perform this action.");
+		}
+	} else {
+		message_markup_secondary =
+			_("An application is attempting to perform an action that requires privileges. Authentication is required to perform this action.");
+	}
+	gtk_label_set_markup (GTK_LABEL (auth_dialog->priv->message_label_secondary), message_markup_secondary);
+}
+
+static void
+polkit_gnome_auth_dialog_set_message (PolkitGnomeAuthDialog *auth_dialog, const char *markup)
+{
+	char *str;
+	str = g_strdup_printf ("<big><b>%s</b></big>", markup);
+        gtk_label_set_markup (GTK_LABEL (auth_dialog->priv->message_label), str);
+	g_free (str);
+}
+
+static void
+polkit_gnome_auth_dialog_set_action_id (PolkitGnomeAuthDialog *auth_dialog, const char *action_id)
+{
+	char *str;
+	str = g_strdup_printf ("<small><a href=\"%s\">%s</a></small>", 
+			       action_id, 
+			       action_id);
+	sexy_url_label_set_markup (SEXY_URL_LABEL (auth_dialog->priv->privilege_desc_label), str);
+	g_free (str);
+
+	str = g_strdup_printf (_("Click to edit %s"), action_id);
+	gtk_widget_set_tooltip_markup (auth_dialog->priv->privilege_desc_label, str);
+	g_free (str);
+}
+
+static void
+update_vendor (PolkitGnomeAuthDialog *auth_dialog)
+{
+	char *str;
+
+	if (auth_dialog->priv->vendor == NULL)
+		return;
+
+	if (auth_dialog->priv->vendor_url == NULL) {
+		str = g_strdup_printf ("<small>%s</small>", auth_dialog->priv->vendor);
+		gtk_widget_set_tooltip_markup (auth_dialog->priv->privilege_vendor_label, NULL);
+	} else {
+		char *s2;
+
+		str = g_strdup_printf ("<small><a href=\"%s\">%s</a></small>", 
+				       auth_dialog->priv->vendor_url, 
+				       auth_dialog->priv->vendor);
+
+		s2 = g_strdup_printf (_("Click to open %s"), auth_dialog->priv->vendor_url);
+		gtk_widget_set_tooltip_markup (auth_dialog->priv->privilege_vendor_label, s2);
+		g_free (s2);
+	}
+	sexy_url_label_set_markup (SEXY_URL_LABEL (auth_dialog->priv->privilege_vendor_label), str);
+	g_free (str);
+}
+
+static void
+polkit_gnome_auth_dialog_set_icon_name (PolkitGnomeAuthDialog *auth_dialog, const char *icon_name)
+{
+	GdkPixbuf *pixbuf;
+	GdkPixbuf *vendor_pixbuf;
+
+	pixbuf = NULL;
+	vendor_pixbuf = NULL;
+
+	vendor_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+					   icon_name,
+					   48,
+					   0,
+					   NULL);
+	if (vendor_pixbuf == NULL)
+		goto out;
+
+	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+					   GTK_STOCK_DIALOG_AUTHENTICATION,
+					   48,
+					   0,
+					   NULL);
+	if (pixbuf == NULL)
+		goto out;
+
+	/* blend the vendor icon in the bottom right quarter */
+	gdk_pixbuf_composite (vendor_pixbuf,
+			      pixbuf,
+			      24, 24, 24, 24,
+			      24, 24, 0.5, 0.5,
+			      GDK_INTERP_BILINEAR,
+			      255);
+	
+	gtk_image_set_from_pixbuf (GTK_IMAGE (auth_dialog->priv->icon),
+				   pixbuf);
+
+out:
+
+	if (pixbuf != NULL)
+		g_object_unref (pixbuf);
+	if (vendor_pixbuf != NULL)
+		g_object_unref (vendor_pixbuf);
+}
+
+static void
+polkit_gnome_auth_dialog_set_program (PolkitGnomeAuthDialog *auth_dialog, const char *program)
+{
+	char *str;
+	str = g_strdup_printf ("<small>%s</small>", program);
+	gtk_label_set_markup (GTK_LABEL (auth_dialog->priv->app_desc_label), str);
+	g_free (str);
+}
+
+
+void
+polkit_gnome_auth_dialog_set_prompt (PolkitGnomeAuthDialog *auth_dialog, 
+					const char *prompt, 
+					gboolean show_chars)
+{
+	gtk_label_set_text_with_mnemonic (GTK_LABEL (auth_dialog->priv->prompt_label), prompt);
+	gtk_entry_set_visibility (GTK_ENTRY (auth_dialog->priv->password_entry), show_chars);
+	gtk_entry_set_text (GTK_ENTRY (auth_dialog->priv->password_entry), "");
+	gtk_widget_grab_focus (auth_dialog->priv->password_entry);
+}
+
+static void
+polkit_gnome_auth_dialog_set_property (GObject *object,
+					  guint prop_id,
+					  const GValue *value,
+					  GParamSpec *pspec)
+{
+	PolkitGnomeAuthDialog *auth_dialog = POLKIT_GNOME_AUTH_DIALOG (object);
+	switch (prop_id)
+	{
+	case PROP_PROGRAM:
+		polkit_gnome_auth_dialog_set_program (auth_dialog, g_value_get_string (value));
+		break;
+
+	case PROP_ACTION_ID:
+		polkit_gnome_auth_dialog_set_action_id (auth_dialog, g_value_get_string (value));
+		break;
+
+	case PROP_VENDOR:
+		g_free (auth_dialog->priv->vendor);
+		auth_dialog->priv->vendor = g_strdup (g_value_get_string (value));
+		update_vendor (auth_dialog);
+		break;
+
+	case PROP_VENDOR_URL:
+		g_free (auth_dialog->priv->vendor_url);
+		auth_dialog->priv->vendor_url = g_strdup (g_value_get_string (value));
+		update_vendor (auth_dialog);
+		break;
+
+	case PROP_ICON_NAME:
+		polkit_gnome_auth_dialog_set_icon_name (auth_dialog, g_value_get_string (value));
+		break;
+
+	case PROP_MESSAGE:
+		if (auth_dialog->priv->message)
+			g_free (auth_dialog->priv->message);
+		auth_dialog->priv->message = g_strdup (g_value_get_string (value));
+		polkit_gnome_auth_dialog_set_message (auth_dialog, auth_dialog->priv->message);
+		break;
+
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+polkit_gnome_auth_dialog_get_property (GObject *object,
+					  guint prop_id,
+					  GValue *value,
+					  GParamSpec *pspec)
+{
+	PolkitGnomeAuthDialog *auth_dialog = POLKIT_GNOME_AUTH_DIALOG (object);
+
+	switch (prop_id)
+	{
+	case PROP_MESSAGE:
+		g_value_set_string (value, auth_dialog->priv->message);
+		break;
+		
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+
+}
+
+static GtkWidget *
+add_row (GtkWidget *table, int row, const char *label_text, GtkWidget *entry)
+{
+	GtkWidget *label;
+
+	label = gtk_label_new_with_mnemonic (label_text);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+
+	gtk_table_attach (GTK_TABLE (table), label,
+			  0, 1, row, row + 1,
+			  GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+	gtk_table_attach_defaults (GTK_TABLE (table), entry,
+				   1, 2, row, row + 1);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+
+	return label;
+}
+
+static void
+remember_check_button_toggled (GtkWidget *widget, PolkitGnomeAuthDialog *auth_dialog)
+{
+	gboolean toggled;
+
+	toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+	if (auth_dialog->priv->keep_privilege_session_only_check_button != NULL) {
+		gtk_widget_set_sensitive (auth_dialog->priv->keep_privilege_session_only_check_button, toggled);
+	}
+}
+
+static void
+vendor_url_activated (SexyUrlLabel *url_label, char *url, gpointer user_data)
+{
+        if (url != NULL) {
+                gnome_vfs_url_show (url);
+        }
+}
+
+static void
+action_id_activated (SexyUrlLabel *url_label, char *url, gpointer user_data)
+{
+        GError *error;
+        DBusGConnection *bus;
+        DBusGProxy *manager_proxy;
+
+        error = NULL;
+        bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+        if (bus == NULL) {
+                g_warning ("Couldn't connect to session bus: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+	manager_proxy = dbus_g_proxy_new_for_name (bus,
+                                               "org.gnome.PolicyKit.AuthorizationManager",
+                                               "/",
+                                               "org.gnome.PolicyKit.AuthorizationManager.SingleInstance");
+        if (manager_proxy == NULL) {
+                g_warning ("Could not construct manager_proxy object; bailing out");
+                goto out;
+        }
+
+	if (!dbus_g_proxy_call (manager_proxy,
+                                "ShowAction",
+                                &error,
+                                G_TYPE_STRING, url,
+                                G_TYPE_INVALID,
+                                G_TYPE_INVALID)) {
+                if (error != NULL) {
+                        g_warning ("Failed to call into manager: %s", error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to call into manager");
+                }
+                goto out;
+	}
+out:
+	;
+}
+
+static void
+polkit_gnome_auth_dialog_init (PolkitGnomeAuthDialog *auth_dialog)
+{
+	GtkDialog *dialog = GTK_DIALOG (auth_dialog);
+	PolkitGnomeAuthDialogPrivate *priv;
+
+	priv = auth_dialog->priv = g_new0 (PolkitGnomeAuthDialogPrivate, 1);
+
+        gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+        gtk_dialog_add_button (dialog, _("_Authenticate"), GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+
+	gtk_dialog_set_has_separator (dialog, FALSE);
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
+	gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
+	gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
+	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+	gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION);
+
+	GtkWidget *hbox, *main_vbox, *vbox;
+
+	hbox = gtk_hbox_new (FALSE, 12);
+	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+	gtk_box_pack_start (GTK_BOX (dialog->vbox), hbox, TRUE, TRUE, 0);
+
+	priv->icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
+	gtk_misc_set_alignment (GTK_MISC (priv->icon), 0.5, 0.0);
+	gtk_box_pack_start (GTK_BOX (hbox), priv->icon, FALSE, FALSE, 0);
+
+	main_vbox = gtk_vbox_new (FALSE, 10);
+	gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
+
+	/* main message */
+	priv->message_label = gtk_label_new (NULL);
+	polkit_gnome_auth_dialog_set_message (auth_dialog, "");
+	gtk_misc_set_alignment (GTK_MISC (priv->message_label), 0.0, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (priv->message_label), TRUE);
+	gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (priv->message_label),
+			    FALSE, FALSE, 0);
+
+
+	/* secondary message */
+	priv->message_label_secondary = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (priv->message_label_secondary), "");
+	gtk_misc_set_alignment (GTK_MISC (priv->message_label_secondary), 0.0, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (priv->message_label_secondary), TRUE);
+	gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (priv->message_label_secondary),
+			    FALSE, FALSE, 0);
+
+	/* user combobox */
+	priv->user_combobox = gtk_combo_box_new ();
+	gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (priv->user_combobox), FALSE, FALSE, 0);
+
+	/* password entry */
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
+
+        GtkWidget *table_alignment;
+        GtkWidget *table;
+	table_alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_box_pack_start (GTK_BOX (vbox), table_alignment, FALSE, FALSE, 0);
+	table = gtk_table_new (1, 2, FALSE);
+	gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+	gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+	gtk_container_add (GTK_CONTAINER (table_alignment), table);
+	priv->password_entry = gtk_entry_new ();
+	gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE);
+        priv->prompt_label = add_row (table, 0, _("_Password:"), priv->password_entry);
+
+	g_signal_connect_swapped (priv->password_entry, "activate",
+				  G_CALLBACK (gtk_window_activate_default),
+				  dialog);
+
+	priv->keep_privilege_check_button = gtk_check_button_new_with_mnemonic ("");
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->keep_privilege_check_button), TRUE);
+	gtk_box_pack_start (GTK_BOX (vbox), priv->keep_privilege_check_button, FALSE, FALSE, 0);
+	g_signal_connect (priv->keep_privilege_check_button, "toggled",
+			  G_CALLBACK (remember_check_button_toggled), auth_dialog);
+
+	GtkWidget *keep_alignment;
+	keep_alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (keep_alignment), 0, 0, 10, 0);
+	
+	gtk_box_pack_start (GTK_BOX (vbox), keep_alignment, FALSE, FALSE, 0);
+	GtkWidget *vbox3;
+	vbox3 = gtk_vbox_new (FALSE, 6);
+	gtk_container_add (GTK_CONTAINER (keep_alignment), vbox3);
+	
+	priv->keep_privilege_session_only_check_button = 
+		gtk_check_button_new_with_mnemonic (_("For this _session only"));
+	gtk_box_pack_start (GTK_BOX (vbox3), priv->keep_privilege_session_only_check_button, FALSE, FALSE, 0);
+
+	gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_check_button, TRUE);
+	gtk_widget_set_no_show_all (auth_dialog->priv->keep_privilege_session_only_check_button, TRUE);
+
+
+	GtkWidget *details_expander;
+	details_expander = gtk_expander_new_with_mnemonic (_("<small><b>_Details</b></small>"));
+	gtk_expander_set_use_markup (GTK_EXPANDER (details_expander), TRUE);
+	gtk_box_pack_start (GTK_BOX (dialog->vbox), details_expander, FALSE, FALSE, 0);
+	//gtk_box_pack_start (GTK_BOX (vbox), details_expander, FALSE, FALSE, 0);
+
+	GtkWidget *details_vbox;
+	details_vbox = gtk_vbox_new (FALSE, 10);
+	gtk_container_add (GTK_CONTAINER (details_expander), details_vbox);
+
+        //GtkWidget *table_alignment;
+        //GtkWidget *table;
+	table_alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_box_pack_start (GTK_BOX (details_vbox), table_alignment, FALSE, FALSE, 0);
+	table = gtk_table_new (1, 3, FALSE);
+	gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+	gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+	gtk_container_add (GTK_CONTAINER (table_alignment), table);
+
+
+	priv->app_desc_label = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (priv->app_desc_label), 0, 1.0);
+        add_row (table, 0, _("<small><b>Application:</b></small>"), priv->app_desc_label);
+
+	priv->privilege_desc_label = sexy_url_label_new ();
+	gtk_misc_set_alignment (GTK_MISC (priv->privilege_desc_label), 0, 1.0);
+        add_row (table, 1, _("<small><b>Action:</b></small>"), priv->privilege_desc_label);
+        g_signal_connect (priv->privilege_desc_label, "url-activated", (GCallback) action_id_activated, NULL);
+
+	priv->privilege_vendor_label = sexy_url_label_new ();
+	gtk_misc_set_alignment (GTK_MISC (priv->privilege_vendor_label), 0, 1.0);
+        add_row (table, 2, _("<small><b>Vendor:</b></small>"), priv->privilege_vendor_label);
+        g_signal_connect (priv->privilege_vendor_label, "url-activated", (GCallback) vendor_url_activated, NULL);
+}
+
+static void
+polkit_gnome_auth_dialog_finalize (GObject *object)
+{
+	PolkitGnomeAuthDialog *auth_dialog = POLKIT_GNOME_AUTH_DIALOG (object);
+
+	g_free (auth_dialog->priv);
+
+	G_OBJECT_CLASS (polkit_gnome_auth_dialog_parent_class)->finalize (object);
+}
+
+#define PARAM_STATIC G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
+
+static void
+polkit_gnome_auth_dialog_class_init (PolkitGnomeAuthDialogClass * klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	polkit_gnome_auth_dialog_parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+	gobject_class->finalize = polkit_gnome_auth_dialog_finalize;
+	gobject_class->get_property = polkit_gnome_auth_dialog_get_property;
+	gobject_class->set_property = polkit_gnome_auth_dialog_set_property;
+
+	g_object_class_install_property
+		(gobject_class,
+		 PROP_PROGRAM,
+		 g_param_spec_string ("program",
+				      "program",
+				      "program",
+				      NULL,
+				      G_PARAM_READWRITE | PARAM_STATIC));
+
+	g_object_class_install_property
+		(gobject_class,
+		 PROP_ACTION_ID,
+		 g_param_spec_string ("action-id",
+				      "action-id",
+				      "action-id",
+				      NULL,
+				      G_PARAM_READWRITE | PARAM_STATIC));
+
+	g_object_class_install_property
+		(gobject_class,
+		 PROP_VENDOR,
+		 g_param_spec_string ("vendor",
+				      "vendor",
+				      "vendor",
+				      NULL,
+				      G_PARAM_READWRITE | PARAM_STATIC));
+
+	g_object_class_install_property
+		(gobject_class,
+		 PROP_VENDOR_URL,
+		 g_param_spec_string ("vendor-url",
+				      "vendor-url",
+				      "vendor-url",
+				      NULL,
+				      G_PARAM_READWRITE | PARAM_STATIC));
+
+	g_object_class_install_property
+		(gobject_class,
+		 PROP_ICON_NAME,
+		 g_param_spec_string ("icon-name",
+				      "icon-name",
+				      "icon-name",
+				      NULL,
+				      G_PARAM_READWRITE | PARAM_STATIC));
+
+
+	g_object_class_install_property
+		(gobject_class,
+		 PROP_MESSAGE,
+		 g_param_spec_string ("message",
+				      "message",
+				      "message",
+				      NULL,
+				      G_PARAM_READWRITE | PARAM_STATIC));
+
+
+	signals[USER_SELECTED] =
+		g_signal_new ("user-selected",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (PolkitGnomeAuthDialogClass,
+					       user_selected),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1,
+			      G_TYPE_STRING);
+
+}
+
+/**
+ * polkit_gnome_auth_dialog_new:
+ * 
+ * Yada yada yada...
+ * 
+ * Returns: A new password dialog.
+ **/
+GtkWidget *
+polkit_gnome_auth_dialog_new (const char *path_to_program,
+			      const char *action_id,
+			      const char *vendor,
+			      const char *vendor_url,
+			      const char *icon_name,
+			      const char *message_markup)
+{
+	PolkitGnomeAuthDialog *auth_dialog;
+	GtkWindow *window;
+
+	auth_dialog = g_object_new (POLKIT_GNOME_TYPE_AUTH_DIALOG, 
+				    "program", path_to_program,
+				    "action-id", action_id,
+				    "vendor", vendor,
+				    "vendor-url", vendor_url,
+				    "icon-name", icon_name,
+				    "message", message_markup,
+				    NULL);
+
+	window = GTK_WINDOW (auth_dialog);
+
+ 	gtk_window_set_position (window, GTK_WIN_POS_CENTER);
+	gtk_window_set_modal (window, TRUE);
+	gtk_window_set_resizable (window, FALSE);
+	gtk_window_set_keep_above (window, TRUE);
+	gtk_window_set_title (window, _("Authenticate"));
+	g_signal_connect (auth_dialog, "close",
+			  G_CALLBACK (gtk_widget_hide), NULL);
+	
+	return GTK_WIDGET (auth_dialog);
+}
+
+const char *
+polkit_gnome_auth_dialog_get_password (PolkitGnomeAuthDialog *auth_dialog)
+{
+	return gtk_entry_get_text (GTK_ENTRY (auth_dialog->priv->password_entry));
+}
+
+gboolean
+polkit_gnome_auth_dialog_get_remember_session (PolkitGnomeAuthDialog *auth_dialog)
+{
+	gboolean ret;
+	gboolean remember;
+
+	remember = gtk_toggle_button_get_active (
+		GTK_TOGGLE_BUTTON (auth_dialog->priv->keep_privilege_check_button));
+
+	if (auth_dialog->priv->can_do_always) {
+		gboolean session_only;
+		session_only = gtk_toggle_button_get_active (
+			GTK_TOGGLE_BUTTON (auth_dialog->priv->keep_privilege_session_only_check_button));
+
+		ret = remember && session_only;
+	} else {
+		ret = remember;
+	}
+	return ret;
+}
+
+gboolean
+polkit_gnome_auth_dialog_get_remember_always (PolkitGnomeAuthDialog *auth_dialog)
+{
+	gboolean ret;
+	gboolean remember;
+
+	remember = gtk_toggle_button_get_active (
+		GTK_TOGGLE_BUTTON (auth_dialog->priv->keep_privilege_check_button));
+
+	if (auth_dialog->priv->can_do_always) {
+		gboolean session_only;
+		session_only = gtk_toggle_button_get_active (
+			GTK_TOGGLE_BUTTON (auth_dialog->priv->keep_privilege_session_only_check_button));
+
+		ret = remember && (!session_only);
+	} else {
+		ret = FALSE;
+	}
+	return ret;
+}
+
+/**
+ * polkit_gnome_auth_dialog_indicate_auth_error:
+ * @auth_dialog: the auth dialog
+ * 
+ * Call this function to indicate an authentication error; typically shakes the window
+ **/
+void
+polkit_gnome_auth_dialog_indicate_auth_error (PolkitGnomeAuthDialog *auth_dialog)
+{
+	int x, y;
+	int n;
+	int diff;
+
+	/* TODO: detect compositing manager and do fancy stuff here */
+
+	gtk_window_get_position (GTK_WINDOW (auth_dialog), &x, &y);
+	for (n = 0; n < 10; n++) {
+		if (n % 2 == 0)
+			diff = -15;
+		else
+			diff = 15;
+
+		gtk_window_move (GTK_WINDOW (auth_dialog), x + diff, y);
+
+                while (gtk_events_pending ()) {
+                        gtk_main_iteration ();
+                }
+
+                g_usleep (10000);
+	}
+	gtk_window_move (GTK_WINDOW (auth_dialog), x, y);
+}

Added: trunk/src/polkit-gnome-auth-dialog.h
==============================================================================
--- (empty file)
+++ trunk/src/polkit-gnome-auth-dialog.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,83 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifndef POLKIT_GNOME_AUTH_DIALOG_H
+#define POLKIT_GNOME_AUTH_DIALOG_H
+
+#include <gtk/gtkdialog.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_GNOME_TYPE_AUTH_DIALOG            (polkit_gnome_auth_dialog_get_type ())
+#define POLKIT_GNOME_AUTH_DIALOG(obj)            (GTK_CHECK_CAST ((obj), POLKIT_GNOME_TYPE_AUTH_DIALOG, PolkitGnomeAuthDialog))
+#define POLKIT_GNOME_AUTH_DIALOG_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), POLKIT_GNOME_TYPE_AUTH_DIALOG, PolkitGnomeAuthDialogClass))
+#define POLKIT_GNOME_IS_AUTH_DIALOG(obj)         (GTK_CHECK_TYPE ((obj), POLKIT_GNOME_TYPE_AUTH_DIALOG))
+#define POLKIT_GNOME_IS_AUTH_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), POLKIT_GNOME_TYPE_AUTH_DIALOG))
+
+typedef struct _PolkitGnomeAuthDialog        PolkitGnomeAuthDialog;
+typedef struct _PolkitGnomeAuthDialogClass   PolkitGnomeAuthDialogClass;
+typedef struct _PolkitGnomeAuthDialogPrivate PolkitGnomeAuthDialogPrivate;
+
+struct _PolkitGnomeAuthDialog
+{
+	GtkDialog gtk_dialog;
+	PolkitGnomeAuthDialogPrivate *priv;
+};
+
+struct _PolkitGnomeAuthDialogClass
+{
+	GtkDialogClass parent_class;
+
+	/* Signals: */
+
+	void (*user_selected) (PolkitGnomeAuthDialog *auth_dialog, const char *user_name);
+};
+
+GtkType    polkit_gnome_auth_dialog_get_type      (void);
+GtkWidget *polkit_gnome_auth_dialog_new (const char *path_to_program,
+					 const char *action_id,
+					 const char *vendor,
+					 const char *vendor_url,
+					 const char *icon_name,
+					 const char *message_markup);
+
+void        polkit_gnome_auth_dialog_set_prompt (PolkitGnomeAuthDialog *auth_dialog,
+						 const char *prompt,
+						 gboolean show_chars);
+
+const char *polkit_gnome_auth_dialog_get_password (PolkitGnomeAuthDialog *auth_dialog);
+
+void        polkit_gnome_auth_dialog_set_options (PolkitGnomeAuthDialog *auth_dialog, 
+						  gboolean session, 
+						  gboolean always,
+						  gboolean requires_admin,
+						  char **admin_users);
+
+gboolean    polkit_gnome_auth_dialog_get_remember_session (PolkitGnomeAuthDialog *auth_dialog);
+gboolean    polkit_gnome_auth_dialog_get_remember_always  (PolkitGnomeAuthDialog *auth_dialog);
+gboolean    polkit_gnome_auth_dialog_get_apply_all        (PolkitGnomeAuthDialog *auth_dialog);
+
+void        polkit_gnome_auth_dialog_select_admin_user (PolkitGnomeAuthDialog *auth_dialog, const char *admin_user);
+
+void        polkit_gnome_auth_dialog_indicate_auth_error (PolkitGnomeAuthDialog *auth_dialog);
+
+G_END_DECLS
+
+#endif /* POLKIT_GNOME_AUTH_DIALOG_H */

Added: trunk/src/polkit-gnome-manager.c
==============================================================================
--- (empty file)
+++ trunk/src/polkit-gnome-manager.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,1119 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+#include <polkit-dbus/polkit-dbus.h>
+#include <polkit-grant/polkit-grant.h>
+
+#include "polkit-gnome-manager.h"
+#include "polkit-gnome-manager-glue.h"
+
+#include "polkit-gnome-auth-dialog.h"
+
+static void do_cancel_auth (void);
+
+
+static guint kill_timer_id = 0;
+
+static gboolean kill_timer_no_exit = FALSE;
+
+static gboolean
+kill_timer_exit (gpointer user_data)
+{
+        g_debug ("Exiting because of kill timer.");
+        exit (0);
+        return FALSE;
+}
+
+static void
+kill_timer_stop (void)
+{
+
+        if (kill_timer_id > 0) {
+                g_debug ("Removing kill timer.");
+                g_source_remove (kill_timer_id);
+                kill_timer_id = 0;
+        }
+}
+
+static void
+kill_timer_start (void)
+{
+        if (kill_timer_no_exit)
+                return;
+
+        kill_timer_stop ();
+        g_debug ("Setting kill timer to 30 seconds.");
+        kill_timer_id = g_timeout_add (30 * 1000, kill_timer_exit, NULL);
+}
+
+static gboolean
+do_polkit_auth (PolKitContext *pk_context,
+                DBusConnection *system_bus_connection,
+                const char *caller_exe_name,
+                const char *action_id, 
+                guint32     xid,
+                pid_t       caller_pid);
+
+struct PolKitGnomeManagerPrivate
+{
+        DBusGConnection *session_bus_connection;
+        DBusGProxy      *session_bus_proxy;
+
+        DBusGConnection *system_bus_connection;
+
+        PolKitContext   *pk_context;
+
+        gboolean         auth_in_progress;
+        char            *session_bus_unique_name_of_client;
+};
+
+static void     polkit_gnome_manager_class_init  (PolKitGnomeManagerClass *klass);
+static void     polkit_gnome_manager_init        (PolKitGnomeManager      *seat);
+static void     polkit_gnome_manager_finalize    (GObject     *object);
+
+G_DEFINE_TYPE (PolKitGnomeManager, polkit_gnome_manager, G_TYPE_OBJECT)
+
+#define POLKIT_GNOME_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_GNOME_TYPE_MANAGER, PolKitGnomeManagerPrivate))
+
+GQuark
+polkit_gnome_manager_error_quark (void)
+{
+        static GQuark ret = 0;
+
+#if 0
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			ENUM_ENTRY (POLKIT_MANAGER_ERROR_NO_SUCH_USER, "NoSuchUser"),
+			ENUM_ENTRY (POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE, "NoSuchPrivilege"),
+			ENUM_ENTRY (POLKIT_MANAGER_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+			ENUM_ENTRY (POLKIT_MANAGER_ERROR_CANNOT_OBTAIN_PRIVILEGE, "CannotObtainPrivilege"),
+			ENUM_ENTRY (POLKIT_MANAGER_ERROR_ERROR, "Error"),
+			{ 0, 0, 0 }
+		};
+		
+		g_assert (POLKIT_MANAGER_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+		
+		etype = g_enum_register_static ("PolkitManagerError", values);
+	}
+#endif
+
+        if (ret == 0) {
+                ret = g_quark_from_static_string ("polkit_gnome_manager_error");
+        }
+
+        return ret;
+}
+
+static GObject *
+polkit_gnome_manager_constructor (GType                  type,
+                                  guint                  n_construct_properties,
+                                  GObjectConstructParam *construct_properties)
+{
+        PolKitGnomeManager      *manager;
+        PolKitGnomeManagerClass *klass;
+
+        klass = POLKIT_GNOME_MANAGER_CLASS (g_type_class_peek (POLKIT_GNOME_TYPE_MANAGER));
+
+        manager = POLKIT_GNOME_MANAGER (G_OBJECT_CLASS (polkit_gnome_manager_parent_class)->constructor (
+                                                type,
+                                                n_construct_properties,
+                                                construct_properties));
+
+        return G_OBJECT (manager);
+}
+
+static void
+polkit_gnome_manager_class_init (PolKitGnomeManagerClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructor = polkit_gnome_manager_constructor;
+        object_class->finalize = polkit_gnome_manager_finalize;
+
+        g_type_class_add_private (klass, sizeof (PolKitGnomeManagerPrivate));
+
+        dbus_g_object_type_install_info (POLKIT_GNOME_TYPE_MANAGER, &dbus_glib_polkit_gnome_manager_object_info);
+}
+
+static void
+polkit_gnome_manager_init (PolKitGnomeManager *manager)
+{
+        manager->priv = POLKIT_GNOME_MANAGER_GET_PRIVATE (manager);
+
+}
+
+static void
+polkit_gnome_manager_finalize (GObject *object)
+{
+        PolKitGnomeManager *manager;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (POLKIT_GNOME_IS_MANAGER (object));
+
+        manager = POLKIT_GNOME_MANAGER (object);
+
+        g_return_if_fail (manager->priv != NULL);
+
+        g_object_unref (manager->priv->session_bus_proxy);
+
+        G_OBJECT_CLASS (polkit_gnome_manager_parent_class)->finalize (object);
+}
+
+
+static void
+_polkit_config_changed_cb (PolKitContext *pk_context, gpointer user_data)
+{
+        g_debug ("PolicyKit reports that the config have changed");
+}
+
+
+static void
+session_bus_name_owner_changed (DBusGProxy  *bus_proxy,
+                                const char  *service_name,
+                                const char  *old_service_name,
+                                const char  *new_service_name,
+                                gpointer     user_data)
+{
+        PolKitGnomeManager *manager = user_data;
+
+        if (strlen (new_service_name) == 0 &&
+            manager->priv->auth_in_progress &&
+            manager->priv->session_bus_unique_name_of_client != NULL &&
+            strcmp (manager->priv->session_bus_unique_name_of_client, old_service_name) == 0) {
+                do_cancel_auth ();
+        }
+
+}
+
+
+static gboolean
+pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+        int fd;
+        PolKitContext *pk_context = user_data;
+        fd = g_io_channel_unix_get_fd (channel);
+        polkit_context_io_func (pk_context, fd);
+        return TRUE;
+}
+
+static int 
+pk_io_add_watch (PolKitContext *pk_context, int fd)
+{
+        guint id = 0;
+        GIOChannel *channel;
+        channel = g_io_channel_unix_new (fd);
+        if (channel == NULL)
+                goto out;
+        id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
+        if (id == 0) {
+                g_io_channel_unref (channel);
+                goto out;
+        }
+        g_io_channel_unref (channel);
+out:
+        return id;
+}
+
+static void 
+pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+        g_source_remove (watch_id);
+}
+
+static gboolean
+register_manager (PolKitGnomeManager *manager)
+{
+        GError *error = NULL;
+        PolKitError *pk_error;
+
+        error = NULL;
+        manager->priv->session_bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+        if (manager->priv->session_bus_connection == NULL) {
+                if (error != NULL) {
+                        g_critical ("error getting session bus: %s", error->message);
+                        g_error_free (error);
+                }
+                goto error;
+        }
+
+        manager->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (manager->priv->system_bus_connection == NULL) {
+                if (error != NULL) {
+                        g_critical ("error getting system bus: %s", error->message);
+                        g_error_free (error);
+                }
+                goto error;
+        }
+
+        dbus_g_connection_register_g_object (manager->priv->session_bus_connection, 
+                                             "/org/gnome/PolicyKit/Manager", 
+                                             G_OBJECT (manager));
+
+        dbus_g_connection_register_g_object (manager->priv->session_bus_connection, 
+                                             "/", 
+                                             G_OBJECT (manager));
+
+        manager->priv->session_bus_proxy = dbus_g_proxy_new_for_name (manager->priv->session_bus_connection,
+                                                                      DBUS_SERVICE_DBUS,
+                                                                      DBUS_PATH_DBUS,
+                                                                      DBUS_INTERFACE_DBUS);
+
+        dbus_g_proxy_add_signal (manager->priv->session_bus_proxy,
+                                 "NameOwnerChanged",
+                                 G_TYPE_STRING,
+                                 G_TYPE_STRING,
+                                 G_TYPE_STRING,
+                                 G_TYPE_INVALID);
+        dbus_g_proxy_connect_signal (manager->priv->session_bus_proxy,
+                                     "NameOwnerChanged",
+                                     G_CALLBACK (session_bus_name_owner_changed),
+                                     manager,
+                                     NULL);
+
+        manager->priv->pk_context = polkit_context_new ();
+        if (manager->priv->pk_context == NULL) {
+                g_critical ("error creating PK context");
+                goto error;
+        }
+        polkit_context_set_load_descriptions (manager->priv->pk_context);
+        polkit_context_set_config_changed (manager->priv->pk_context,
+                                           _polkit_config_changed_cb,
+                                           NULL);
+        polkit_context_set_io_watch_functions (manager->priv->pk_context, pk_io_add_watch, pk_io_remove_watch);
+        pk_error = NULL;
+        if (!polkit_context_init (manager->priv->pk_context, &pk_error)) {
+                g_critical ("error creating PK context: %s", polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+                goto error;
+        }
+
+        return TRUE;
+
+error:
+        return FALSE;
+}
+
+
+PolKitGnomeManager *
+polkit_gnome_manager_new (gboolean no_exit)
+{
+        GObject *object;
+        gboolean res;
+
+        object = g_object_new (POLKIT_GNOME_TYPE_MANAGER, NULL);
+
+        res = register_manager (POLKIT_GNOME_MANAGER (object));
+        if (! res) {
+                g_object_unref (object);
+                return NULL;
+        }
+
+        kill_timer_no_exit = no_exit;
+        kill_timer_start ();
+
+        return POLKIT_GNOME_MANAGER (object);
+}
+
+/* TODO: this is right now Linux specific */
+
+static char *
+get_exe_for_pid (pid_t pid)
+{
+        char *result;
+        char buf[PATH_MAX];
+        ssize_t len;
+        char proc_name[32];
+
+        result = NULL;
+
+        snprintf (proc_name, sizeof (proc_name), "/proc/%d/exe", pid);
+        len = readlink (proc_name, buf, sizeof (buf) - 1);
+        if (len == -1) {
+                goto out;
+        }
+        g_assert (len >= 0 && len < PATH_MAX - 1);
+
+        buf[len] = '\0';
+        result = g_strdup (buf);
+
+out:
+        return result;
+}
+
+typedef struct
+{
+        PolKitGnomeManager    *manager;
+        char                  *action_id;
+        guint32                xid;
+        pid_t                  pid;
+        DBusGMethodInvocation *context;
+} WorkClosure;
+
+static gboolean
+do_auth (gpointer user_data)
+{
+        WorkClosure *wc = user_data;
+        const char *sender;
+        pid_t caller_pid;
+        char *caller_exe;
+        gboolean gained_privilege;
+        GError *error;
+
+        kill_timer_stop ();
+
+        if (wc->manager->priv->auth_in_progress) {
+                error = g_error_new (POLKIT_GNOME_MANAGER_ERROR,
+                                     POLKIT_GNOME_MANAGER_ERROR_AUTH_IN_PROGRESS,
+                                     "Another client is already authenticating. Please try again later.");
+                dbus_g_method_return_error (wc->context, error);
+                g_error_free (error);
+                goto out;
+        }
+
+        g_debug ("in show_dialog action_id='%s'", wc->action_id);
+
+        sender = dbus_g_method_get_sender (wc->context);
+
+        if (wc->pid == -1) {
+                error = NULL;
+                if (! dbus_g_proxy_call (wc->manager->priv->session_bus_proxy, "GetConnectionUnixProcessID", &error,
+                                         G_TYPE_STRING, sender,
+                                         G_TYPE_INVALID,
+                                         G_TYPE_UINT, &caller_pid,
+                                         G_TYPE_INVALID)) {
+                        g_debug ("GetConnectionUnixProcessID() failed: %s", error->message);
+                        g_error_free (error);
+                        
+                        error = g_error_new (POLKIT_GNOME_MANAGER_ERROR,
+                                             POLKIT_GNOME_MANAGER_ERROR_GENERAL,
+                                             "Unable to lookup process ID for caller");
+                        dbus_g_method_return_error (wc->context, error);
+                        g_error_free (error);
+                        goto out;
+                }
+        } else {
+                caller_pid = wc->pid;
+        }
+
+        g_debug ("process id = %d", caller_pid);
+
+        caller_exe = get_exe_for_pid (caller_pid);
+        if (caller_exe == NULL) {
+                caller_exe = g_strdup ("(unknown)");
+#if 0
+                error = g_error_new (POLKIT_GNOME_MANAGER_ERROR,
+                                     POLKIT_GNOME_MANAGER_ERROR_GENERAL,
+                                     "Unable to lookup exe for caller");
+                dbus_g_method_return_error (wc->context, error);
+                g_error_free (error);
+                goto out;
+#endif
+        }
+
+        g_debug ("exe = '%s'", caller_exe);
+
+        wc->manager->priv->auth_in_progress = TRUE;
+        wc->manager->priv->session_bus_unique_name_of_client = g_strdup (sender);
+
+        gained_privilege = do_polkit_auth (wc->manager->priv->pk_context,
+                                           dbus_g_connection_get_connection (wc->manager->priv->system_bus_connection),
+                                           caller_exe,
+                                           wc->action_id,
+                                           wc->xid,
+                                           caller_pid);
+
+        g_free (caller_exe);
+
+        dbus_g_method_return (wc->context, gained_privilege);
+
+        wc->manager->priv->auth_in_progress = FALSE;
+        g_free (wc->manager->priv->session_bus_unique_name_of_client);
+        wc->manager->priv->session_bus_unique_name_of_client = NULL;
+out:
+        kill_timer_start ();
+        g_free (wc->action_id);
+        g_free (wc);
+        return FALSE;
+}
+
+/* exported methods */
+
+
+gboolean
+polkit_gnome_manager_obtain_authorization (PolKitGnomeManager    *manager,
+                                           const char            *action_id,
+                                           guint32                xid,
+                                           guint32                pid,
+                                           DBusGMethodInvocation *context)
+{
+        WorkClosure *wc;
+
+        wc = g_new0 (WorkClosure, 1);
+        wc->manager = manager;
+        wc->action_id = g_strdup (action_id);
+        wc->xid = xid;
+        wc->context = context;
+        wc->pid = pid;
+
+        g_idle_add (do_auth, wc);
+        return TRUE;
+}
+
+gboolean
+polkit_gnome_manager_show_dialog (PolKitGnomeManager    *manager,
+                                  const char            *action_id,
+                                  guint32                xid,
+                                  DBusGMethodInvocation *context)
+{
+        return polkit_gnome_manager_obtain_authorization (manager, action_id, xid, -1, context);
+}
+
+
+/*----------------------------------------------------------------------------------------------------*/
+
+typedef struct {
+        GMainLoop *loop;
+        GtkWidget *dialog;
+        PolKitGrant *polkit_grant;
+
+        gboolean gained_privilege;
+        gboolean was_cancelled;
+        gboolean was_bogus;
+        gboolean new_user_selected;
+
+        gboolean remember_session;
+        gboolean remember_always;
+        gboolean requires_admin;
+        char **admin_users;
+
+        char *admin_user_selected;
+} UserData;
+
+static void
+conversation_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
+{
+        UserData *ud = user_data;
+
+        ud->remember_session = FALSE;
+        ud->remember_always = FALSE;
+        ud->requires_admin = FALSE;
+
+        switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+                ud->requires_admin = TRUE;
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+                ud->requires_admin = TRUE;
+                ud->remember_session = TRUE;
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+                ud->requires_admin = TRUE;
+                ud->remember_always = TRUE;
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+                ud->remember_session = TRUE;
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                ud->remember_always = TRUE;
+                break;
+        default:
+                g_assert_not_reached ();
+                break;
+        }
+
+        polkit_gnome_auth_dialog_set_options (POLKIT_GNOME_AUTH_DIALOG (ud->dialog), 
+                                              ud->remember_session,
+                                              ud->remember_always,
+                                              ud->requires_admin,
+                                              ud->admin_users);
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static void
+_do_grab (GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+        GdkGrabStatus ret;
+
+        ret = gdk_pointer_grab (widget->window, 
+                                TRUE,
+                                GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK,
+                                NULL,
+                                NULL,
+                                GDK_CURRENT_TIME);
+        if (ret != GDK_GRAB_SUCCESS) {
+                g_warning ("Couldn't grab the pointer; ret = %d", ret);
+        }
+
+        ret = gdk_keyboard_grab (widget->window, 
+                                FALSE,
+                                GDK_CURRENT_TIME);
+        if (ret != GDK_GRAB_SUCCESS) {
+                g_warning ("Couldn't grab the pointer; ret = %d", ret);
+        }
+
+        g_debug ("Grabbed pointer and keyboard");
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static void 
+dialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
+{
+        UserData *ud = user_data;
+
+        g_debug ("dialog response %d", response_id);
+        if (ud->admin_user_selected == NULL)
+                ud->admin_user_selected = g_strdup ("");
+}
+
+static void
+user_selected (PolkitGnomeAuthDialog *auth_dialog, const char *user_name, gpointer user_data)
+{
+        UserData *ud = user_data;
+
+        g_debug ("In user_selected, user_name=%s", user_name);
+
+        if (ud->admin_user_selected == NULL) {
+                /* happens when we're invoked from conversation_select_admin_user() */
+                ud->admin_user_selected = g_strdup (user_name);
+        } else {
+                g_debug ("Restart auth as new user...");
+                g_free (ud->admin_user_selected);
+                ud->admin_user_selected = g_strdup (user_name);
+                ud->new_user_selected = TRUE;
+                polkit_grant_cancel_auth (ud->polkit_grant);
+                /* break out of gtk_dialog_run() ... */
+                gtk_dialog_response (GTK_DIALOG (ud->dialog), GTK_RESPONSE_OK);
+        }
+}
+
+static char *
+conversation_select_admin_user (PolKitGrant *polkit_grant, char **admin_users, void *user_data)
+{
+        UserData *ud = user_data;
+        gulong response_id;
+        char *result;
+        int n;
+        const char *user_name;
+
+        /* if we've already selected the admin user.. then reuse the same one (this
+         * is mainly when the user entered the wrong password)
+         */
+        if (ud->admin_user_selected != NULL) {
+                result = strdup (ud->admin_user_selected);
+                goto out;
+        }
+
+        ud->admin_users = g_strdupv (admin_users);
+
+        /* show the auth dialog with the given admin users */
+        polkit_gnome_auth_dialog_set_options (POLKIT_GNOME_AUTH_DIALOG (ud->dialog), 
+                                              ud->remember_session,
+                                              ud->remember_always,
+                                              ud->requires_admin,
+                                              ud->admin_users);
+
+        /* if we are running as one of the users in admin_users then preselect that user... */
+        user_name = g_get_user_name ();
+        if (user_name != NULL) {
+                for (n = 0; admin_users[n] != NULL; n++) {
+                        if (strcmp (user_name, admin_users[n]) == 0) {
+                                ud->admin_user_selected = g_strdup (user_name);
+                                result = strdup (ud->admin_user_selected);
+
+                                polkit_gnome_auth_dialog_select_admin_user (POLKIT_GNOME_AUTH_DIALOG (ud->dialog), 
+                                                                            ud->admin_user_selected);
+
+                                g_debug ("Preselecting ourselves as admin_user");
+                                goto out;
+                        }
+                }
+        }
+
+        polkit_gnome_auth_dialog_set_prompt (POLKIT_GNOME_AUTH_DIALOG (ud->dialog), _("_Password:"), FALSE);
+	response_id = g_signal_connect (GTK_WIDGET (ud->dialog), "response", G_CALLBACK (dialog_response), ud);
+        gtk_window_present (GTK_WINDOW (ud->dialog));
+        gtk_widget_show_all (ud->dialog);
+
+        /* run the mainloop waiting for the user to be selected */
+        while (ud->admin_user_selected == NULL)
+                g_main_context_iteration (g_main_loop_get_context (ud->loop), TRUE);
+
+        g_signal_handler_disconnect (GTK_WIDGET (ud->dialog), response_id);
+
+        /* if admin_user_selected is the empty string.. it means the dialog was
+         * cancelled (see dialog_response() above) 
+         */
+        if (strcmp (ud->admin_user_selected, "") == 0) {
+                ud->was_cancelled = TRUE;
+                polkit_grant_cancel_auth (polkit_grant);
+                result = NULL;
+        } else {
+                result = strdup (ud->admin_user_selected);
+        }
+out:
+        return result;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static char *
+conversation_pam_prompt (PolKitGrant *polkit_grant, const char *request, void *user_data, gboolean echo_on)
+{
+        UserData *ud = user_data;
+        char *password;
+        char *request2;
+        int response;
+
+        password = NULL;
+
+        g_debug ("in conversation_pam_prompt, request='%s', echo_on=%d", request, echo_on);
+
+        /* Fix up, and localize, password prompt if it's password auth */
+        printf ("request: '%s'\n", request);
+        if (g_ascii_strncasecmp (request, "password:", 9) == 0) {
+                if (ud->requires_admin) {
+                        if (ud->admin_user_selected != NULL) {
+                                request2 = g_strdup_printf (_("_Password for %s:"), ud->admin_user_selected);
+                        } else {
+                                request2 = g_strdup (_("_Password for root:"));
+                        }
+                } else {
+                        request2 = g_strdup (_("_Password:"));
+                }
+        } else if (g_ascii_strncasecmp (request, "password or swipe finger:", 25) == 0) {
+                if (ud->requires_admin) {
+                        if (ud->admin_user_selected != NULL) {
+                                request2 = g_strdup_printf (_("_Password or swipe finger for %s:"), 
+                                                            ud->admin_user_selected);
+                        } else {
+                                request2 = g_strdup (_("_Password or swipe finger for root:"));
+                        }
+                } else {
+                        request2 = g_strdup (_("_Password or swipe finger:"));
+                }
+        } else {
+                request2 = g_strdup (request);
+        }
+
+        polkit_gnome_auth_dialog_set_prompt (POLKIT_GNOME_AUTH_DIALOG (ud->dialog), request2, echo_on);
+        g_free (request2);
+
+        gtk_widget_show_all (ud->dialog);
+
+        response = gtk_dialog_run (GTK_DIALOG (ud->dialog));
+
+        /* cancel auth unless user clicked "Authenticate" */
+        if (response != GTK_RESPONSE_OK) {
+                ud->was_cancelled = TRUE;
+                polkit_grant_cancel_auth (polkit_grant);
+                goto out;
+        }
+
+        password = strdup (polkit_gnome_auth_dialog_get_password (POLKIT_GNOME_AUTH_DIALOG (ud->dialog)));
+out:
+        return password;
+}
+
+static char *
+conversation_pam_prompt_echo_off (PolKitGrant *polkit_grant, const char *request, void *user_data)
+{
+        return conversation_pam_prompt (polkit_grant, request, user_data, FALSE);
+}
+
+static char *
+conversation_pam_prompt_echo_on (PolKitGrant *polkit_grant, const char *request, void *user_data)
+{
+        return conversation_pam_prompt (polkit_grant, request, user_data, TRUE);
+}
+
+static void
+conversation_pam_error_msg (PolKitGrant *polkit_grant, const char *msg, void *user_data)
+{
+        g_debug ("error_msg='%s'", msg);
+}
+
+static void
+conversation_pam_text_info (PolKitGrant *polkit_grant, const char *msg, void *user_data)
+{
+        g_debug ("text_info='%s'", msg);
+}
+
+static PolKitResult
+conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
+{
+        polkit_bool_t keep_session = FALSE;
+        polkit_bool_t keep_always = FALSE;
+        PolKitResult overridden_auth_type;
+        UserData *ud = user_data;
+
+        switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+                break;
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+                break;
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+                keep_session = 
+                        polkit_gnome_auth_dialog_get_remember_session (POLKIT_GNOME_AUTH_DIALOG (ud->dialog));
+                break;
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                keep_always = 
+                        polkit_gnome_auth_dialog_get_remember_always (POLKIT_GNOME_AUTH_DIALOG (ud->dialog));
+                keep_session = 
+                        polkit_gnome_auth_dialog_get_remember_session (POLKIT_GNOME_AUTH_DIALOG (ud->dialog));
+                break;
+        default:
+                g_assert_not_reached ();
+        }
+
+        g_debug ("keep_always = %d", keep_always);
+        g_debug ("keep_session = %d", keep_session);
+
+        switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT;
+                break;
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH;
+                if (keep_session)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION;
+                else if (keep_always)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS;
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT;
+                break;
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH;
+                if (keep_session)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION;
+                else if (keep_always)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS;
+                break;
+
+        default:
+                g_assert_not_reached ();
+        }
+
+        return overridden_auth_type;
+}
+
+
+static void 
+conversation_done (PolKitGrant *polkit_grant, 
+                   polkit_bool_t gained_privilege, 
+                   polkit_bool_t input_was_bogus, 
+                   void *user_data)
+{
+        UserData *ud = user_data;
+        ud->gained_privilege = gained_privilege;
+        ud->was_bogus = input_was_bogus;
+
+        g_debug ("in conversation_done gained=%d, bogus=%d", gained_privilege, input_was_bogus);
+
+        if ((ud->was_bogus || ud->was_cancelled) && ud->dialog != NULL) {
+                gtk_widget_destroy (ud->dialog);
+                ud->dialog = NULL;
+        }
+
+        g_main_loop_quit (ud->loop);
+}
+
+static void
+child_watch_func (GPid pid,
+                  gint status,
+                  gpointer user_data)
+{
+        PolKitGrant *polkit_grant = user_data;
+        polkit_grant_child_func (polkit_grant, pid, WEXITSTATUS (status));
+}
+
+static int
+add_child_watch (PolKitGrant *polkit_grant, pid_t pid)
+{
+        return g_child_watch_add (pid, child_watch_func, polkit_grant);
+}
+
+static gboolean
+io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+        int fd;
+        PolKitGrant *polkit_grant = user_data;
+        fd = g_io_channel_unix_get_fd (channel);
+        polkit_grant_io_func (polkit_grant, fd);
+        return TRUE;
+}
+
+static int
+add_io_watch (PolKitGrant *polkit_grant, int fd)
+{
+        guint id = 0;
+        GIOChannel *channel;
+        channel = g_io_channel_unix_new (fd);
+        if (channel == NULL)
+                goto out;
+        id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, polkit_grant);
+        if (id == 0) {
+                g_io_channel_unref (channel);
+                goto out;
+        }
+        g_io_channel_unref (channel);
+out:
+        return id;
+}
+
+static void 
+remove_watch (PolKitGrant *polkit_auth, int watch_id)
+{
+        g_source_remove (watch_id);
+}
+
+static PolKitGrant *grant = NULL;
+static UserData *ud = NULL;
+
+static gboolean
+do_polkit_auth (PolKitContext  *pk_context,
+                DBusConnection *system_bus_connection,
+                const char     *caller_exe_name,
+                const char     *action_id, 
+                guint32         xid,
+                pid_t           caller_pid)
+{
+        PolKitAction *action = NULL;
+        PolKitCaller *caller = NULL;
+        DBusError error;
+        gboolean ret;
+        int num_tries;
+        PolKitPolicyCache *pk_cache;
+        PolKitPolicyFileEntry *pfe;
+        const char *message_markup;
+        const char *vendor;
+        const char *vendor_url;
+        const char *icon_name;
+
+        ret = FALSE;
+
+        ud = g_new0 (UserData, 1);
+
+        ud->requires_admin = FALSE;
+
+        action = polkit_action_new ();
+        polkit_action_set_action_id (action, action_id);
+
+        dbus_error_init (&error);
+        caller = polkit_caller_new_from_pid (system_bus_connection, 
+                                             caller_pid,
+                                             &error);
+        if (caller == NULL) {
+                if (dbus_error_is_set (&error)) {
+                        fprintf (stderr, "error: polkit_caller_new_from_pid(): %s: %s\n", 
+                                 error.name, error.message);
+                        goto error;
+                }
+        }
+
+        ud->dialog = NULL;
+        ud->loop = g_main_loop_new (NULL, TRUE);
+        ud->gained_privilege = FALSE;
+
+        pk_cache = polkit_context_get_policy_cache (pk_context);
+        if (pk_cache == NULL) {
+                g_warning ("Cannot load policy files");
+                goto error;
+        }
+        pfe = polkit_policy_cache_get_entry (pk_cache, action);
+        if (pfe == NULL) {
+                g_warning ("No policy file entry for given action");
+                goto error;
+        }
+
+        message_markup = polkit_policy_file_entry_get_action_message (pfe);
+        if (message_markup == NULL) {
+                g_warning ("No message markup for given action");
+                goto error;
+        }
+
+        vendor = polkit_policy_file_entry_get_action_vendor (pfe);
+        vendor_url = polkit_policy_file_entry_get_action_vendor_url (pfe);
+        icon_name = polkit_policy_file_entry_get_action_icon_name (pfe);
+        
+        ud->dialog = polkit_gnome_auth_dialog_new (
+                caller_exe_name,
+                action_id,
+                vendor,
+                vendor_url,
+                icon_name,
+                message_markup);
+
+        /* XID zero is used to mean "universal null resource or null atom" ... so if the
+         * caller is not an X11 client he can pass in 0 and we won't even attempt to
+         * find an X11 window that we're transient for.
+         */
+        if (xid != 0) {
+                GdkWindow *foreign_window;
+                foreign_window = gdk_window_foreign_new (xid);
+                if (foreign_window != NULL) {
+                        gtk_widget_realize (ud->dialog);
+                        gdk_window_set_transient_for (ud->dialog->window, foreign_window);
+                }
+        }
+
+	g_signal_connect (GTK_WIDGET (ud->dialog), "user-selected", G_CALLBACK (user_selected), ud);
+
+        /* grab the pointer and keyboard as soon as we are mapped */
+        g_signal_connect(ud->dialog, "map_event", G_CALLBACK(_do_grab), ud);
+
+        num_tries = 0;
+try_again:
+        grant = polkit_grant_new ();
+        ud->polkit_grant = grant;
+        polkit_grant_set_functions (grant,
+                                    add_io_watch,
+                                    add_child_watch,
+                                    remove_watch,
+                                    conversation_type,
+                                    conversation_select_admin_user,
+                                    conversation_pam_prompt_echo_off,
+                                    conversation_pam_prompt_echo_on,
+                                    conversation_pam_error_msg,
+                                    conversation_pam_text_info,
+                                    conversation_override_grant_type,
+                                    conversation_done,
+                                    ud);
+        ud->was_cancelled = FALSE;
+        ud->was_bogus = FALSE;
+        ud->new_user_selected = FALSE;
+        
+        if (!polkit_grant_initiate_auth (grant,
+                                         action,
+                                         caller)) {
+                g_warning ("Failed to initiate privilege grant.");
+                ret = 1;
+                goto error;
+        }
+        g_main_loop_run (ud->loop);
+
+        if (ud->new_user_selected) {
+                g_debug ("new user selected so restarting auth..");
+                polkit_grant_unref (grant);
+                grant = NULL;
+                goto try_again;
+        }
+
+        num_tries++;
+
+        g_debug ("gained_privilege=%d was_cancelled=%d was_bogus=%d.", 
+                 ud->gained_privilege, ud->was_cancelled, ud->was_bogus);
+
+        if (!ud->gained_privilege && !ud->was_cancelled && !ud->was_bogus) {
+                if (ud->dialog != NULL) {
+
+                        /* shake the dialog to indicate error */
+                        polkit_gnome_auth_dialog_indicate_auth_error (POLKIT_GNOME_AUTH_DIALOG (ud->dialog));
+
+                        if (num_tries < 3) {
+                                polkit_grant_unref (grant);
+                                grant = NULL;
+                                goto try_again;
+                        }
+                }
+        }
+
+        ret = ud->gained_privilege;
+
+error:
+
+        /* Ungrab keyboard and pointer */
+        gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+        gdk_pointer_ungrab (GDK_CURRENT_TIME);
+        g_debug ("Ungrabbed pointer and keyboard");
+
+        if (ud->dialog != NULL) {
+                gtk_widget_destroy (ud->dialog);
+                ud->dialog = NULL;
+        }
+        if (ud->loop != NULL)
+                g_main_loop_unref (ud->loop);
+        if (ud->admin_users != NULL)
+                g_strfreev (ud->admin_users);
+        if (ud->admin_user_selected != NULL)
+                g_free (ud->admin_user_selected);
+
+        if (grant != NULL)
+                polkit_grant_unref (grant);
+        if (action != NULL)
+                polkit_action_unref (action);
+        if (caller != NULL)
+                polkit_caller_unref (caller);
+
+        ud = NULL;
+        grant = NULL;
+
+        return ret;
+}
+
+static void
+do_cancel_auth (void)
+{
+        g_return_if_fail (ud != NULL);
+        g_return_if_fail (grant != NULL);
+
+        ud->was_cancelled = TRUE;
+        polkit_grant_cancel_auth (grant);
+}

Added: trunk/src/polkit-gnome-manager.h
==============================================================================
--- (empty file)
+++ trunk/src/polkit-gnome-manager.h	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifndef POLKIT_GNOME_MANAGER_H
+#define POLKIT_GNOME_MANAGER_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_GNOME_TYPE_MANAGER         (polkit_gnome_manager_get_type ())
+#define POLKIT_GNOME_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_GNOME_TYPE_MANAGER, PolKitGnomeManager))
+#define POLKIT_GNOME_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_GNOME_TYPE_MANAGER, PolKitGnomeManagerClass))
+#define POLKIT_GNOME_IS_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_GNOME_TYPE_MANAGER))
+#define POLKIT_GNOME_IS_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_GNOME_TYPE_MANAGER))
+#define POLKIT_GNOME_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_GNOME_TYPE_MANAGER, PolKitGnomeManagerClass))
+
+typedef struct PolKitGnomeManagerPrivate PolKitGnomeManagerPrivate;
+
+typedef struct
+{
+        GObject        parent;
+        PolKitGnomeManagerPrivate *priv;
+} PolKitGnomeManager;
+
+typedef struct
+{
+        GObjectClass   parent_class;
+} PolKitGnomeManagerClass;
+
+typedef enum
+{
+        POLKIT_GNOME_MANAGER_ERROR_GENERAL,
+        POLKIT_GNOME_MANAGER_ERROR_AUTH_IN_PROGRESS
+} PolKitGnomeManagerError;
+
+#define POLKIT_GNOME_MANAGER_ERROR polkit_gnome_manager_error_quark ()
+
+GQuark              polkit_gnome_manager_error_quark         (void);
+GType               polkit_gnome_manager_get_type            (void);
+PolKitGnomeManager *polkit_gnome_manager_new                 (gboolean no_exit);
+
+/* exported methods */
+gboolean            polkit_gnome_manager_show_dialog (PolKitGnomeManager    *manager,
+                                                      const char            *action_id,
+                                                      guint32                xid,
+                                                      DBusGMethodInvocation *context);
+
+gboolean            polkit_gnome_manager_obtain_authorization (PolKitGnomeManager    *manager,
+                                                               const char            *action_id,
+                                                               guint32                xid,
+                                                               guint32                pid,
+                                                               DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* POLKIT_GNOME_MANAGER_H */

Added: trunk/src/polkit-gnome-manager.xml
==============================================================================
--- (empty file)
+++ trunk/src/polkit-gnome-manager.xml	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,42 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+
+<node name="/">
+
+  <!-- this interface is deprecated and will be removed in a future release -->
+  <interface name="org.gnome.PolicyKit.Manager">
+    <method name="ShowDialog">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+
+      <!-- IN: PolicyKit action identifier; see PolKitAction -->
+      <arg name="action_id" direction="in" type="s"/>
+
+      <!-- IN: X11 window ID for the top-level X11 window the dialog will be transient for. -->
+      <arg name="xid" direction="in" type="u"/>
+
+      <!-- OUT: whether the user gained the authorization -->
+      <arg name="gained_authorization" direction="out" type="b"/>
+
+    </method>
+  </interface>
+
+  <interface name="org.freedesktop.PolicyKit.AuthenticationAgent">
+    <method name="ObtainAuthorization">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+
+      <!-- IN: PolicyKit action identifier; see PolKitAction -->
+      <arg name="action_id" direction="in" type="s"/>
+
+      <!-- IN: X11 window ID for the top-level X11 window the dialog will be transient for. -->
+      <arg name="xid" direction="in" type="u"/>
+
+      <!-- IN: Process ID to grant authorization to -->
+      <arg name="pid" direction="in" type="u"/>
+
+      <!-- OUT: whether the user gained the authorization -->
+      <arg name="gained_authorization" direction="out" type="b"/>
+
+    </method>
+  </interface>
+
+</node>

Added: trunk/tools/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/tools/Makefile.am	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,49 @@
+
+bin_PROGRAMS = polkit-gnome-authorization
+
+polkit_gnome_authorization_SOURCES = 			\
+	polkit-gnome-authorization.c
+
+polkit_gnome_authorization_CPPFLAGS = 			\
+	-I$(top_srcdir)					\
+	-DLIBEXECDIR=\""$(libexecdir)"\"		\
+	-DDATADIR=\""$(pkgdatadir)"\"			\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
+	$(DISABLE_DEPRECATED)				\
+	$(AM_CPPFLAGS)
+
+polkit_gnome_authorization_CFLAGS = 			\
+	$(GTK_CFLAGS)					\
+	$(SEXY_CFLAGS)					\
+	$(GNOME_VFS_CFLAGS)				\
+	$(DBUS_GLIB_CFLAGS)				\
+	$(POLKIT_DBUS_CFLAGS)				\
+	$(POLKIT_GRANT_CFLAGS)				\
+	$(WARN_CFLAGS)					\
+	$(AM_CFLAGS)
+
+polkit_gnome_authorization_LDFLAGS = 			\
+	$(AM_LDFLAGS)
+
+polkit_gnome_authorization_LDADD = 			\
+	$(GTK_LIBS)					\
+	$(SEXY_LIBS)					\
+	$(GNOME_VFS_LIBS)				\
+	$(DBUS_GLIB_LIBS)				\
+	$(POLKIT_DBUS_LIBS)				\
+	$(POLKIT_GRANT_LIBS)				\
+	$(INTLLIBS)					\
+	$(top_builddir)/polkit-gnome/libpolkit-gnome.la
+
+BUILT_SOURCES =						\
+	single-instance-glue.h
+
+single-instance-glue.h: single-instance.xml Makefile.am
+	dbus-binding-tool --prefix=single_instance --mode=glib-server --output=single-instance-glue.h $(top_srcdir)/tools/single-instance.xml
+
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = single-instance.xml
+
+clean-local :
+	rm -f *~

Added: trunk/tools/polkit-gnome-authorization.c
==============================================================================
--- (empty file)
+++ trunk/tools/polkit-gnome-authorization.c	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,2457 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * polkit-gnome-authorization: View and manage authorizations
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <polkit-gnome/polkit-gnome.h>
+#include <libsexy/sexy.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+static GType boxed_pfe_type;
+
+enum
+{
+        ICON_COLUMN,
+        ACTION_ID_COLUMN,
+        ACTION_NAME_COLUMN,
+        PFE_COLUMN,
+        N_COLUMNS
+};
+
+enum
+{
+        EXPLICIT_ICON_COLUMN,
+        EXPLICIT_ENTITY_NAME_COLUMN,
+        EXPLICIT_SCOPE_COLUMN,
+        EXPLICIT_CONSTRAINTS_COLUMN,
+        EXPLICIT_OBTAINED_COLUMN,
+        EXPLICIT_OBTAINED_HOW_COLUMN,
+        EXPLICIT_AUTH_OBJECT_COLUMN,
+        EXPLICIT_N_COLUMNS
+};
+
+static GdkPixbuf *person_pixbuf;
+static GdkPixbuf *action_pixbuf;
+static GdkPixbuf *namespace_pixbuf;
+static GdkPixbuf *stop_pixbuf;
+
+static GtkWidget *toplevel_window = NULL;
+static GtkWidget *notebook;
+static GtkTreeStore *action_store;
+static GtkWidget *action_treeview = NULL;
+static PolKitGnomeContext *pkgc;
+
+static GtkListStore *authlist_store;
+static GtkWidget *summary_box;
+
+static GtkWidget *summary_action_icon;
+static GtkWidget *summary_action_id_label;
+static GtkWidget *summary_action_desc_label;
+static GtkWidget *summary_label_any;
+static GtkWidget *summary_label_inactive;
+static GtkWidget *summary_label_active;
+static GtkWidget *summary_action_vendor_label;
+
+static PolKitAction *pk_read_action;
+static PolKitAction *pk_revoke_action;
+static PolKitAction *pk_grant_action;
+static PolKitAction *pk_modify_defaults_action;
+
+static PolKitGnomeToggleAction *read_action;
+static PolKitGnomeAction *revoke_action;
+static PolKitGnomeAction *revert_to_defaults_action;
+
+static GtkWidget *authlist_treeview;
+
+static GtkTreeSelection *action_treeselect;
+static GtkTreeSelection *authlist_treeselect;
+
+static GtkWidget *grant_button;
+static GtkWidget *block_button;
+
+static GSList *reffed_auths = NULL;
+
+static GtkWidget *edit_impl_button;
+static GtkWidget *revert_impl_button;
+
+
+typedef struct {
+        PolKitResult result;
+        char *text;
+} EditImplResult;
+
+static EditImplResult edit_impl_result_options[POLKIT_RESULT_N_RESULTS - 1] = {
+        
+        {POLKIT_RESULT_NO,                                  N_("No")},
+
+        {POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT,        N_("Admin Authentication (one shot)")},
+        {POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH,                 N_("Admin Authentication")},
+        {POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION,    N_("Admin Authentication (keep session)")},
+        {POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS,     N_("Admin Authentication (keep indefinitely)")},
+
+        {POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT,         N_("Authentication (one shot)")},
+        {POLKIT_RESULT_ONLY_VIA_SELF_AUTH,                  N_("Authentication")},
+        {POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION,     N_("Authentication (keep session)")},
+        {POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS,      N_("Authentication (keep indefinitely)")},
+
+        {POLKIT_RESULT_YES,                                 N_("Yes")},
+
+};
+
+static char *
+_get_string_for_polkit_result (PolKitResult result)
+{
+        int n;
+        for (n = 0; n < POLKIT_RESULT_N_RESULTS - 1; n++) {
+                if (edit_impl_result_options[n].result == result)
+                        return edit_impl_result_options[n].text;
+        }
+
+        return NULL;
+}
+
+static char *
+make_breakable (const char *string, char break_char)
+{
+        int n;
+        char **tokens;
+        GString *str;
+        char break_str[] = {break_char, '\0'};
+
+        tokens = g_strsplit (string, break_str, 0);
+        str = g_string_new ("");
+        for (n = 0; tokens[n] != NULL; n++) {
+                g_string_append (str, tokens[n]);
+                if (tokens[n+1] != NULL) {
+                        g_string_append_c (str, '.');
+                        /* U+200B ZERO WIDTH SPACE (this character is intended for line break control; it has no
+                         * width, but its presence between two characters does not prevent increased letter 
+                         * spacing in justification)
+                         */
+                        g_string_append_unichar (str, 0x200b); 
+                }
+        }
+        g_strfreev (tokens);
+
+        return g_string_free (str, FALSE);
+}
+
+static GdkPixbuf *
+get_face_for_pw (struct passwd *pw)
+{
+        GdkPixbuf *pixbuf;
+
+        pixbuf = NULL;
+        if (pw != NULL && pw->pw_dir != NULL) {
+                char *path;
+                path = g_strdup_printf ("%s/.face", pw->pw_dir);
+                pixbuf = gdk_pixbuf_new_from_file_at_scale (path, 24, 24, TRUE, NULL);
+                g_free (path);
+        }
+        
+        /* fall back to stock_person icon */
+        if (pixbuf == NULL)
+                pixbuf = g_object_ref (person_pixbuf);
+
+        return pixbuf;
+}
+
+static GdkPixbuf *
+get_face_for_uid (uid_t uid)
+{
+        return get_face_for_pw (getpwuid (uid));
+}
+
+typedef struct
+{
+        GtkWidget *vbox;
+        const char *action_id;
+        PolKitCaller *self;
+        PolKitSession *self_session;
+        char *self_session_objpath;
+        polkit_bool_t self_is_local;
+        polkit_bool_t self_is_active;
+        int num_entries;
+} AuthClosure;
+
+static PolKitPolicyFileEntry *
+get_selected_pfe (GtkTreeView *treeview)
+{
+        PolKitPolicyFileEntry *pfe;
+        GtkTreePath *path;
+        GtkTreeModel *treemodel;
+
+        pfe = NULL;
+
+        treemodel = gtk_tree_view_get_model (treeview);
+        gtk_tree_view_get_cursor (treeview, &path, NULL);
+        if (path != NULL) {
+                GtkTreeIter iter;
+
+                if (gtk_tree_model_get_iter (treemodel, &iter, path)) {
+
+                        gtk_tree_model_get (treemodel, &iter,
+                                            PFE_COLUMN,
+                                            &pfe,
+                                            -1);
+                }
+                gtk_tree_path_free (path);
+        }
+
+        return pfe;
+}
+
+#if 0
+static char *
+get_selected_action_id (GtkTreeView *treeview)
+{
+        char *action_id;
+        GtkTreePath *path;
+        GtkTreeModel *treemodel;
+
+        action_id = NULL;
+
+        treemodel = gtk_tree_view_get_model (treeview);
+        gtk_tree_view_get_cursor (treeview, &path, NULL);
+        if (path != NULL) {
+                GtkTreeIter iter;
+
+                if (gtk_tree_model_get_iter (treemodel, &iter, path)) {
+
+                        gtk_tree_model_get (treemodel, &iter,
+                                            ACTION_ID_COLUMN,
+                                            &action_id,
+                                            -1);
+                }
+                gtk_tree_path_free (path);
+        }
+
+        return action_id;
+}
+#endif
+
+static polkit_bool_t 
+_build_constraint_string (PolKitAuthorization *auth, PolKitAuthorizationConstraint *authc, void *user_data)
+{
+        char buf[128];
+        GString *str = (GString *) user_data;
+
+        if (str->len > 0)
+                g_string_append (str, _(", "));
+
+        switch (polkit_authorization_constraint_type (authc)) {
+        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL:
+                g_string_append (str, _("Must be on console"));
+                break;
+        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE:
+                g_string_append (str, _("Must be in active session"));
+                break;
+        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE:
+                g_string_append_printf (str, _("Must be program %s"),
+                                        polkit_authorization_constraint_get_exe (authc));
+                break;
+        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT:
+                g_string_append_printf (str, _("Must be SELinux Context %s"),
+                                        polkit_authorization_constraint_get_selinux_context (authc));
+                break;
+        default:
+                buf[sizeof (buf) - 1] = '\0';
+                polkit_authorization_constraint_to_string (authc, buf, sizeof (buf) - 1);
+                g_string_append (str, buf);
+                break;
+        }
+
+        return FALSE;
+}
+
+static polkit_bool_t
+add_authorization (PolKitAuthorizationDB *authdb,
+                   PolKitAuthorization   *auth, 
+                   void                  *user_data)
+{
+        time_t time_granted;
+        struct timeval now;
+        uid_t for_uid;
+        char *for_user;
+        pid_t pid;
+        polkit_uint64_t pid_start_time;
+        AuthClosure *ac = (AuthClosure *) user_data;
+        struct passwd *pw;
+        DBusError dbus_error;
+        char *scope;
+        uid_t auth_uid, pimp_uid;
+        polkit_bool_t is_negative;
+        char *how;
+        char *time_string;
+        gint64 delta;
+        char *constraint_string;
+        char exe[512];
+        GString *str;
+
+        is_negative = FALSE;
+
+        if (strcmp (polkit_authorization_get_action_id (auth), ac->action_id) != 0)
+                goto out;
+
+        dbus_error_init (&dbus_error);
+        if (!polkit_tracker_is_authorization_relevant (pkgc->pk_tracker, auth, &dbus_error)) {
+                if (dbus_error_is_set (&dbus_error)) {
+                        g_warning ("Cannot determine if authorization is relevant: %s: %s",
+                                   dbus_error.name,
+                                   dbus_error.message);
+                        dbus_error_free (&dbus_error);
+                } else {
+                        goto out;
+                }
+        }
+
+        time_granted = polkit_authorization_get_time_of_grant (auth);
+        gettimeofday (&now, NULL);
+        delta = (gint64) (now.tv_sec - time_granted);
+        if (delta < 60)
+                time_string = g_strdup (_("A moment ago"));
+        else if (delta < (60 * 60)) {
+                int minutes = (int) (delta / 60);
+                if (minutes == 1)
+                        time_string = g_strdup (_("1 minute ago"));
+                else
+                        time_string = g_strdup_printf (_("%d minutes ago"), minutes);
+        } else if (delta < (24 * 60 * 60)) {
+                int hours = (int) (delta / (60 * 60));
+                if (hours == 1)
+                        time_string = g_strdup (_("1 hour ago"));
+                else
+                        time_string = g_strdup_printf (_("%d hours ago"), hours);
+        } else {
+                int days = (int) (delta / (24 * 60 * 60));
+                if (days == 1)
+                        time_string = g_strdup (_("1 day ago"));
+                else
+                        time_string = g_strdup_printf (_("%d days ago"), days);
+        }
+
+        for_uid = polkit_authorization_get_uid (auth);
+        pw = getpwuid (for_uid);
+        if (pw != NULL)
+                if (pw->pw_gecos != NULL && strlen (pw->pw_gecos) > 0)
+                        for_user = g_strdup_printf ("%s (%s)", pw->pw_gecos, pw->pw_name);
+                else
+                        for_user = g_strdup_printf ("%s", pw->pw_name);
+        else
+                for_user = g_strdup_printf ("uid %d", for_uid);
+
+        how = NULL;
+        if (polkit_authorization_was_granted_via_defaults (auth, &auth_uid)) { 
+                pw = getpwuid (auth_uid);
+                if (pw != NULL)
+                        how = g_strdup_printf (_("Auth as %s (uid %d)"), pw->pw_name, auth_uid);
+                else
+                        how = g_strdup_printf (_("Auth as uid %d"), auth_uid);
+
+        } else if (polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative)) { 
+                pw = getpwuid (pimp_uid);
+                if (is_negative) {
+                        if (pw != NULL)
+                                how = g_strdup_printf (_("Blocked by %s (uid %d)"), pw->pw_name, pimp_uid);
+                        else
+                                how = g_strdup_printf (_("Blocked by uid %d"), pimp_uid);
+                } else {
+                        if (pw != NULL)
+                                how = g_strdup_printf (_("Granted by %s (uid %d)"), pw->pw_name, pimp_uid);
+                        else
+                                how = g_strdup_printf (_("Granted by uid %d"), pimp_uid);
+                }
+
+        }
+
+        if (how == NULL)
+                how = g_strdup ("");
+
+
+        scope = NULL;
+        switch (polkit_authorization_get_scope (auth)) {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT:
+                polkit_authorization_scope_process_get_pid (auth, &pid, &pid_start_time);
+                exe[sizeof (exe) - 1] = '\0';
+                polkit_sysdeps_get_exe_for_pid (pid, exe, sizeof (exe) - 1);
+                scope = g_strdup_printf (_("Single shot pid %d (%s)"), pid, exe);
+                break;
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
+                polkit_authorization_scope_process_get_pid (auth, &pid, &pid_start_time);
+                exe[sizeof (exe) - 1] = '\0';
+                polkit_sysdeps_get_exe_for_pid (pid, exe, sizeof (exe) - 1);
+                scope = g_strdup_printf (_("pid %d (%s)"), pid, exe);
+                break;
+        case POLKIT_AUTHORIZATION_SCOPE_SESSION:
+                scope = g_strdup (_("This session"));
+                break;
+        case POLKIT_AUTHORIZATION_SCOPE_ALWAYS:
+                scope = g_strdup (_("Always"));
+                break;
+        }
+
+        str = g_string_new (NULL);
+        polkit_authorization_constraints_foreach (auth, _build_constraint_string, str);
+        if (str->len > 0) {
+                constraint_string = g_string_free (str, FALSE);
+        } else {
+                g_string_free (str, TRUE);
+                constraint_string = g_strdup (_("None"));
+        }
+
+        GdkPixbuf *pixbuf;
+        GdkPixbuf *pixbuf_to_use;
+        pixbuf = get_face_for_uid (for_uid);
+
+        if (is_negative) {
+                pixbuf_to_use = gdk_pixbuf_copy (pixbuf);
+
+                /* turn black and white */
+                gdk_pixbuf_saturate_and_pixelate (pixbuf_to_use,
+                                                  pixbuf_to_use,
+                                                  0.0,
+                                                  FALSE);
+
+                /* blend the STOP icon on top */
+                gdk_pixbuf_composite (stop_pixbuf,
+                                      pixbuf_to_use,
+                                      12, 12, 12, 12,
+                                      12.0, 12.0, 0.5, 0.5,
+                                      GDK_INTERP_BILINEAR,
+                                      255);
+
+        } else {
+                pixbuf_to_use = g_object_ref (pixbuf);
+        }
+        g_object_unref (pixbuf);
+
+        GtkTreeIter iter;
+        gtk_list_store_append (authlist_store, &iter);
+        gtk_list_store_set (authlist_store, &iter,
+                            EXPLICIT_ICON_COLUMN, pixbuf_to_use,
+                            EXPLICIT_ENTITY_NAME_COLUMN, for_user,
+                            EXPLICIT_SCOPE_COLUMN, scope,
+                            EXPLICIT_CONSTRAINTS_COLUMN, constraint_string,
+                            EXPLICIT_OBTAINED_COLUMN, time_string,
+                            EXPLICIT_OBTAINED_HOW_COLUMN, how,
+                            EXPLICIT_AUTH_OBJECT_COLUMN, auth,
+                            -1);
+
+        /* ref the authorization */
+        reffed_auths = g_slist_prepend (reffed_auths, polkit_authorization_ref (auth));
+
+        g_free (for_user);
+        g_free (scope);
+        g_free (how);
+        g_free (time_string);
+        g_free (constraint_string);
+
+out:
+        return FALSE;
+}
+
+
+static PolKitAuthorization *
+get_selected_auth (GtkTreeView *treeview)
+{
+        PolKitAuthorization *auth;
+        GtkTreePath *path;
+        GtkTreeModel *treemodel;
+
+        auth = NULL;
+
+        treemodel = gtk_tree_view_get_model (treeview);
+        gtk_tree_view_get_cursor (treeview, &path, NULL);
+        if (path != NULL) {
+                GtkTreeIter iter;
+
+                if (gtk_tree_model_get_iter (treemodel, &iter, path)) {
+
+                        gtk_tree_model_get (treemodel, &iter,
+                                            EXPLICIT_AUTH_OBJECT_COLUMN,
+                                            &auth,
+                                            -1);
+                }
+                gtk_tree_path_free (path);
+        }
+
+        return auth;
+}
+
+static void
+update_authlist (void)
+{
+        GtkTreeView *treeview;
+        PolKitAuthorization *auth;
+
+        treeview = gtk_tree_selection_get_tree_view (authlist_treeselect);
+        auth = get_selected_auth (treeview);
+
+        if (auth != NULL) {
+                uid_t our_uid;
+                uid_t for_uid;
+                uid_t pimp_uid;
+                gboolean need_revoke;
+                polkit_bool_t is_negative;
+
+                polkit_gnome_action_set_sensitive (revoke_action, TRUE);
+
+                our_uid = getuid ();
+
+                for_uid = polkit_authorization_get_uid (auth);
+
+                /* we need org.fd.polkit.revoke if:
+                 *  1) the auth is for another user than us
+                 *  2) the auth was granted by someone else than us 
+                 */
+                need_revoke = FALSE;
+                if (for_uid != our_uid) {
+                        need_revoke = TRUE;
+                } else if (polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative)) {
+                        if (pimp_uid != our_uid) {
+                                need_revoke = TRUE;
+                        }
+                }
+
+                if (need_revoke) {
+                        g_object_set (revoke_action, 
+                                      "polkit_action", pk_revoke_action,
+                                      NULL);
+                } else {
+                        g_object_set (revoke_action, 
+                                      "polkit_action", NULL,
+                                      NULL);
+                }
+
+        } else {
+                polkit_gnome_action_set_sensitive (revoke_action, FALSE);
+        }
+
+
+}
+
+static void
+authlist_changed (GtkTreeSelection *selection, gpointer user_data)
+{
+        update_authlist ();
+}
+
+static void
+revoke_action_activate (PolKitGnomeAction *action, gpointer user_data)
+{
+        GtkTreeView *treeview;
+        PolKitAuthorization *auth;
+
+        treeview = gtk_tree_selection_get_tree_view (authlist_treeselect);
+        auth = get_selected_auth (treeview);
+
+        if (auth != NULL) {
+                PolKitAuthorizationDB *authdb;
+                PolKitError *pk_error;
+
+                authdb = polkit_context_get_authorization_db (pkgc->pk_context);
+
+                pk_error = NULL;
+                if (!polkit_authorization_db_revoke_entry (authdb, auth, &pk_error)) {
+                        g_warning ("Error doing revoke: %s: %s", 
+                                   polkit_error_get_error_name (pk_error), 
+                                   polkit_error_get_error_message (pk_error));
+                        polkit_error_free (pk_error);
+                }
+        }
+}
+
+
+static void
+_entity_combobox_set_sensitive (GtkCellLayout   *cell_layout,
+                                GtkCellRenderer *cell,
+                                GtkTreeModel    *tree_model,
+                                GtkTreeIter     *iter,
+                                gpointer         user_data)
+{
+	GtkTreePath *path;
+	gint *indices;
+	gboolean sensitive;
+	
+	path = gtk_tree_model_get_path (tree_model, iter);
+	indices = gtk_tree_path_get_indices (path);
+	if (indices[0] == 0)
+		sensitive = FALSE;
+	else
+		sensitive = TRUE;
+	gtk_tree_path_free (path);
+	
+	g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+static gboolean
+_real_user (struct passwd *pw)
+{
+        gboolean ret;
+
+        ret = FALSE;
+
+        /* TODO: there's probably better heuristic / tests than theses... */
+
+        if (pw->pw_uid < 500)
+                goto out;
+
+        if (pw->pw_shell == NULL || strcmp (pw->pw_shell, "/sbin/nologin") == 0)
+                goto out;
+
+        ret = TRUE;
+out:
+        return ret;
+}
+
+static void
+_create_entity_combobox_populate (GtkListStore *store, gboolean show_system_users)
+{
+	GtkTreeIter iter;
+        struct passwd *pw;
+
+        gtk_list_store_clear (store);
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter,
+			    0, NULL,
+			    1, _("Select user..."),
+			    2, NULL,
+			    -1);
+
+        /* we're single threaded so this is a fine way to iterate over all users */
+        for (setpwent(); (pw = getpwent ()) != NULL; ) {
+		char *real_name;
+		GdkPixbuf *pixbuf;
+
+		errno = 0;
+
+                if (!show_system_users && !_real_user (pw))
+                        continue;
+
+		/* Real name */
+		if (pw->pw_gecos != NULL && strlen (pw->pw_gecos) > 0)
+			real_name = g_strdup_printf (_("%s (%s)"), pw->pw_gecos, pw->pw_name);
+		else
+			real_name = g_strdup (pw->pw_name);
+
+		/* Load users face */
+		pixbuf = get_face_for_pw (pw);
+
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter,
+				    0, pixbuf,
+				    1, real_name,
+				    2, pw->pw_name,
+                                    3, pw->pw_uid,
+				    -1);
+
+		g_free (real_name);
+		g_object_unref (pixbuf);
+	}
+}
+
+static GtkWidget *
+_create_entity_combobox (void)
+{
+	GtkComboBox *combo;
+	GtkCellRenderer *renderer;
+        GtkListStore *store;
+
+	combo = GTK_COMBO_BOX (gtk_combo_box_new ());
+	store = gtk_list_store_new (4, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
+
+        /* sort on uid */
+        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 3, GTK_SORT_ASCENDING);
+
+        _create_entity_combobox_populate (store, FALSE);
+	
+	gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
+        g_object_unref (store);
+
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+					"pixbuf", 0,
+					NULL);
+	gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
+					    renderer,
+					    _entity_combobox_set_sensitive,
+					    NULL, NULL);
+	
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+					"text", 1,
+					NULL);
+	gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
+					    renderer,
+					    _entity_combobox_set_sensitive,
+					    NULL, NULL);
+
+	/* Initially select the "Select user..." ... */
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+
+        return GTK_WIDGET (combo);
+}
+
+typedef struct {
+        gboolean is_block;
+
+        uid_t uid;
+        PolKitGnomeAction *grant_action;
+        GtkWidget *combo;
+        gboolean constraint_none;
+        gboolean constraint_active;
+        gboolean constraint_console;
+        gboolean constraint_active_console;
+} EntitySelected;
+
+static void
+_entity_combobox_update_sensitivity (EntitySelected *entity_selected)
+{
+        polkit_gnome_action_set_sensitive (entity_selected->grant_action, (int) entity_selected->uid != -1);
+
+        if (entity_selected->is_block) {
+                g_object_set (entity_selected->grant_action,
+                              "polkit-action", (entity_selected->uid == getuid ()) ? NULL : pk_grant_action,
+                              NULL);
+        }
+}
+
+static void
+_entity_combobox_changed (GtkComboBox *widget, gpointer user_data)
+{
+	GtkTreeIter iter;
+        EntitySelected *entity_selected = (EntitySelected *) user_data;
+
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+		gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (widget)), &iter, 
+                                    3, &(entity_selected->uid), -1);
+                _entity_combobox_update_sensitivity (entity_selected);
+	}
+}
+
+static void
+_entity_radio_toggled (GtkToggleButton *toggle_button, gpointer user_data)
+{
+        gboolean *value = (gboolean *) user_data;
+
+        *value = gtk_toggle_button_get_active (toggle_button);
+}
+
+static void
+_entity_show_system_users_toggled (GtkToggleButton *toggle_button, gpointer user_data)
+{
+        GtkListStore *list_store;
+        gboolean show_system_users;
+        EntitySelected *entity_selected = (EntitySelected *) user_data;
+
+        show_system_users = gtk_toggle_button_get_active (toggle_button);
+
+        list_store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (entity_selected->combo)));
+        _create_entity_combobox_populate (list_store, show_system_users);
+
+	/* Initially select the "Select user..." ... */
+	gtk_combo_box_set_active (GTK_COMBO_BOX (entity_selected->combo), 0);
+        entity_selected->uid = -1;
+
+        _entity_combobox_update_sensitivity (entity_selected);
+}
+
+static void
+block_grant_do (gboolean is_block)
+{
+        gint response;
+        GtkWidget *label;
+        GtkWidget *dialog;
+        GtkWidget *grant_button;
+        GtkWidget *combo;
+        GtkTreeView *treeview;
+        PolKitPolicyFileEntry *pfe;
+        char *s;
+        char *s2;
+        const char *action_id;
+        EntitySelected entity_selected;
+        GtkWidget *show_system_entities;
+        GtkWidget *hbox;
+        GtkWidget *vbox;
+	GtkWidget *main_vbox;
+        GtkWidget *icon;
+        PolKitGnomeAction *grant_action;
+        GtkWidget *radio1;
+        GtkWidget *radio2;
+        GtkWidget *radio3;
+        GtkWidget *radio4;
+        GtkWidget *align;
+        GtkWidget *section_vbox;
+
+        treeview = gtk_tree_selection_get_tree_view (action_treeselect);
+        pfe = get_selected_pfe (treeview);
+        if (pfe == NULL)
+                goto out;
+
+        action_id = polkit_policy_file_entry_get_id (pfe);
+
+        dialog = gtk_dialog_new_with_buttons (is_block ? _("Grant Negative Authorization"): _("Grant Authorization"),
+                                              GTK_WINDOW (toplevel_window), 
+                                              GTK_DIALOG_MODAL,
+                                              GTK_STOCK_CANCEL,
+                                              GTK_RESPONSE_CANCEL,
+                                              NULL);
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+	gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_ADD);
+
+	hbox = gtk_hbox_new (FALSE, 12);
+	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, 0);
+
+	icon = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_DIALOG);
+	gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
+	gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
+
+	main_vbox = gtk_vbox_new (FALSE, 8);
+	gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
+
+        s2 = make_breakable (action_id, '.');
+        s = g_strdup_printf (
+                is_block ? 
+                _("<b><big>Granting a negative authorization for the <i>%s</i> action requires more information</big></b>") :
+                _("<b><big>Granting an authorization for the <i>%s</i> action requires more information</big></b>"),
+                s2);
+        g_free (s2);
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), s);
+        g_free (s);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, TRUE, 0);
+
+        if (is_block)
+                label = gtk_label_new (_("Select the user to block for the action and, optionally, any constraints on the negative authorization that you are about to grant."));
+        else
+                label = gtk_label_new (_("Select the beneficiary and, optionally, how to constrain the authorization that you are about to grant."));
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, TRUE, 0);
+
+        /* --------------------------------- */
+        /* Select user/group/selinux context */
+        /* --------------------------------- */
+        section_vbox = gtk_vbox_new (FALSE, 0);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<b>Beneficiary</b>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (section_vbox), label, FALSE, TRUE, 0);
+
+        vbox = gtk_vbox_new (FALSE, 4);
+        hbox = gtk_hbox_new (FALSE, 6);
+
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, TRUE, 6);
+
+        if (is_block)
+                label = gtk_label_new (_("Select the user that will receive the negative authorization."));
+        else
+                label = gtk_label_new (_("Select the user that will receive the authorization."));
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+
+        combo = _create_entity_combobox ();
+        gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0);
+	g_signal_connect (combo, "changed", G_CALLBACK (_entity_combobox_changed), &entity_selected);
+
+        show_system_entities = gtk_check_button_new_with_mnemonic (_("_Show system users"));
+        gtk_box_pack_start (GTK_BOX (vbox), show_system_entities, FALSE, TRUE, 0);
+	g_signal_connect (show_system_entities, "toggled", G_CALLBACK (_entity_show_system_users_toggled), &entity_selected);
+
+        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (main_vbox), section_vbox, FALSE, TRUE, 0);
+
+        /* -------------------- */
+        /* Physical constraints */
+        /* -------------------- */
+        section_vbox = gtk_vbox_new (FALSE, 0);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<b>Constraints</b>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (section_vbox), label, FALSE, TRUE, 0);
+
+        vbox = gtk_vbox_new (FALSE, 2);
+        hbox = gtk_hbox_new (FALSE, 6);
+
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, TRUE, 6);
+
+        label = gtk_label_new (_("Constraints limits the authorization such that it only applies under certain circumstances."));
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+
+        radio1 = gtk_radio_button_new_with_mnemonic (NULL,
+                                                     _("_None"));
+        radio2 = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio1)),
+                                                     _("Must be _in active session"));
+        radio3 = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio1)),
+                                                     _("Must be on _local console"));
+        radio4 = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio1)),
+                                                     _("Must be in _active session on local console"));
+        gtk_box_pack_start (GTK_BOX (vbox), radio1, FALSE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (vbox), radio2, FALSE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (vbox), radio3, FALSE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (vbox), radio4, FALSE, TRUE, 0);
+	g_signal_connect (radio1, "toggled", G_CALLBACK (_entity_radio_toggled), &(entity_selected.constraint_none));
+	g_signal_connect (radio2, "toggled", G_CALLBACK (_entity_radio_toggled), &(entity_selected.constraint_active));
+	g_signal_connect (radio3, "toggled", G_CALLBACK (_entity_radio_toggled), &(entity_selected.constraint_console));
+	g_signal_connect (radio4, "toggled", G_CALLBACK (_entity_radio_toggled), &(entity_selected.constraint_active_console));
+
+        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (main_vbox), section_vbox, FALSE, TRUE, 0);
+
+        /* ------- */
+        /* Buttons */
+        /* ------- */
+
+        if (is_block)
+                grant_action = polkit_gnome_action_new_default ("grant", pk_grant_action, 
+                                                                _("_Block..."),
+                                                                NULL);
+        else
+                grant_action = polkit_gnome_action_new_default ("grant", pk_grant_action, 
+                                                                _("_Grant..."),
+                                                                NULL);
+        polkit_gnome_action_set_sensitive (grant_action, FALSE);
+        grant_button = polkit_gnome_action_create_button (grant_action);
+        g_object_unref (grant_action);
+        gtk_dialog_add_action_widget (GTK_DIALOG (dialog), grant_button, GTK_RESPONSE_OK);
+
+	/* Listen when a new user is selected */
+        entity_selected.is_block = is_block;
+        entity_selected.uid = -1;
+        entity_selected.combo = combo;
+        entity_selected.grant_action = grant_action;
+        entity_selected.constraint_none = TRUE;
+        entity_selected.constraint_active = FALSE;
+        entity_selected.constraint_console = FALSE;
+        entity_selected.constraint_active_console = FALSE;
+
+        gtk_widget_show_all (dialog);
+        response = gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+
+        if (response == GTK_RESPONSE_OK) {
+                PolKitAction *action;
+                PolKitAuthorizationDB *authdb;
+                PolKitError *pk_error;
+                unsigned int num_constraints;
+                PolKitAuthorizationConstraint *constraints[3];
+
+                action = polkit_action_new ();
+                polkit_action_set_action_id (action, action_id);
+                
+                authdb = polkit_context_get_authorization_db (pkgc->pk_context);
+
+                num_constraints = 0;
+
+                if (entity_selected.constraint_none) {
+                        ;
+                } else if (entity_selected.constraint_active) {
+                        constraints[num_constraints++] = polkit_authorization_constraint_get_require_active ();
+                } else if (entity_selected.constraint_console) {
+                        constraints[num_constraints++] = polkit_authorization_constraint_get_require_local ();
+                } else {
+                        g_assert (entity_selected.constraint_active_console);
+                        constraints[num_constraints++] = polkit_authorization_constraint_get_require_local ();
+                        constraints[num_constraints++] = polkit_authorization_constraint_get_require_active ();
+                }
+                constraints[num_constraints] = NULL;
+
+                if ((int) entity_selected.uid != -1) {
+                        polkit_bool_t res;
+                        pk_error = NULL;
+
+                        if (is_block)
+                                res = polkit_authorization_db_grant_negative_to_uid (authdb,
+                                                                                     action,
+                                                                                     entity_selected.uid,
+                                                                                     constraints,
+                                                                                     &pk_error);
+                        else
+                                res = polkit_authorization_db_grant_to_uid (authdb,
+                                                                            action,
+                                                                            entity_selected.uid,
+                                                                            constraints,
+                                                                            &pk_error);
+
+                        if (!res) {
+                                g_warning ("Error granting auth: %s: %s\n", 
+                                           polkit_error_get_error_name (pk_error),
+                                           polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                        }
+                }
+        }
+
+out:
+        if (pfe != NULL) {
+                polkit_policy_file_entry_unref (pfe);
+        }
+}
+
+static void
+block_clicked (GtkButton *button, gpointer user_data)
+{
+        block_grant_do (TRUE);
+}
+
+static void
+grant_clicked (GtkButton *button, gpointer user_data)
+{
+        block_grant_do (FALSE);
+}
+
+typedef struct {
+        PolKitGnomeAction *modify_defaults_action;
+
+        PolKitResult any_orig;
+        PolKitResult inactive_orig;
+        PolKitResult active_orig;
+
+        PolKitResult any;
+        PolKitResult inactive;
+        PolKitResult active;        
+} EditImplData;
+
+
+static void
+edit_impl_update_sensitive (EditImplData *data)
+{
+        gboolean sensitive;
+
+        if (data->any      != data->any_orig || 
+            data->inactive != data->inactive_orig || 
+            data->active   != data->active_orig) {
+                sensitive = TRUE;
+        } else {
+                sensitive = FALSE;
+        }
+        polkit_gnome_action_set_sensitive (data->modify_defaults_action, sensitive);
+}
+
+static void
+edit_impl_combo_any_changed (GtkComboBox *combo, gpointer user_data)
+{
+        int active;
+        PolKitResult result;
+        EditImplData *data = (EditImplData *) user_data;
+
+        active = gtk_combo_box_get_active (combo);
+        g_assert (active >= 0 && active < POLKIT_RESULT_N_RESULTS - 1);
+        result = edit_impl_result_options[active].result;
+        data->any = result;
+
+        edit_impl_update_sensitive (data);
+}
+
+static void
+edit_impl_combo_inactive_changed (GtkComboBox *combo, gpointer user_data)
+{
+        int active;
+        PolKitResult result;
+        EditImplData *data = (EditImplData *) user_data;
+
+        active = gtk_combo_box_get_active (combo);
+        g_assert (active >= 0 && active < POLKIT_RESULT_N_RESULTS - 1);
+        result = edit_impl_result_options[active].result;
+        data->inactive = result;
+
+        edit_impl_update_sensitive (data);
+}
+
+static void
+edit_impl_combo_active_changed (GtkComboBox *combo, gpointer user_data)
+{
+        int active;
+        PolKitResult result;
+        EditImplData *data = (EditImplData *) user_data;
+
+        active = gtk_combo_box_get_active (combo);
+        g_assert (active >= 0 && active < POLKIT_RESULT_N_RESULTS - 1);
+        result = edit_impl_result_options[active].result;
+        data->active = result;
+
+        edit_impl_update_sensitive (data);
+}
+
+static void
+edit_impl_clicked (GtkButton *button, gpointer user_data)
+{
+        char *s;
+        char *s2;
+        const char *action_id;
+        const char *action_desc;
+        GtkTreeView *treeview;
+        PolKitPolicyFileEntry *pfe;
+        PolKitPolicyDefault *defaults;
+        GtkWidget *label;
+        GtkWidget *dialog;
+        GtkWidget *hbox;
+	GtkWidget *main_vbox;
+        GtkWidget *icon;
+        int response;
+        EditImplData data;
+        GtkWidget *modify_defaults_button;
+
+        treeview = gtk_tree_selection_get_tree_view (action_treeselect);
+        pfe = get_selected_pfe (treeview);
+        if (pfe == NULL)
+                goto out;
+
+        defaults = polkit_policy_file_entry_get_default (pfe);
+
+        action_id = polkit_policy_file_entry_get_id (pfe);
+        action_desc = polkit_policy_file_entry_get_action_description (pfe);
+
+        dialog = gtk_dialog_new_with_buttons (_("Edit Implicit Authorizations"),
+                                              GTK_WINDOW (toplevel_window), 
+                                              GTK_DIALOG_MODAL,
+                                              GTK_STOCK_CANCEL,
+                                              GTK_RESPONSE_CANCEL,
+                                              NULL);
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+	hbox = gtk_hbox_new (FALSE, 12);
+	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, 0);
+
+	icon = gtk_image_new_from_stock (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_DIALOG);
+	gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
+	gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
+	gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
+
+	main_vbox = gtk_vbox_new (FALSE, 8);
+	gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<b><big>Choose new implicit authorizations</big></b>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, TRUE, 0);
+
+        int n;
+        GtkWidget *table;
+        GtkWidget *edit_impl_combo_any;
+        GtkWidget *edit_impl_combo_inactive;
+        GtkWidget *edit_impl_combo_active;
+
+
+        label = gtk_label_new (NULL);
+        s2 = make_breakable (action_id, '.');
+        s = g_strdup_printf (_("Implicit authorizations are authorizations that are granted "
+                               "automatically to users under certain circumstances. Choose "
+                               "what is required for the action <i>%s</i>."),
+                             s2);
+        gtk_label_set_markup (GTK_LABEL (label), s);
+        g_free (s);
+        g_free (s2);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, TRUE, 0);
+
+
+        table = gtk_table_new (3, 2, FALSE);
+        gtk_table_set_col_spacings (GTK_TABLE (table), 8);
+        gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+        for (n = 0; n < 3; n++) {
+                int m;
+                const char *s;
+                GtkWidget **combo;
+                PolKitResult *allow;
+                GCallback callback;
+
+                switch (n) {
+                default:
+                case 0:
+                        s = _("<i>Anyone:</i>");
+                        combo = &edit_impl_combo_any;
+                        allow = &data.any;
+                        data.any_orig = data.any = polkit_policy_default_get_allow_any (defaults);
+                        callback = (GCallback) edit_impl_combo_any_changed;
+                        break;
+                case 1:
+                        s = _("<i>Console:</i>");
+                        combo = &edit_impl_combo_inactive;
+                        allow = &data.inactive;
+                        data.inactive_orig = data.inactive = polkit_policy_default_get_allow_inactive (defaults);
+                        callback = (GCallback) edit_impl_combo_inactive_changed;
+                        break;
+                case 2:
+                        s = _("<i>Active Console:</i>");
+                        combo = &edit_impl_combo_active;
+                        allow = &data.active;
+                        data.active_orig = data.active = polkit_policy_default_get_allow_active (defaults);
+                        callback = (GCallback) edit_impl_combo_active_changed;
+                        break;
+                }
+
+                label = gtk_label_new (NULL);
+                gtk_label_set_markup (GTK_LABEL (label), s);
+                gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+                gtk_table_attach (GTK_TABLE (table), label, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+
+                *combo = gtk_combo_box_new_text ();
+                for (m = 0; m < POLKIT_RESULT_N_RESULTS - 1; m++) {
+                        gtk_combo_box_append_text (GTK_COMBO_BOX (*combo), (edit_impl_result_options[m]).text);
+                        if ((edit_impl_result_options[m]).result == *allow) {
+                                gtk_combo_box_set_active (GTK_COMBO_BOX (*combo), m);
+                        }
+                }
+                g_signal_connect (*combo, "changed", callback, &data);
+
+                gtk_table_attach (GTK_TABLE (table), *combo, 1, 2, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+        }
+        gtk_box_pack_start (GTK_BOX (main_vbox), table, TRUE, TRUE, 0);
+
+
+        data.modify_defaults_action = polkit_gnome_action_new_default ("ModifyDefaults", 
+                                                                       pk_modify_defaults_action,
+                                                                       _("_Modify..."),
+                                                                       NULL);
+        polkit_gnome_action_set_sensitive (data.modify_defaults_action, FALSE);
+        modify_defaults_button = polkit_gnome_action_create_button (data.modify_defaults_action);
+        g_object_unref (data.modify_defaults_action);
+        gtk_dialog_add_action_widget (GTK_DIALOG (dialog), modify_defaults_button, GTK_RESPONSE_OK);
+
+        gtk_widget_show_all (dialog);
+        response = gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+
+        if (response == GTK_RESPONSE_OK) {
+                PolKitError *pk_error;
+                PolKitPolicyDefault *new_defaults;
+
+                new_defaults = polkit_policy_default_new ();
+                polkit_policy_default_set_allow_any      (new_defaults, data.any);
+                polkit_policy_default_set_allow_inactive (new_defaults, data.inactive);
+                polkit_policy_default_set_allow_active   (new_defaults, data.active);
+
+                pk_error = NULL;
+                polkit_policy_file_entry_debug (pfe);
+                if (!polkit_policy_file_entry_set_default (pfe, new_defaults, &pk_error)) {
+                        g_warning ("Error: code=%d: %s: %s",
+                                   polkit_error_get_error_code (pk_error),
+                                   polkit_error_get_error_name (pk_error),
+                                   polkit_error_get_error_message (pk_error));
+                        polkit_error_free (pk_error);
+                }
+
+                polkit_policy_default_unref (new_defaults);
+        }
+out:
+        if (pfe != NULL) {
+                polkit_policy_file_entry_unref (pfe);
+        }
+}
+
+static void
+revert_impl_activate (PolKitGnomeAction *action, gpointer user_data)
+{
+        GtkTreeView *treeview;
+        PolKitPolicyFileEntry *pfe;
+        PolKitPolicyDefault *factory_defaults;
+        PolKitError *pk_error;
+
+        treeview = gtk_tree_selection_get_tree_view (action_treeselect);
+        pfe = get_selected_pfe (treeview);
+        if (pfe == NULL)
+                goto out;
+
+        factory_defaults = polkit_policy_file_entry_get_default_factory (pfe);
+
+        pk_error = NULL;
+        if (!polkit_policy_file_entry_set_default (pfe, factory_defaults, &pk_error)) {
+                g_warning ("Error: code=%d: %s: %s",
+                           polkit_error_get_error_code (pk_error),
+                           polkit_error_get_error_name (pk_error),
+                           polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+        }
+        
+out:
+        if (pfe != NULL) {
+                polkit_policy_file_entry_unref (pfe);
+        }
+}
+
+static void
+summary_action_vendor_url_activated (SexyUrlLabel *url_label, char *url, gpointer user_data)
+{
+        if (url != NULL) {
+                gnome_vfs_url_show (url);
+        }
+}
+
+static void
+update_summary (void)
+{
+        const char *action_id;
+        const char *description;
+        PolKitPolicyFileEntry *pfe;
+        PolKitResult allow_any;
+        PolKitResult allow_inactive;
+        PolKitResult allow_active;
+        PolKitPolicyDefault *defaults;
+        GtkTreeView *treeview;
+
+        treeview = gtk_tree_selection_get_tree_view (action_treeselect);
+        pfe = get_selected_pfe (treeview);
+
+        gtk_list_store_clear (authlist_store);
+
+        /* unref all reffed auths */
+        g_slist_foreach (reffed_auths, (GFunc) polkit_authorization_unref, NULL);
+        g_slist_free (reffed_auths);
+        reffed_auths = NULL;
+
+
+        if (pfe != NULL) {
+                const char *vendor;
+                const char *vendor_url;
+                const char *icon_name;
+
+                action_id = polkit_policy_file_entry_get_id (pfe);
+                description = polkit_policy_file_entry_get_action_description (pfe);
+                vendor = polkit_policy_file_entry_get_action_vendor (pfe);
+                vendor_url = polkit_policy_file_entry_get_action_vendor_url (pfe);
+                icon_name = polkit_policy_file_entry_get_action_icon_name (pfe);
+
+                defaults = polkit_policy_file_entry_get_default (pfe);
+                allow_any = polkit_policy_default_get_allow_any (defaults);
+                allow_inactive = polkit_policy_default_get_allow_inactive (defaults);
+                allow_active = polkit_policy_default_get_allow_active (defaults);
+
+                gtk_widget_set_sensitive (edit_impl_button, TRUE);
+                gtk_widget_set_sensitive (grant_button, TRUE);
+
+                if (polkit_policy_default_equals (defaults, polkit_policy_file_entry_get_default_factory (pfe)))
+                        polkit_gnome_action_set_sensitive (revert_to_defaults_action, FALSE);
+                else
+                        polkit_gnome_action_set_sensitive (revert_to_defaults_action, TRUE);
+
+                gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
+
+
+                if (vendor_url != NULL) {
+                        char *s;
+
+                        s = g_strdup_printf ("<a href=\"%s\">%s</a>", vendor_url, vendor);
+                        sexy_url_label_set_markup (SEXY_URL_LABEL (summary_action_vendor_label), s);
+                        g_free (s);
+
+                        s = g_strdup_printf (_("Click to open %s"), vendor_url);
+                        gtk_widget_set_tooltip_markup (summary_action_vendor_label, s);
+                        g_free (s);
+
+                } else {
+                        sexy_url_label_set_markup (SEXY_URL_LABEL (summary_action_vendor_label), vendor);
+                        gtk_widget_set_tooltip_markup (summary_action_vendor_label, NULL);
+                }
+
+                if (icon_name != NULL) {
+                        GdkPixbuf *pixbuf;
+
+                        pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), 
+                                                           icon_name, 
+                                                           48, 
+                                                           0, 
+                                                           NULL);
+                        if (pixbuf != NULL) {
+                                gtk_image_set_from_pixbuf (GTK_IMAGE (summary_action_icon), pixbuf);
+                                g_object_unref (pixbuf);
+                        } else {
+                                gtk_image_clear (GTK_IMAGE (summary_action_icon));
+                        }
+                } else {
+                        gtk_image_clear (GTK_IMAGE (summary_action_icon));
+                }
+                
+        } else {
+                action_id = "";
+                description = "";
+
+                /* no active item */
+                allow_any = -1;
+                allow_inactive = -1;
+                allow_active = -1;
+
+                gtk_widget_set_sensitive (edit_impl_button, FALSE);
+                gtk_widget_set_sensitive (grant_button, FALSE);
+
+                polkit_gnome_action_set_sensitive (revert_to_defaults_action, FALSE);
+
+                gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1);
+        }
+
+        /* ---- Action ---- */
+        gtk_label_set_markup (GTK_LABEL (summary_action_id_label), action_id);
+        gtk_label_set_markup (GTK_LABEL (summary_action_desc_label), description);
+
+        /* ---- Implicit Authorizations ---- */
+        gtk_label_set_markup (GTK_LABEL (summary_label_any), _get_string_for_polkit_result (allow_any));
+        gtk_label_set_markup (GTK_LABEL (summary_label_inactive), _get_string_for_polkit_result (allow_inactive));
+        gtk_label_set_markup (GTK_LABEL (summary_label_active), _get_string_for_polkit_result (allow_active));
+
+        /* ---- Explicit Authorizations ---- */
+        PolKitCaller *self;
+        DBusError dbus_error;
+        dbus_error_init (&dbus_error);
+        self = polkit_tracker_get_caller_from_pid (pkgc->pk_tracker, getpid (), &dbus_error);
+
+        PolKitAuthorizationDB *authdb;
+        authdb = polkit_context_get_authorization_db (pkgc->pk_context);
+        if (authdb != NULL && strlen (action_id) > 0 && self != NULL) {
+                AuthClosure ac;
+                
+                ac.action_id = action_id;
+                ac.self = self;
+                ac.self_session = NULL;
+                ac.self_session_objpath = NULL;
+                ac.self_is_local = FALSE;
+                ac.self_is_active = FALSE;
+                ac.num_entries = 0;
+
+                polkit_caller_get_ck_session (self, &ac.self_session);
+                polkit_session_get_ck_objref (ac.self_session, &ac.self_session_objpath);
+                polkit_session_get_ck_is_local (ac.self_session, &ac.self_is_local);
+                polkit_session_get_ck_is_active (ac.self_session, &ac.self_is_active);
+
+                PolKitAction *action;
+                action = polkit_action_new ();
+                polkit_action_set_action_id (action, action_id);
+                PolKitError *pk_error = NULL;
+                gboolean ret;
+
+                if (polkit_gnome_action_get_polkit_result (POLKIT_GNOME_ACTION (read_action)) == POLKIT_RESULT_YES) {
+                        ret = polkit_authorization_db_foreach_for_action (authdb,
+                                                                          action,
+                                                                          add_authorization,
+                                                                          &ac,
+                                                                          &pk_error);
+                } else {
+                        ret = polkit_authorization_db_foreach_for_action_for_uid (authdb,
+                                                                                  action,
+                                                                                  getuid (),
+                                                                                  add_authorization,
+                                                                                  &ac,
+                                                                                  &pk_error);
+                }
+
+                if (!ret) {
+                        if (pk_error != NULL) {
+                                g_warning ("Error: code=%d: %s",
+                                           polkit_error_get_error_code (pk_error),
+                                           polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                        }
+                }
+                polkit_action_unref (action);
+
+                GtkTreePath *path;
+                path = gtk_tree_path_new_first ();
+
+                /* select the first entry in the authlist */
+                gtk_tree_view_set_cursor (GTK_TREE_VIEW (authlist_treeview),
+                                          path,
+                                          NULL,
+                                          FALSE);
+        }
+
+        update_authlist ();
+
+        if (pfe != NULL) {
+                polkit_policy_file_entry_unref (pfe);
+        }
+}
+
+
+static void
+action_tree_changed (GtkTreeSelection *selection, gpointer user_data)
+{
+        update_summary ();
+}
+
+#if 0
+static gboolean
+is_authorized_from_pfe (PolKitPolicyFileEntry *pfe)
+{
+        PolKitResult pk_result;
+        PolKitAction *pk_action;
+        gboolean is_authorized;
+        static PolKitCaller *pk_caller = NULL;
+
+        if (pk_caller == NULL) {
+                DBusError dbus_error;
+                dbus_error_init (&dbus_error);
+                pk_caller = polkit_tracker_get_caller_from_pid (pkgc->pk_tracker, getpid (), &dbus_error);
+        }
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, polkit_policy_file_entry_get_id (pfe));
+        pk_result = polkit_context_is_caller_authorized (pkgc->pk_context, pk_action, pk_caller, FALSE, NULL);
+        polkit_action_unref (pk_action);
+
+        is_authorized = (pk_result == POLKIT_RESULT_YES);
+
+        return is_authorized;
+}
+#endif
+
+static polkit_bool_t
+build_action_list_pfe_iterator (PolKitPolicyCache *policy_cache, PolKitPolicyFileEntry *pfe, void *user_data)
+{
+        GSList **pfe_list = (GSList **) user_data;
+
+        *pfe_list = g_slist_append (*pfe_list, pfe);
+
+        /* keep iterating */
+        return FALSE;
+}
+
+static gint
+pfe_compare (gconstpointer a, gconstpointer b)
+{
+        PolKitPolicyFileEntry *pfe_a = (PolKitPolicyFileEntry *) a;
+        PolKitPolicyFileEntry *pfe_b = (PolKitPolicyFileEntry *) b;
+
+        return - g_ascii_strcasecmp (polkit_policy_file_entry_get_id (pfe_a),
+                                     polkit_policy_file_entry_get_id (pfe_b));
+}
+
+typedef struct {
+        const char *action_id;
+        gboolean found;
+        GtkTreeIter iter;
+} FIBAData;
+
+static gboolean 
+find_iter_by_action_id_foreach (GtkTreeModel *model,
+                                GtkTreePath *path,
+                                GtkTreeIter *iter,
+                                gpointer data)
+{
+        gboolean ret;
+        char *action_id = NULL;
+        FIBAData *fiba_data = (FIBAData *) data;
+
+        ret = FALSE;
+        gtk_tree_model_get (model, iter, ACTION_ID_COLUMN, &action_id, -1);
+        if (strcmp (action_id, fiba_data->action_id) == 0) {
+                fiba_data->found = TRUE;
+                fiba_data->iter = *iter;
+                ret = TRUE;
+        }
+        if (action_id != NULL)
+                g_free (action_id);
+
+        return ret;
+}
+
+
+static gboolean
+find_iter_by_action_id (const char *action_id, GtkTreeIter *out_iter)
+{
+        FIBAData fiba_data;
+        gboolean ret;
+
+        fiba_data.action_id = action_id;
+        fiba_data.found = FALSE;
+        gtk_tree_model_foreach (GTK_TREE_MODEL (action_store), find_iter_by_action_id_foreach, &fiba_data);
+        if (fiba_data.found) {
+                if (out_iter != NULL)
+                        *out_iter = fiba_data.iter;
+                ret = TRUE;
+        } else {
+                ret = FALSE;
+        }
+
+        return ret;
+}
+
+static void
+get_namespace_iter (const char *action_id, GtkTreeIter *out_iter)
+{
+        int n;
+        int len;
+        char *namespace;
+        char *pretty_name;
+        GtkTreeIter parent_iter;
+        gboolean got_parent;
+
+        got_parent = FALSE;
+
+        namespace = g_strdup (action_id);
+        len = strlen (namespace);
+        if (namespace[len - 1] == '.')
+                len--;
+        for (n =  len - 1; n >= 0; n--) {
+                if (namespace[n] == '.') {
+                        //namespace[n] = '\0';
+                        break;
+                }
+                namespace[n] = '\0';
+        }
+
+        /* see if we have an element for namespace already */
+        if (find_iter_by_action_id (namespace, out_iter))
+                return;
+
+        /* get a parent */
+        len = strlen (namespace);
+        for (n = 0; n < len - 1; n++) {
+                if (namespace[n] == '.') {
+                        get_namespace_iter (namespace, &parent_iter);
+                        got_parent = TRUE;
+                }
+        }
+
+        pretty_name = g_strdup (namespace);
+        len = strlen (pretty_name);
+        if (len > 0) {
+                pretty_name[len - 1] = '\0';
+                len--;
+        }
+        for (n = len - 1; n >= 0; n--) {
+                if (pretty_name[n] == '.') {
+                        char *tmp;
+                        tmp = g_strdup (pretty_name + n + 1);
+                        g_free (pretty_name);
+                        pretty_name = tmp;
+                        break;
+                }
+        }
+
+        gtk_tree_store_append (action_store, out_iter, got_parent ? &parent_iter : NULL);
+        gtk_tree_store_set (action_store, out_iter,
+                            ICON_COLUMN, namespace_pixbuf,
+                            ACTION_ID_COLUMN, namespace,
+                            ACTION_NAME_COLUMN, pretty_name,
+                            -1);
+
+        if (action_treeview != NULL && got_parent) {
+                GtkTreePath *path;
+                path = gtk_tree_model_get_path (GTK_TREE_MODEL (action_store), &parent_iter);
+                gtk_tree_view_expand_row (GTK_TREE_VIEW (action_treeview),
+                                          path,
+                                          FALSE);
+                gtk_tree_path_free (path);
+        }
+
+        g_free (namespace);
+        g_free (pretty_name);
+}
+
+static GSList *to_remove = NULL;
+
+static gboolean
+update_action_tree_cull (GtkTreeModel *model,
+                         GtkTreePath  *path,
+                         GtkTreeIter  *iter,
+                         gpointer      user_data)
+{
+        char *action_id;
+        GSList *pfe_list = (GSList *) user_data;
+        GSList *l;
+        PolKitPolicyFileEntry *pfe;
+
+        gtk_tree_model_get (model, iter,
+                            ACTION_ID_COLUMN,
+                            &action_id,
+                            PFE_COLUMN,
+                            &pfe,
+                            -1);
+        if (pfe != NULL) {
+                polkit_policy_file_entry_unref (pfe);
+        }
+        if (action_id == NULL)
+                goto out;
+
+        /* I'm sure one could use a better data structure that is O(log n) instead of this O(n) */
+
+        if (pfe == NULL) {
+                /* this is a name space */
+                for (l = pfe_list; l != NULL; l = l->next) {
+                        const char *action_id_l;
+                        PolKitPolicyFileEntry *pfe_l = l->data;
+                        
+                        action_id_l = polkit_policy_file_entry_get_id (pfe_l);
+                        if (g_str_has_prefix (action_id_l, action_id))
+                                goto found;
+                }
+        } else {
+                /* this is an action */
+                for (l = pfe_list; l != NULL; l = l->next) {
+                        const char *action_id_l;
+                        PolKitPolicyFileEntry *pfe_l = l->data;
+                        
+                        action_id_l = polkit_policy_file_entry_get_id (pfe_l);
+                        if (strcmp (action_id, action_id_l) == 0)
+                                goto found;
+                }
+        }
+
+        to_remove = g_slist_prepend (to_remove, gtk_tree_iter_copy (iter));
+
+found:
+        g_free (action_id);
+
+out:
+        return FALSE;
+}
+
+
+static void
+update_action_tree (void)
+{
+        PolKitPolicyCache *pc;
+        GSList *pfe_list;
+        GSList *l;
+
+        pfe_list = NULL;
+        pc = polkit_context_get_policy_cache (pkgc->pk_context);
+        polkit_policy_cache_foreach (pc, build_action_list_pfe_iterator, &pfe_list);
+        pfe_list = g_slist_sort (pfe_list, pfe_compare);
+
+        /* first insert new items from list into the tree... */
+        for (l = pfe_list; l != NULL; l = l->next) {
+                GtkTreeIter iter;
+                const char *action_id;
+                const char *description;
+                const char *icon_name;
+                PolKitPolicyFileEntry *pfe = l->data;
+                GtkTreeIter name_space_iter;
+                        
+                action_id = polkit_policy_file_entry_get_id (pfe);
+                description = polkit_policy_file_entry_get_action_description (pfe);
+                icon_name = polkit_policy_file_entry_get_action_icon_name (pfe);
+
+                /* see if we have this one already */
+                if (find_iter_by_action_id (action_id, &iter)) {
+                        /* we do; update the pfe */
+                        gtk_tree_store_set (action_store, &iter,
+                                            PFE_COLUMN, pfe,
+                                            -1);
+                        continue;
+                }
+
+                get_namespace_iter (action_id, &name_space_iter);
+                
+                gtk_tree_store_append (action_store, &iter, &name_space_iter);
+                gtk_tree_store_set (action_store, &iter,
+                                    ICON_COLUMN, action_pixbuf,
+                                    ACTION_ID_COLUMN, action_id,
+                                    ACTION_NAME_COLUMN, description,
+                                    PFE_COLUMN, pfe,
+                                    -1);
+
+                if (action_treeview != NULL) {
+                        GtkTreePath *path;
+                        path = gtk_tree_model_get_path (GTK_TREE_MODEL (action_store), &name_space_iter);
+                        gtk_tree_view_expand_row (GTK_TREE_VIEW (action_treeview),
+                                                  path,
+                                                  FALSE);
+                        gtk_tree_path_free (path);
+                }
+        }
+
+        /* ... then run through the tree and cull items no longer in the list */
+        to_remove = NULL;
+        gtk_tree_model_foreach (GTK_TREE_MODEL (action_store), update_action_tree_cull, pfe_list);
+        for (l = to_remove; l != NULL; l = l->next) {
+                GtkTreeIter *iter = l->data;
+                gtk_tree_store_remove (action_store, iter);
+                gtk_tree_iter_free (iter);
+        }
+        g_slist_free (to_remove);
+        to_remove = NULL;
+
+        g_slist_free (pfe_list);
+}
+
+static GtkWidget *
+action_list_new (void)
+{
+        GtkCellRenderer *renderer;
+        GtkTreeViewColumn *column;
+        GtkWidget *treeview;
+
+        action_store = gtk_tree_store_new (N_COLUMNS,
+                                           GDK_TYPE_PIXBUF,
+                                           G_TYPE_STRING,
+                                           G_TYPE_STRING,
+                                           boxed_pfe_type);
+
+        treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (action_store));
+
+        column = gtk_tree_view_column_new ();
+        renderer = gtk_cell_renderer_pixbuf_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", ICON_COLUMN, NULL);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "markup", ACTION_NAME_COLUMN, NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+
+        action_treeselect = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+        gtk_tree_selection_set_mode (action_treeselect, GTK_SELECTION_SINGLE);
+        g_signal_connect (action_treeselect, "changed", (GCallback) action_tree_changed, NULL);
+
+        update_action_tree ();
+
+        gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
+
+        return treeview;
+}
+
+static void
+_pk_config_changed (PolKitGnomeContext *pk_g_context, gpointer user_data)
+{
+        update_action_tree ();
+        update_summary ();
+}
+
+static void
+_pk_console_kit_db_changed (PolKitGnomeContext *pk_g_context, gpointer user_data)
+{
+        /* for now, just use the same code as above... */
+        _pk_config_changed (pk_g_context, user_data);
+}
+
+
+static GtkWidget *
+build_summary_box (void)
+{
+        int n;
+        GtkWidget *summary_box;
+        GtkWidget *hbox;
+        GtkWidget *vbox;
+        GtkWidget *align;
+        GtkWidget *label;
+        GtkWidget *table;
+        GtkWidget *button_box;
+
+        summary_box = gtk_vbox_new (FALSE, 4);
+
+        /* ---- Action ---- */
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<b>Action</b>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (summary_box), label, FALSE, FALSE, 0);
+
+        hbox = gtk_hbox_new (FALSE, 0);
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, TRUE, 12);
+
+        table = gtk_table_new (3, 2, FALSE);
+        gtk_table_set_col_spacings (GTK_TABLE (table), 8);
+        gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+
+        n = 0;
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<i>Identifier:</i>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        summary_action_id_label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (summary_action_id_label), 0.0, 0.5);
+        gtk_label_set_ellipsize (GTK_LABEL (summary_action_id_label), PANGO_ELLIPSIZE_END);
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+        gtk_table_attach (GTK_TABLE (table), summary_action_id_label, 1, 2, n, n + 1, GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0);
+        n++;
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<i>Description:</i>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        summary_action_desc_label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (summary_action_desc_label), 0.0, 0.5);
+        gtk_label_set_ellipsize (GTK_LABEL (summary_action_desc_label), PANGO_ELLIPSIZE_END);
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+        gtk_table_attach (GTK_TABLE (table), summary_action_desc_label, 1, 2, n, n + 1, GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0);
+        n++;
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<i>Vendor:</i>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        summary_action_vendor_label = sexy_url_label_new ();
+        g_signal_connect (summary_action_vendor_label, "url-activated", 
+                          (GCallback) summary_action_vendor_url_activated, NULL);
+        gtk_misc_set_alignment (GTK_MISC (summary_action_vendor_label), 0.0, 0.5);
+        gtk_label_set_ellipsize (GTK_LABEL (summary_action_vendor_label), PANGO_ELLIPSIZE_END);
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+        gtk_table_attach (GTK_TABLE (table), summary_action_vendor_label, 1, 2, n, n + 1, GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0);
+        n++;
+
+        gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
+
+        summary_action_icon = gtk_image_new ();
+        gtk_misc_set_padding (GTK_MISC (summary_action_icon), 0, 0);
+        gtk_box_pack_end (GTK_BOX (hbox), summary_action_icon, FALSE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (summary_box), hbox, FALSE, TRUE, 0);
+
+        /* ---- Space ---- */
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_box_pack_start (GTK_BOX (summary_box), align, FALSE, TRUE, 9);
+
+        /* ---- Implicit Authorizations ---- */
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<b>Implicit Authorizations</b>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (summary_box), label, FALSE, FALSE, 0);
+
+        hbox = gtk_hbox_new (FALSE, 24);
+        vbox = gtk_vbox_new (FALSE, 6);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("Implicit authorizations are authorizations automatically given to users based on certain criteria such as if they are on the local console."));
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+
+        table = gtk_table_new (3, 2, FALSE);
+        gtk_table_set_col_spacings (GTK_TABLE (table), 8);
+        gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+        for (n = 0; n < 3; n++) {
+                const char *s;
+                GtkWidget **slabel;
+
+                switch (n) {
+                default:
+                case 0:
+                        s = _("<i>Anyone:</i>");
+                        slabel = &summary_label_any;
+                        break;
+                case 1:
+                        s = _("<i>Console:</i>");
+                        slabel = &summary_label_inactive;
+                        break;
+                case 2:
+                        s = _("<i>Active Console:</i>");
+                        slabel = &summary_label_active;
+                        break;
+                }
+                label = gtk_label_new (NULL);
+                gtk_label_set_markup (GTK_LABEL (label), s);
+                gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+                gtk_table_attach (GTK_TABLE (table), label, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+
+
+                *slabel = gtk_label_new (NULL);
+                gtk_misc_set_alignment (GTK_MISC (*slabel), 0.0, 0.5);
+                gtk_table_attach (GTK_TABLE (table), *slabel, 1, 2, n, n + 1, GTK_FILL, GTK_FILL, 0, 0);
+        }
+        gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
+ 
+        button_box = gtk_hbutton_box_new ();
+        gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START);
+        gtk_box_set_spacing (GTK_BOX (button_box), 6);
+
+        edit_impl_button = gtk_button_new_with_mnemonic  (_("_Edit..."));
+        gtk_container_add (GTK_CONTAINER (button_box), edit_impl_button);
+        g_signal_connect (edit_impl_button, "clicked", (GCallback) edit_impl_clicked, NULL);
+
+
+        revert_to_defaults_action = polkit_gnome_action_new_default ("RevertToDefaults", 
+                                                                     pk_modify_defaults_action,
+                                                                     _("Revert To _Defaults..."),
+                                                                     NULL);
+        g_signal_connect (revert_to_defaults_action, "activate", G_CALLBACK (revert_impl_activate), NULL);
+        revert_impl_button = polkit_gnome_action_create_button (revert_to_defaults_action);
+        gtk_container_add (GTK_CONTAINER (button_box), revert_impl_button);
+
+        gtk_box_pack_start (GTK_BOX (vbox), button_box, TRUE, TRUE, 0);
+
+
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+
+        gtk_box_pack_start (GTK_BOX (summary_box), hbox, FALSE, TRUE, 0);
+
+        /* ---- Space ---- */
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_box_pack_start (GTK_BOX (summary_box), align, FALSE, TRUE, 9);
+
+        /* ---- Explicit Authorizations ---- */
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("<b>Explicit Authorizations</b>"));
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (summary_box), label, FALSE, FALSE, 0);
+
+        GtkWidget *hbox2;
+
+        hbox = gtk_hbox_new (FALSE, 24);
+        vbox = gtk_vbox_new (FALSE, 6);
+        hbox2 = gtk_hbox_new (FALSE, 6);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), _("This list displays authorizations that are either obtained through authentication or specifically given to the entity in question. Blocked authorizations are marked with a STOP sign."));
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+
+        GtkWidget *authlist_scrolled_window;
+
+        authlist_store = gtk_list_store_new (EXPLICIT_N_COLUMNS,
+                                             GDK_TYPE_PIXBUF,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_STRING,
+                                             G_TYPE_POINTER);
+
+        authlist_treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (authlist_store));
+
+        GtkCellRenderer *renderer;
+        GtkTreeViewColumn *column;
+
+        column = gtk_tree_view_column_new ();
+        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+        renderer = gtk_cell_renderer_pixbuf_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", EXPLICIT_ICON_COLUMN, NULL);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "markup", EXPLICIT_ENTITY_NAME_COLUMN, NULL);
+        gtk_tree_view_column_set_title (column, _("Entity"));
+        gtk_tree_view_append_column (GTK_TREE_VIEW (authlist_treeview), column);
+
+        column = gtk_tree_view_column_new ();
+        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "markup", EXPLICIT_SCOPE_COLUMN, NULL);
+        gtk_tree_view_column_set_title (column, _("Scope"));
+        gtk_tree_view_append_column (GTK_TREE_VIEW (authlist_treeview), column);
+
+        column = gtk_tree_view_column_new ();
+        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "markup", EXPLICIT_OBTAINED_COLUMN, NULL);
+        gtk_tree_view_column_set_title (column, _("Obtained"));
+        gtk_tree_view_append_column (GTK_TREE_VIEW (authlist_treeview), column);
+
+        column = gtk_tree_view_column_new ();
+        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "markup", EXPLICIT_OBTAINED_HOW_COLUMN, NULL);
+        gtk_tree_view_column_set_title (column, _("How"));
+        gtk_tree_view_append_column (GTK_TREE_VIEW (authlist_treeview), column);
+
+        column = gtk_tree_view_column_new ();
+        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer, "markup", EXPLICIT_CONSTRAINTS_COLUMN, NULL);
+        gtk_tree_view_column_set_title (column, _("Constraints"));
+        gtk_tree_view_append_column (GTK_TREE_VIEW (authlist_treeview), column);
+
+
+        authlist_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (authlist_scrolled_window),
+                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (authlist_scrolled_window),
+                                             GTK_SHADOW_IN);
+        gtk_container_add (GTK_CONTAINER (authlist_scrolled_window), authlist_treeview);
+
+        authlist_treeselect = gtk_tree_view_get_selection (GTK_TREE_VIEW (authlist_treeview));
+        gtk_tree_selection_set_mode (authlist_treeselect, GTK_SELECTION_SINGLE);
+        g_signal_connect (authlist_treeselect, "changed", (GCallback) authlist_changed, NULL);
+
+        GtkWidget *button;
+
+        button_box = gtk_vbutton_box_new ();
+        gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START);
+        gtk_box_set_spacing (GTK_BOX (button_box), 6);
+
+        grant_button = gtk_button_new_with_mnemonic  (_("_Grant..."));
+        gtk_button_set_image (GTK_BUTTON (grant_button), 
+                              gtk_image_new_from_stock (GTK_STOCK_ADD,
+                                                        GTK_ICON_SIZE_SMALL_TOOLBAR));
+        g_signal_connect (grant_button, "clicked", (GCallback) grant_clicked, NULL);
+        gtk_container_add (GTK_CONTAINER (button_box), grant_button);
+
+        block_button = gtk_button_new_with_mnemonic  (_("_Block..."));
+        gtk_button_set_image (GTK_BUTTON (block_button), 
+                              gtk_image_new_from_stock (GTK_STOCK_STOP,
+                                                        GTK_ICON_SIZE_SMALL_TOOLBAR));
+        g_signal_connect (block_button, "clicked", (GCallback) block_clicked, NULL);
+        gtk_container_add (GTK_CONTAINER (button_box), block_button);
+
+
+        revoke_action = polkit_gnome_action_new ("RevokeAction");
+        g_object_set (revoke_action,
+                      "polkit-action",    pk_revoke_action,
+                      "no-visible",       TRUE,
+                      "no-sensitive",     FALSE,
+                      "no-short-label",   NULL,
+                      "no-label",         _("_Revoke"),
+                      "no-tooltip",       NULL,
+                      "no-icon-name",     GTK_STOCK_CLEAR,
+                      
+                      "auth-visible",     TRUE,
+                      "auth-sensitive",   TRUE,
+                      "auth-short-label", NULL,
+                      "auth-label",       _("_Revoke..."),
+                      "auth-tooltip",     NULL,
+                      "auth-icon-name",   GTK_STOCK_CLEAR,
+                      
+                      "yes-visible",      TRUE,
+                      "yes-sensitive",    TRUE,
+                      "yes-short-label",  NULL,
+                      "yes-label",        _("_Revoke"),
+                      "yes-tooltip",      NULL,
+                      "yes-icon-name",    GTK_STOCK_CLEAR,
+                      NULL);
+        
+        g_signal_connect (revoke_action, "activate", G_CALLBACK (revoke_action_activate), NULL);
+        button = polkit_gnome_action_create_button (revoke_action);
+        gtk_container_add (GTK_CONTAINER (button_box), button);
+
+
+        GtkWidget *read_all_auths;
+
+        read_action = polkit_gnome_toggle_action_new_default ("read", pk_read_action, 
+                                                              _("_Show authorizations from all users..."),
+                                                              _("_Show authorizations from all users"));
+        read_all_auths = gtk_check_button_new ();
+        gtk_action_connect_proxy (GTK_ACTION (read_action), read_all_auths);
+
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_box_pack_start (GTK_BOX (hbox2), authlist_scrolled_window, TRUE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (hbox2), button_box, FALSE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (vbox), read_all_auths, FALSE, FALSE, 0);
+
+        gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, TRUE, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (summary_box), hbox, TRUE, TRUE, 0);
+
+        return summary_box;
+}
+
+typedef struct SingleInstance SingleInstance;
+typedef struct SingleInstanceClass SingleInstanceClass;
+
+GType single_instance_get_type (void);
+
+struct SingleInstance
+{
+  GObject parent;
+};
+
+struct SingleInstanceClass
+{
+  GObjectClass parent;
+};
+
+#define TYPE_SINGLE_INSTANCE              (single_instance_get_type ())
+#define SINGLE_INSTANCE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_SINGLE_INSTANCE, SingleInstance))
+#define SINGLE_INSTANCE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SINGLE_INSTANCE, SingleInstanceClass))
+#define IS_SINGLE_INSTANCE_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TYPE_SINGLE_INSTANCE))
+#define IS_SINGLE_INSTANCE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SINGLE_INSTANCE))
+#define SINGLE_INSTANCE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SINGLE_INSTANCE, SingleInstanceClass))
+
+G_DEFINE_TYPE(SingleInstance, single_instance, G_TYPE_OBJECT)
+
+gboolean single_instance_show_action (SingleInstance *obj, const char *action_id, GError **error);
+
+#include "single-instance-glue.h"
+
+static void
+single_instance_init (SingleInstance *obj)
+{
+}
+
+static void
+single_instance_class_init (SingleInstanceClass *klass)
+{
+}
+
+gboolean 
+single_instance_show_action (SingleInstance *obj, const char *action_id, GError **error)
+{
+        GtkTreeIter iter;
+
+        if (find_iter_by_action_id (action_id, &iter)) {
+                GtkTreePath *path;
+
+                path = gtk_tree_model_get_path (GTK_TREE_MODEL (action_store), &iter);
+                if (path != NULL) {
+                        gtk_tree_view_set_cursor (GTK_TREE_VIEW (action_treeview),
+                                                  path,
+                                                  NULL,
+                                                  FALSE);
+                        gtk_tree_path_free (path);
+
+                        /* bring top level window to front */
+                        if (toplevel_window != NULL)
+                                gtk_window_present (GTK_WINDOW (toplevel_window));
+                }                                
+        }
+
+        return TRUE;
+}
+
+
+static gboolean
+setup_single_instance (void)
+{
+        gboolean ret;
+        GObject *single_instance;
+        GError *error;
+        DBusGConnection *bus;
+        DBusGProxy *bus_proxy;
+        guint result;
+        const char bus_name[] = "org.gnome.PolicyKit.AuthorizationManager";
+
+        ret = FALSE;
+
+        error = NULL;
+        bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+        if (bus == NULL) {
+                g_warning ("Couldn't connect to session bus: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+	bus_proxy = dbus_g_proxy_new_for_name (bus,
+                                               DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS);
+        if (bus_proxy == NULL) {
+                g_warning ("Could not construct bus_proxy object; bailing out");
+                goto out;
+        }
+
+	if (!dbus_g_proxy_call (bus_proxy,
+                                "RequestName",
+                                &error,
+                                G_TYPE_STRING, bus_name,
+                                G_TYPE_UINT, 0,
+                                G_TYPE_INVALID,
+                                G_TYPE_UINT, &result,
+                                G_TYPE_INVALID)) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", bus_name, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", bus_name);
+                }
+                goto out;
+	}
+
+ 	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", bus_name, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", bus_name);
+                }
+                goto out;
+        }
+
+        dbus_g_object_type_install_info (TYPE_SINGLE_INSTANCE, &dbus_glib_single_instance_object_info);
+
+        single_instance = g_object_new (TYPE_SINGLE_INSTANCE, NULL);
+
+        dbus_g_connection_register_g_object (bus, "/", G_OBJECT (single_instance));
+
+        ret = TRUE;
+
+out:
+        return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+        GtkWidget *vbox;
+        GtkWidget *treeview_scrolled_window;
+        GtkWidget *button;
+        GtkWidget *hbutton_box;
+        GMainLoop*loop;
+        GtkWidget *pane;
+
+        gtk_init (&argc, &argv);
+
+        if (!setup_single_instance ()) {
+                g_debug ("Already running");
+                return 1;
+        }
+
+        boxed_pfe_type = g_boxed_type_register_static ("GBoxedPolKitPolicyFileEntry", 
+                                                       (GBoxedCopyFunc) polkit_policy_file_entry_ref,
+                                                       (GBoxedFreeFunc) polkit_policy_file_entry_unref);
+
+        loop = g_main_loop_new (NULL, FALSE);
+
+        pkgc = polkit_gnome_context_get (NULL);
+        polkit_context_set_load_descriptions (pkgc->pk_context);
+
+        pk_revoke_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_revoke_action, "org.freedesktop.policykit.revoke");
+
+        pk_read_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_read_action, "org.freedesktop.policykit.read");
+
+        pk_grant_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_grant_action, "org.freedesktop.policykit.grant");
+
+        pk_modify_defaults_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_modify_defaults_action, "org.freedesktop.policykit.modify-defaults");
+
+        action_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), 
+                                                  "application-x-executable", 
+                                                  24, 
+                                                  0, 
+                                                  NULL);
+
+        person_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), 
+                                                  "stock_person", 
+                                                  24, 
+                                                  0, 
+                                                  NULL);
+
+        namespace_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), 
+                                                     "gnome-mime-application-x-archive", 
+                                                     24, 
+                                                     0, 
+                                                     NULL);
+
+	stop_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                                GTK_STOCK_STOP,
+                                                24,
+                                                0,
+                                                NULL);
+
+
+        toplevel_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+        vbox = gtk_vbox_new (FALSE, 6);
+        gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+        gtk_container_add (GTK_CONTAINER (toplevel_window), vbox);
+
+        summary_box = build_summary_box ();
+        gtk_container_set_border_width (GTK_CONTAINER (summary_box), 8);
+
+        action_treeview = action_list_new ();
+        treeview_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (treeview_scrolled_window),
+                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (treeview_scrolled_window),
+                                             GTK_SHADOW_IN);
+        gtk_container_add (GTK_CONTAINER (treeview_scrolled_window), action_treeview);
+
+        pane = gtk_hpaned_new ();
+        gtk_paned_add1 (GTK_PANED (pane), treeview_scrolled_window);
+
+        notebook = gtk_notebook_new ();
+
+        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), summary_box, NULL);
+        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), gtk_label_new (_("Select an action")), NULL);
+        gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
+        gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
+
+        gtk_paned_add2 (GTK_PANED (pane), notebook);
+        gtk_paned_set_position (GTK_PANED (pane), 300);
+        gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
+
+        //gtk_box_pack_start (GTK_BOX (vbox), treeview_scrolled_window, TRUE, TRUE, 0);
+        //gtk_box_pack_start (GTK_BOX (vbox), summary_box, FALSE, TRUE, 0);
+
+        /* button box */
+
+        hbutton_box = gtk_hbutton_box_new ();
+        gtk_button_box_set_layout (GTK_BUTTON_BOX (hbutton_box), GTK_BUTTONBOX_END);
+        gtk_box_set_spacing (GTK_BOX (hbutton_box), 6);
+
+        button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+        g_signal_connect (button, "clicked", (GCallback) exit, NULL);
+        gtk_container_add (GTK_CONTAINER (hbutton_box), button);
+
+
+        gtk_box_pack_start (GTK_BOX (vbox), hbutton_box, FALSE, TRUE, 0);
+
+        gtk_window_set_icon_name (GTK_WINDOW (toplevel_window), "gtk-dialog-authentication");
+        gtk_window_set_default_size (GTK_WINDOW (toplevel_window), 800, 700);
+        gtk_window_set_title (GTK_WINDOW (toplevel_window), _("Authorizations"));
+        g_signal_connect (toplevel_window, "delete-event", (GCallback) exit, NULL);
+        gtk_widget_show_all (toplevel_window);
+
+        g_signal_connect (pkgc,
+                          "config-changed",
+                          G_CALLBACK (_pk_config_changed),
+                          NULL);
+                
+        g_signal_connect (pkgc,
+                          "console-kit-db-changed",
+                          G_CALLBACK (_pk_console_kit_db_changed),
+                          NULL);
+
+        update_summary ();
+
+        g_main_loop_run (loop);
+        return 0;
+}

Added: trunk/tools/single-instance.xml
==============================================================================
--- (empty file)
+++ trunk/tools/single-instance.xml	Fri Apr  4 07:02:43 2008
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+  <interface name="org.gnome.PolicyKit.AuthorizationManager.SingleInstance">
+    <method name="ShowAction">
+      <arg name="action_id" type="s"/>
+    </method>
+  </interface>
+</node>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]