policykit-gnome r2 - in trunk: . data doc examples po polkit-gnome src tools
- From: davidz svn gnome org
- To: svn-commits-list gnome org
- Subject: policykit-gnome r2 - in trunk: . data doc examples po polkit-gnome src tools
- Date: Fri, 4 Apr 2008 07:02:45 +0100 (BST)
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]