pax_global_header00006660000000000000000000000064134144142670014520gustar00rootroot0000000000000052 comment=ed2d81fe558b657b52940dd52316bcc1a32d0cff geoclue-2.5.2/000077500000000000000000000000001341441426700131515ustar00rootroot00000000000000geoclue-2.5.2/.gitlab-ci.yml000066400000000000000000000024221341441426700156050ustar00rootroot00000000000000before_script: - sed -i '/^#\sdeb-src /s/^#//' '/etc/apt/sources.list' - apt-get update && apt-get build-dep --yes geoclue-2.0 - apt-get install --yes git gobject-introspection libmm-glib-dev wget libnotify-dev xsltproc gtk-doc-tools python3-pip ninja-build gettext modemmanager-dev - pip3 install meson # Ubuntu 14.04 is not supported, see README for details # # FIXME: Also disable gtk-doc on Ubuntu 16.04 cause it fails install. Would be nice to get it fixed. ubuntu-16.04: image: ubuntu:xenial artifacts: when: always name: "xenial-${CI_COMMIT_REF_NAME}" paths: - "${CI_PROJECT_DIR}/build" script: meson -Dgtk-doc=false build && ninja -C build && ninja -C build test && ninja -C build install ubuntu-17.10: image: ubuntu:artful artifacts: when: always name: "artful-${CI_COMMIT_REF_NAME}" paths: - "${CI_PROJECT_DIR}/build" script: meson build && ninja -C build && ninja -C build test && ninja -C build install ubuntu-18.04: image: ubuntu:bionic artifacts: when: always name: "bionic-${CI_COMMIT_REF_NAME}" paths: - "${CI_PROJECT_DIR}/build" script: meson build && ninja -C build && ninja -C build test && ninja -C build install geoclue-2.5.2/COPYING000066400000000000000000001253311341441426700142110ustar00rootroot00000000000000The source code of Geoclue is licensed to you under the GNU General Public License version 2, or (at your option) any later version. ======================================================================== GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser 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. Copyright This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 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 Lesser General Public License instead of this License. ================================================================================ GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [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. Copyright 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! geoclue-2.5.2/COPYING.LIB000066400000000000000000000636211341441426700146210ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] 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 Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these 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 other code 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. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. 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, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser 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 combine 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) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) 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. d) 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. e) 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 materials to be 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 with 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 Lesser 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. Copyright 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! geoclue-2.5.2/NEWS000066400000000000000000000511561341441426700136600ustar00rootroot000000000000002.5.2 ===== - Scan for WiFi networks, greatly improving accuracy of WiFi source. - Allow multiple clients on the same D-Bus connection and add API for it. This is mainly targetted for Flatpak location portal. - Add API for apps to explicitly delete their client objects. Long running apps, like gnome-settings-daemon and Flatpak location portal, should use that to ensure Geoclue knows when these apps are not actually using it and hence it doesn't need to keep running needlessly. - Restore accidently removed, build of modem sources. - Update location on connectivity actually changing. - Try not spamming Mozilla Location Service. - Fix unexpected exit when non-active clients are connected. - Fix a check for system apps. - Use absolute paths for sysconfdir. - Fix links in docs. - More debug log. - A bunch of internal and/or non-functional fixes & improvements. Dependency-related changes: - Require glib >= 2.44. Contributors: Bastien Nocera Jan Alexander Steffens (heftig) Laurent Bigonville Valentin Blot Will Thompson Zeeshan Ali 2.5.1 ===== - Fix libgeoclue ABI break in 2.5.0. - Use absolute paths for libexecdir. 2.5.0 ===== Changes since 2.4.10 that were not included in subsequent 2.4.x releases as well: - Drop authorization for system (non-flatpak) apps. - Switch from autotools to meson build system. - Use WiFi-based geolocation for city level accuracy. - Provide Vala API. - Don't enable all warnings from C compiler by default. - No need to mark translatable strings in desktop files. Contributors: Bastien Nocera Corentin Noël Emmanuele Bassi Karl-Philipp Richter Laurent Bigonville Nirbheek Chauhan Ting-Wei Lan Valentin Blot worldofpeace Zeeshan Ali 2.4.10 ====== - Fix issues introduced by last release 2.4.9: - a crash on startup. - Revert the new desktop ID detection code as that turned out to not work for non-root user that geoclue is supposed to be run as. - Use systemd's service file to lockdown the geoclue daemon to stop eventual security problems. Contributors: Bastien Nocera Zeeshan Ali 2.4.9 ===== - Modem GPS refresh rate is now based on the location refresh rate of apps. - Refuse location access if no app-auth agent is registered. This fixes a security hole where an app requests location access before the agent gets to register itself and we end up giving out locaiton access even though user has disabled it. - Port desktop ID detection to Flatpak >= 0.6.10. - The default timeout on the service binary is now the same as the service itself: 5 seconds. - Demo applications: - where-am-i now allows setting location refresh-rate. - Only install demo agent's desktop file if it's enabled. - Build and install demo agent unless disabled explicitly. - Autostart the demo agent by default on non-GNOME platforms, since an agent is required now and no one other than GNOME yet provides one (sigh). Dependency-related changes: Bastien Nocera Mathieu Bridon Zeeshan Ali 2.4.8 ===== - Fix threshold for detecting too old location update. - Explain in the configuration what the applications white-list is meant for. - Allow instant location updates from modem-based GPS. - Fix a deadlock case in the helper library. Dependency-related changes: Require mm-glib >= 1.6 Valentin Blot Zeeshan Ali (Khattak) 2.4.7 ===== - Fix a potential crash. - More verbose warning on invalid accuracy from NMEA source. 2.4.6 ===== - Add to white-list - gnome-color-panel for "Night Light" functionality. - gnome-shell for new weather view in the calendar. - Other minor fixes. Bastien Nocera Florian Müllner Rob Norris 2.4.5 ===== - Fix a potential crash. 2.4.4 ===== - Expose location timestamp over D-Bus. - Add a TimeThreshold property that allows clients to limit location updates by time. - Annotate default value of DistanceThreshold property. - Check for full internet availability before declaring ourselves online. - Fix autogen.sh against builddir ≠ srcdir. - Fix a bunch of memory leaks. - Fix a bunch of build issues. - Other minor fixes. Colin Walters Emilio Pozuelo Monfort Justin Kim Philip Withnall Ting-Wei Lan Zeeshan Ali (Khattak) 2.4.3 ===== Fix a crash in the helper library. 2.4.2 ===== - Reliable desktop ID detection for xdg-app. This together with latest gnome-shell and gnome-control-center, allows for per-application geolocation access controls. - Don't require xdg-app applications to pass a valid desktop ID since Geoclue can automatically detect it. - Don't allow xdg-app application to become user-authorization agents. - Correct introspection namespace version for libgeoclue. - Option to disable the backend build. - Demo: Provide reason to access location data. - Demo agent: - Critical log message on failing to show notification. - If app provides a reason string in it's desktop file, show that to the user. Cosimo Cecchi Zeeshan Ali (Khattak) 2.4.1 ===== - Add some missing NULL checks to avoid some crashes. - More reliable method to connect to Avahi from network NMEA source. - Fix warnings on system log caused by geoclue trying to access D-Bus properties it does not need. Ankit Zeeshan Ali (Khattak) 2.4.0 ===== - Add a convenience library to make interacting with Geoclue very easy. - Put each D-Bus interface description in it's own file. Unified interface file still provided for backwards compatibility. Simon McVittie Zeeshan Ali (Khattak) 2.3.0 ===== - Add a network NMEA source, which together with this application: https://wiki.gnome.org/Apps/GeoclueShare allows you to use the GPS of your Android device on your geoclue-enabled machine. - Allow root to own the name on the bus, i-e run the service. - Make use of compass device if available, through iio-proxy. - Fix a hang on client starting twice. - More helpful error on agent rejection. - Improved documentation. - Do not ship generated D-Bus service files in the tarball. - Only allow the geoclue user and root to call methods on agents. - Fix ignoring of valid location updates due to comparison of distances in different units. - Correctly handle two consecutive location updates with same timestamp on them. - Correctly handle late location update. - Build system fixes: - Fix detection of gdbus-codegen tool. - Workaround an intltool issue. All contributors to this release: Ankit Bastien Nocera Fabrice Bellet Laurent Bigonville Philip Withnall Zeeshan Ali (Khattak) 2.2.0 ===== - Report 'Speed' and 'Heading' on location updates. - Try to provide the most accurate location first. - Avoid a crash by ensuring requested max accuracy is within bounds. - Fix GPS coordinates parsing. - Fix GeoIP on machines without WiFi hardware. - Gracefully handle inexistent agent. - Stop sources whose accuracy level becomes higher, rather than lower, than the requested level. - Keep old location object alive on D-Bus for a bit longer to ensure applications are not accessing it still after it is destroyed. - Don't enable the modem. Seems at least GNOME takes care of modem enabling for us and besides this shouldn't be done by geoclue anyway (see bug#85040). - Wait for modem to be enabled before checking availability of location capabilities and using them. This is particularly important for pin-enabled modems. - Ignore redundant GPS location updates. - Fix some potential crashes. - Some improvements to output of where-am-i demo application. Dependency-related changes: Explicitly require libsoup >= 2.42 All contributors to this release: Ankit Bastien Nocera Fabrice Bellet Pawel Golinski Zeeshan Ali (Khattak) 2.1.10 ====== - Disallow application if disabled explicitly in the configuration. - Make it easy to add alternative modem source(s), e.g ofono-based. - Map: - country-level accuracy to city-level since no source provides country-level accuracy. - neighborhood-level accuracy to city-level in WiFi source (only) so applications requesting neighborhood-level accuracy still get a location even if there is no modem available. - Fixes to WiFi source. - For easier debugging, add: - more debug prints. - commandline options to where-am-i demo application to specify timeout and requested accuracy level. - Fix a potential build failure. 2.1.9 ===== - Move from NetworkManager to direct use of wpa_supplicant to retreive WiFI data, for greater portability. - Port from opencellid.org to Mozilla Location Service for 3G-geolocation. - Network data submission - Explicit option in config to enable submission. - Commandline options to enable network data submission and set nickname. - Submit 3G data. - Submit under 'geoclue' nick by default. - Fix a few crashes. - Drop now redundant workaround for pure geoip queries. - Ability to mark an app as system component in the config so that - Agent can't decide its accuracy level nor agent is asked to authorize it. This mean automatic timezone in GNOME will continue working even if you disable geolocation. - app is not taken into account for 'InUse' property. That means you will no longer have to see location crosshair in gnome-shell's topbar forever just because you have automatic timezone enabled. - Exit demo app if geoclue deactivates it. - Improved debug log. - Many other internal changes and minor improvements. Dependency-related changes: - Drop libnm-glib dependency - Drop libxml2 dependency 2.1.8 ===== - Switch to Mozilla Location Service for geoip as well. - Allow specifying nickname to submit network data with. - Report actual available accuracy level and keep it up2date. - Add 'Active' property to indicate client state. - Expose altitude info (if known). - Timeout on inactivity, rather than no clients. - Automatically: - stop the client if max accuracy level is set to 0. - start the client if max accuracy level is set to non-0 and it was automatically stopped. - Don't disable modem after using it. Disabling the modem, disables it for everyone so if there was an active connection going on through the modem, geoclue will cause it to disconnect. While we need to have some centralized means to enable/disable modem and ideally geoclue shouldn't do any enabling/disabling of modems at all, for now lets just only enable the modem. - Fix issue of missed location updates. - Whitelist correct ID for gnome-settings-daemon in default config. - Replace '--disable-wifi-source' configure option with '--disable-network-manager'. i-e now you disable usage of NetworkManger explicitly rather than wifi source, which is now always built and enabled. - Drop now redundant geoip server. - Don't distribute .desktop.in files for demos. - Plug some leaks. - More debug log. - Other minor fixes. All contributors to this release: Kalev Lember Zeeshan Ali (Khattak) 2.1.7 ===== - 'InUse' property now only affected by active clients. This fixes the issue of gnome-shell incorrectly showing 'geolocation in use' icon. - Move DBus interface files to their canonical location: /usr/share/dbus-1/interfaces/. - Drop redundant check for the C++ compiler in configure script. - Demo agent now prints 'geolocation in use' info. All contributors to this release: Kalev Lember Zeeshan Ali (Khattak) 2.1.6 ===== - Correct binary path is demo's desktop file. - Move demo apps from /usr/share to /usr/libexec. 2.1.5 ===== - Add a NULL check to fix a crasher. - Setup D-Bus policy to be able to access NetworManager API. - Expected agent object path now static. This breaks agent interface but it was needed to fix the D-Bus policy. - Fix issue of us giving every connection access to every property on the system bus. All contributors to this release: Zeeshan Ali (Khattak) 2.1.4 ===== - Don't depend on unreleased libnm-glib. All contributors to this release: Zeeshan Ali (Khattak) 2.1.3 ===== - Agents can now dictate maximum accuracy level allowed for all clients through a D-Bus property. The next version of gnome-shell will make use of that and provide an option to enable/disable geolocation in topbar menu. - Add D-Bus property to specify available accuracy level. For now we just hardcode it to report that we can provide exact accuracy. - Give agents time to register themselves on startup before processing client requests. - Move configuration file under geoclue subdir so that in future we can easily add more configuration files if needed. - Fixes to build. - Some internal clean-ups. All contributors to this release: Colin Walters Marvin Schmidt Zeeshan Ali (Khattak) 2.1.2 ===== - Fix some crashing bugs. - Ignore WiFis with '_nomap' suffix. - Configure options for disabling WiFi, 3G and GPS modem sources. - Avoid spaming the network resources for ignorable changes to network setup. - Add some required files to distribution that we forgot in last release. All contributors to this release: Kalev Lember Ryan Lortie Zeeshan Ali (Khattak) 2.1.1 ===== - 3GPP-based geolocation source. - Uses ModemManager to get cell tower info from 3GPP modem and uses opencellid.org's public API to translate that into a location. - GPS modem-based geolocation source: If your 3GPP modem has a GPS, geoclue can now make use of it. - WiFi-based geolocation source - Uses Mozilla Location Service to find location based on nearby WiFi networks. - Refresh location on changes in WiFi networks. - Option in configuration file to make geoclue use Google Maps Geolocation API rather than Mozilla Location Service. - Option in configuration file to enable submission of wifi data to Mozilla Location Service. If this option is enabled, the data is submitted each time geoclue gets a GPS lock. That means, its not completely autonomous and data is only submitted if an application, e.g gnome-maps requests current location with exact accuracy. - API for clients to specify what level of geolocation accuracy they need, e.g city-level, street-level or exact etc. - API to check if geolocation service is in use. Next version of gnome-shell will make use of that to show an icon in the panel to indicate to user that their location is being accessed. - Application authorization agent - Make agent completely optional. We will revert this once we have a reliable mechanism to identify applications. - Identify agent and client applications by their desktop IDs rather than paths of their binaries. - Ability for agents to dictate the accuracy level allowed for clients. - Maintain a whitelist of clients in configuration that do not need agent authorization. - Avoid redundant queries to web services. - Install demo applications and provide a desktop file for them. - Many more internal fixes and clean-ups. Dependency-related changes: - Require libnm-glib >= 0.9.9.0 (new dependency) - Require libmm-glib >= 1.0 (new dependency) - Require libxml-2.0 (new dependency) Note to package maintainers: This version drops the requirement for geoclue binary to be given 'ptrace' capability that was introduced in last release, 2.1.0. All contributors to this release: Zeeshan Ali (Khattak) 2.1.0 ===== - Application authentication agents support: - API for agents to register themselves. - API that agents need to implement. - configure option to enable requirement of authorization from agent. Until there is at least one agent out there, this requirement is disabled by default. - A demo agent. - Option in ${sysconfdir}/geoclue.conf containing whitelist of all our agents. - Don't use proxy. Seems proxy settings are per-user and system users (which geoclue is supposed to run as) do not have access to them. - Add support for bus-activation via systemd service unit. - Add mandatory 'DesktopId' property to Client interface. - Use HTTPS to connect to geoip.fedoraproject.org. The actual resource is behind HTTPS so using HTTP leads to redirections and thefore redundant TCP packets. - Fixes to build system. Note to package maintainers: For the agent support to work, geoclue binary need 'ptrace' capability. In near future we will try to get this through systemd so systemd-based distributions likely not need to bother about it. Having said that, for this release you can simply keep the agent requirement disabled. All contributors to this release: Colin Guthrie Colin Walters Kalev Lember Philip Withnall Stefan Bernhardsgrütter Zeeshan Ali (Khattak) 2.0.0 ===== - Generate docs for D-Bus interface. Online version: http://www.freedesktop.org/software/geoclue/docs/ - Fix build against Automake 1.13. - Two minor fixes/cleanups. All contributors to this release: Zeeshan Ali (Khattak) 1.99.4 ====== - Correct check for whether db needs update in geoip-update. - Fix geoip-update by direct usage of libsoup for HTTP GET. - Don't inhibit compiler warnings in build. - Fix various potential crashers. - Take 'DistanceThreshold' property into account. - Watch for and signal out location changes. - Add configure option to specify service user. - Add documentation comments to D-Bus interface XML. - Fix various compiler warnings. - Switch to Fedora's geoip server until we've our server setup. - Minor fixes to pkgconfig file. - Setup a glib log domain. - Some optimizations. - More debug logging. Dependency-related changes: - Require libsoup-2.4 All contributors to this release: Bastien Nocera Dominique Leuenberger Kalev Lember Stefan Sauer Zeeshan Ali (Khattak) 1.99.3 ====== - All D-Bus prop names capitalized as per general conventions. - Expose D-Bus specification XML file in pkg-config file. - Fix some potential crashes in error handling code. - Remove unused build-time yelp dependency. - Correct the libsoup dependency in pkg-config (although it doesn't affect any applications at the moment). - Fix some compiler warnings. All contributors to this release: Evgeny Bobkin Guillaume Desmottes Kalev Lember Zeeshan Ali (Khattak) 1.99.2 ====== - Drop client-side library. - Add COPYING file. - Install geoip-lookup with make install. This makes life easier for binary distributions that can then ship geoip-lookup in a package. - Distribute server documentation. - Distribute & install interface XML file. - Add/update forgotten copyright headers. All contributors to this release: Kalev Lember Zeeshan Ali (Khattak) 1.99.1 ====== - Move to system D-Bus. - Import geoip code from geocode-glib. - Add option to automatically exit on inactivity. By default it: - Runs indefinitely when launched manually. - Exits after 5 seconds of inactivity when (auto)launched by D-Bus. - Relicense from LGPLv2+ to GPLv2+. - Some build/installation related fixes. - Correctly version pkg-config file. - Fix crash on error. - Add --version cmdline option. Dependency-related changes: - Remove redundant GOA dep from pkg-config. - Drop dependency on geocode-glib. - New dependencies: - json-glib-1.0 >= 0.14 - libsoup-2.4 - geoip >= 1.5.1 (Only needed by geoip server) All contributors to this release: Bastien Nocera Colin Walters Zeeshan Ali (Khattak) 1.99.0 ====== - Bump the version number 0.0.1 ===== - First release (of geoclue2) geoclue-2.5.2/README000066400000000000000000000007431341441426700140350ustar00rootroot00000000000000GeoClue: The Geoinformation Service =================================== GeoClue is a D-Bus geoinformation service. The goal of the Geoclue project is to make creating location-aware applications as simple as possible. Geoclue is Free Software, licensed under GNU GPLv2+. # Troubleshooting and known limitations * GeoClue requires Glib >= 2.44.0 which should make it hard to build to Ubuntu 14.04. It's currently not supported, but all maintained Ubuntu versions >= 16.04 are. geoclue-2.5.2/data/000077500000000000000000000000001341441426700140625ustar00rootroot00000000000000geoclue-2.5.2/data/geoclue.conf.in000066400000000000000000000066441341441426700167730ustar00rootroot00000000000000# Configuration file for Geoclue # # NOTE: All configurations settings below are mandatory and the defaults are # what you see before you edit them. If you want to keep the default # values around, copy and comment out the appropriate line(s) before # changing them. # Agent configuration options [agent] # Whitelist of desktop IDs (without .desktop part) of all agents we recognise, # separated by a ';'. whitelist=@demo_agent@gnome-shell;io.elementary.desktop.agent-geoclue2 # Network NMEA source configuration options [network-nmea] # Fetch location from NMEA sources on local network? enable=true # 3G source configuration options [3g] # Enable 3G source enable=true # CDMA source configuration options [cdma] # Enable CDMA source enable=true # Modem GPS source configuration options [modem-gps] # Enable Modem-GPS source enable=true # WiFi source configuration options [wifi] # Enable WiFi source enable=true # URL to the wifi geolocation service. The key can currenty be anything, just # needs to be present but that is likely going to change in future. url=https://location.services.mozilla.com/v1/geolocate?key=geoclue # To use the Google geolocation service instead of mozilla's, simply uncomment # this url while changing API_KEY to your Google API key and comment out or # remove the url above. # # WARNING: Please make sure that you are complying with the Google's ToS and # policies if you uncomment this: # # https://developers.google.com/maps/documentation/geolocation/policies # #url=https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_KEY # Submit data to Mozilla Location Service # If set to true, geoclue will automatically submit network data to Mozilla # each time it gets a GPS lock. # submit-data=false # URL to submission API of Mozilla Location Service submission-url=https://location.services.mozilla.com/v1/submit?key=geoclue # A nickname to submit network data with. This is currently used for leaderboard: # https://location.services.mozilla.com/leaders # A nickname must be 2-32 characters long. submission-nick=geoclue # Application configuration options # # NOTE: Having an entry here for an application with allowed=true means that # geoclue will not ask agent to authorize the application. This is to # ensure that system components and applications with built-in # authorization mechanism (e.g web browsers) do not have to be bound to # agents. # # If your application is denied access to location information and your # operating system doesn't provide any mechanism to change that, it is # likely a bug in your operation system (or geoclue). The solution is to # report the issue with all details, rather than adding your application # to this list. # # Format: # # # Desktop ID of application without .desktop part # [random-app] # # # Allowed access to location information? # allowed=true|false # # # Is application a system component? # system=true|false # # # List of UIDs of all users for which this application is allowed location # # info access, separate by ';'. Keep it empty for allowing it for all users. # users= [gnome-datetime-panel] allowed=true system=true users= [gnome-color-panel] allowed=true system=true users= [org.gnome.Shell] allowed=true system=true users= [io.elementary.desktop.agent-geoclue2] allowed=true system=true users= [epiphany] allowed=true system=false users= [firefox] allowed=true system=false users= geoclue-2.5.2/data/geoclue.service.in000066400000000000000000000007341341441426700175000ustar00rootroot00000000000000[Unit] Description=Location Lookup Service [Service] Type=dbus BusName=org.freedesktop.GeoClue2 User=@dbus_srv_user@ ExecStart=@libexecdir@/geoclue # Filesystem lockdown ProtectSystem=strict ProtectKernelTunables=true ProtectControlGroups=true ProtectHome=true PrivateTmp=true # Network PrivateNetwork=false # Execute Mappings MemoryDenyWriteExecute=true # Modules ProtectKernelModules=true # Real-time RestrictRealtime=true # Privilege escalation NoNewPrivileges=true geoclue-2.5.2/data/meson.build000066400000000000000000000037041341441426700162300ustar00rootroot00000000000000if get_option('enable-backend') conf = configuration_data() if get_option('demo-agent') conf.set('demo_agent', 'geoclue-demo-agent;') else conf.set('demo_agent', '') endif conf_dir = join_paths(sysconfdir, 'geoclue') configure_file(output: 'geoclue.conf', input: 'geoclue.conf.in', configuration: conf, install_dir: conf_dir) conf = configuration_data() conf.set('libexecdir', libexecdir) conf.set('dbus_srv_user', get_option('dbus-srv-user')) service_dir = join_paths(datadir, 'dbus-1', 'system-services') configure_file(output: 'org.freedesktop.GeoClue2.service', input: 'org.freedesktop.GeoClue2.service.in', configuration: conf, install_dir: service_dir) # DBus Service policy file dbus_service_dir = get_option('dbus-sys-dir') if dbus_service_dir == '' dbus_service_dir = join_paths(sysconfdir, 'dbus-1', 'system.d') endif configure_file(output: 'org.freedesktop.GeoClue2.conf', input: 'org.freedesktop.GeoClue2.conf.in', configuration: conf, install_dir: dbus_service_dir) configure_file(output: 'org.freedesktop.GeoClue2.Agent.conf', input: 'org.freedesktop.GeoClue2.Agent.conf.in', configuration: conf, install_dir: dbus_service_dir) systemd_unit_dir = get_option('systemd-system-unit-dir') if systemd_unit_dir == '' dep = dependency('systemd', required: false) if dep.found() systemd_unit_dir = dep.get_pkgconfig_variable('systemdsystemunitdir') endif endif if systemd_unit_dir != '' configure_file(output: 'geoclue.service', input: 'geoclue.service.in', configuration: conf, install_dir: systemd_unit_dir) endif endif geoclue-2.5.2/data/org.freedesktop.GeoClue2.Agent.conf.in000066400000000000000000000013171341441426700231020ustar00rootroot00000000000000 geoclue-2.5.2/data/org.freedesktop.GeoClue2.conf.in000066400000000000000000000026331341441426700220470ustar00rootroot00000000000000 geoclue-2.5.2/data/org.freedesktop.GeoClue2.service.in000066400000000000000000000001741341441426700225600ustar00rootroot00000000000000[D-BUS Service] Name=org.freedesktop.GeoClue2 Exec=@libexecdir@/geoclue User=@dbus_srv_user@ SystemdService=geoclue.service geoclue-2.5.2/demo/000077500000000000000000000000001341441426700140755ustar00rootroot00000000000000geoclue-2.5.2/demo/agent.c000066400000000000000000000060071341441426700153420ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* agent.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include #include #include #include #include #include "gclue-service-agent.h" /* Commandline options */ static gboolean version; static GOptionEntry entries[] = { { "version", 0, 0, G_OPTION_ARG_NONE, &version, N_("Display version number"), NULL }, { NULL } }; GClueServiceAgent *agent = NULL; static void on_get_bus_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GDBusConnection *connection; connection = g_bus_get_finish (res, &error); if (connection == NULL) { g_critical ("Failed to get connection to system bus: %s", error->message); g_error_free (error); exit (-2); } agent = gclue_service_agent_new (connection); } #define ABS_PATH ABS_SRCDIR "/agent" int main (int argc, char **argv) { GMainLoop *main_loop; GError *error = NULL; GOptionContext *context; setlocale (LC_ALL, ""); textdomain (GETTEXT_PACKAGE); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); g_set_application_name ("GeoClue Agent"); notify_init (_("GeoClue")); context = g_option_context_new ("- Geoclue Agent service"); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_critical ("option parsing failed: %s\n", error->message); exit (-1); } if (version) { g_print ("%s\n", PACKAGE_VERSION); exit (0); } g_bus_get (G_BUS_TYPE_SYSTEM, NULL, on_get_bus_ready, NULL); main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); if (agent != NULL) g_object_unref (agent); g_main_loop_unref (main_loop); return 0; } geoclue-2.5.2/demo/gclue-service-agent.c000066400000000000000000000340541341441426700201000ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-agent.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include #include #include #include #include "gclue-service-agent.h" #define AGENT_PATH "/org/freedesktop/GeoClue2/Agent" #define SERVICE "org.freedesktop.GeoClue2" #define MANAGER_PATH "/org/freedesktop/GeoClue2/Manager" #define MANAGER_INTERFACE "org.freedesktop.GeoClue2.Manager" static void gclue_service_agent_agent_iface_init (GClueAgentIface *iface); static void gclue_service_agent_constructed (GObject *object); struct _GClueServiceAgentPrivate { GDBusConnection *connection; GDBusProxy *manager_proxy; }; G_DEFINE_TYPE_WITH_CODE (GClueServiceAgent, gclue_service_agent, GCLUE_TYPE_AGENT_SKELETON, G_IMPLEMENT_INTERFACE (GCLUE_TYPE_AGENT, gclue_service_agent_agent_iface_init) G_ADD_PRIVATE (GClueServiceAgent)) enum { PROP_0, PROP_CONNECTION, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static void gclue_service_agent_finalize (GObject *object) { GClueServiceAgentPrivate *priv = GCLUE_SERVICE_AGENT (object)->priv; g_clear_object (&priv->connection); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_service_agent_parent_class)->finalize (object); } static void gclue_service_agent_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueServiceAgent *agent = GCLUE_SERVICE_AGENT (object); switch (prop_id) { case PROP_CONNECTION: g_value_set_object (value, agent->priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_agent_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueServiceAgent *agent = GCLUE_SERVICE_AGENT (object); switch (prop_id) { case PROP_CONNECTION: agent->priv->connection = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_agent_class_init (GClueServiceAgentClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_service_agent_finalize; object_class->get_property = gclue_service_agent_get_property; object_class->set_property = gclue_service_agent_set_property; object_class->constructed = gclue_service_agent_constructed; gParamSpecs[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", "DBus Connection", G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, gParamSpecs[PROP_CONNECTION]); } static void gclue_service_agent_init (GClueServiceAgent *agent) { agent->priv = G_TYPE_INSTANCE_GET_PRIVATE (agent, GCLUE_TYPE_SERVICE_AGENT, GClueServiceAgentPrivate); } static void on_add_agent_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); } static void print_in_use_info (GDBusProxy *manager_proxy) { GVariant *variant; variant = g_dbus_proxy_get_cached_property (manager_proxy, "InUse"); if (g_variant_get_boolean (variant)) g_print (_("Geolocation service in use\n")); else g_print (_("Geolocation service not in use\n")); } static void on_manager_props_changed (GDBusProxy *manager_proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer user_data) { GVariantIter *iter; GVariant *value; gchar *key; if (g_variant_n_children (changed_properties) < 0) return; g_variant_get (changed_properties, "a{sv}", &iter); while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) { if (strcmp (key, "InUse") != 0) continue; print_in_use_info (manager_proxy); break; } g_variant_iter_free (iter); } static void on_manager_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueServiceAgent *agent; GError *error = NULL; agent = GCLUE_SERVICE_AGENT (user_data); agent->priv->manager_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (agent->priv->manager_proxy == NULL) { g_critical ("Failed to create proxy to %s: %s", MANAGER_PATH, error->message); g_error_free (error); return; } g_dbus_proxy_call (agent->priv->manager_proxy, "AddAgent", g_variant_new ("(s)", "geoclue-demo-agent"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, on_add_agent_ready, NULL); print_in_use_info (agent->priv->manager_proxy); g_signal_connect (agent->priv->manager_proxy, "g-properties-changed", G_CALLBACK (on_manager_props_changed), NULL); } static void on_name_appeared (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, SERVICE, MANAGER_PATH, MANAGER_INTERFACE, NULL, on_manager_proxy_ready, user_data); } static void on_name_vanished (GDBusConnection *connection, const gchar *name, gpointer user_data) { GClueServiceAgent *agent = GCLUE_SERVICE_AGENT (user_data); g_clear_object (&agent->priv->manager_proxy); } static void gclue_service_agent_constructed (GObject *object) { GError *error = NULL; GClueServiceAgent *agent = GCLUE_SERVICE_AGENT (object); if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (agent), agent->priv->connection, AGENT_PATH, &error)) { return; } gclue_agent_set_max_accuracy_level (GCLUE_AGENT (agent), GCLUE_ACCURACY_LEVEL_EXACT); g_bus_watch_name (G_BUS_TYPE_SYSTEM, SERVICE, G_BUS_NAME_WATCHER_FLAGS_NONE, on_name_appeared, on_name_vanished, agent, NULL); } typedef struct { GClueAgent *agent; GDBusMethodInvocation *invocation; NotifyNotification *notification; GAppInfo *app_info; gboolean authorized; GClueAccuracyLevel accuracy_level; } NotificationData; static void notification_data_free (NotificationData *data) { g_object_unref (data->app_info); g_object_unref (data->notification); g_slice_free (NotificationData, data); } #define ACTION_YES "yes" #define ACTION_NO "NO" static void on_notify_action (NotifyNotification *notification, char *action, gpointer user_data) { NotificationData *data = (NotificationData *) user_data; GError *error = NULL; data->authorized = (g_strcmp0 (action, ACTION_YES) == 0); if (!notify_notification_close (notification, &error)) { g_dbus_method_invocation_take_error (data->invocation, error); notification_data_free (data); } } static void on_notify_closed (NotifyNotification *notification, gpointer user_data) { NotificationData *data = (NotificationData *) user_data; if (data->authorized) g_debug ("Authorized '%s'", g_app_info_get_display_name (data->app_info)); else g_debug ("'%s' not authorized", g_app_info_get_display_name (data->app_info)); gclue_agent_complete_authorize_app (data->agent, data->invocation, data->authorized, data->accuracy_level); notification_data_free (data); } static gboolean gclue_service_agent_handle_authorize_app (GClueAgent *agent, GDBusMethodInvocation *invocation, const char *desktop_id, GClueAccuracyLevel accuracy_level) { NotifyNotification *notification; NotificationData *data; GError *error = NULL; char *desktop_file; GDesktopAppInfo *app_info; char *msg; const char *reason; desktop_file = g_strjoin (".", desktop_id, "desktop", NULL); app_info = g_desktop_app_info_new (desktop_file); if (app_info == NULL) { g_debug ("Failed to find %s", desktop_file); gclue_agent_complete_authorize_app (agent, invocation, FALSE, accuracy_level); return TRUE; } g_free (desktop_file); msg = g_strdup_printf (_("Allow '%s' to access your location information?"), g_app_info_get_display_name (G_APP_INFO (app_info))); reason = g_desktop_app_info_get_string (app_info, "X-Geoclue-Reason"); if (reason != NULL) { char *tmp = msg; msg = g_strdup_printf ("%s\n\n%s", msg, reason); g_free (tmp); } notification = notify_notification_new (_("Geolocation"), msg, "dialog-question"); g_free (msg); data = g_slice_new0 (NotificationData); data->invocation = invocation; data->notification = notification; data->app_info = G_APP_INFO (app_info); data->accuracy_level = accuracy_level; notify_notification_add_action (notification, ACTION_YES, _("Yes"), on_notify_action, data, NULL); notify_notification_add_action (notification, ACTION_NO, _("No"), on_notify_action, data, NULL); g_signal_connect (notification, "closed", G_CALLBACK (on_notify_closed), data); if (!notify_notification_show (notification, &error)) { g_critical ("Failed to show notification: %s\n", error->message); g_dbus_method_invocation_take_error (invocation, error); notification_data_free (data); return TRUE; } return TRUE; } static void gclue_service_agent_agent_iface_init (GClueAgentIface *iface) { iface->handle_authorize_app = gclue_service_agent_handle_authorize_app; } GClueServiceAgent * gclue_service_agent_new (GDBusConnection *connection) { return g_object_new (GCLUE_TYPE_SERVICE_AGENT, "connection", connection, NULL); } geoclue-2.5.2/demo/gclue-service-agent.h000066400000000000000000000045541341441426700201070ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-agent.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_SERVICE_AGENT_H #define GCLUE_SERVICE_AGENT_H #include #include "geoclue-agent-interface.h" G_BEGIN_DECLS #define GCLUE_TYPE_SERVICE_AGENT (gclue_service_agent_get_type()) #define GCLUE_SERVICE_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_AGENT, GClueServiceAgent)) #define GCLUE_SERVICE_AGENT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_AGENT, GClueServiceAgent const)) #define GCLUE_SERVICE_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_SERVICE_AGENT, GClueServiceAgentClass)) #define GCLUE_IS_SERVICE_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_SERVICE_AGENT)) #define GCLUE_IS_SERVICE_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_SERVICE_AGENT)) #define GCLUE_SERVICE_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_SERVICE_AGENT, GClueServiceAgentClass)) typedef struct _GClueServiceAgent GClueServiceAgent; typedef struct _GClueServiceAgentClass GClueServiceAgentClass; typedef struct _GClueServiceAgentPrivate GClueServiceAgentPrivate; struct _GClueServiceAgent { GClueAgentSkeleton parent; /*< private >*/ GClueServiceAgentPrivate *priv; }; struct _GClueServiceAgentClass { GClueAgentSkeletonClass parent_class; }; GType gclue_service_agent_get_type (void) G_GNUC_CONST; GClueServiceAgent * gclue_service_agent_new (GDBusConnection *connection); G_END_DECLS #endif /* GCLUE_SERVICE_AGENT_H */ geoclue-2.5.2/demo/geoclue-demo-agent.desktop.in.in000066400000000000000000000003431341441426700221430ustar00rootroot00000000000000[Desktop Entry] Name=Geoclue Demo agent GenericName=Demo geoclue agent Keywords=geolocation; Exec=@libexecdir@/geoclue-2.0/demos/agent Icon=mark-location-symbolic NotShowIn=GNOME; NoDisplay=true Terminal=false Type=Application geoclue-2.5.2/demo/geoclue-where-am-i.desktop.in.in000066400000000000000000000005031341441426700220540ustar00rootroot00000000000000[Desktop Entry] Name=Where am I? GenericName=Demo geolocation application Comment=Find your current location Keywords=geolocation; Exec=@libexecdir@/geoclue-2.0/demos/where-am-i Icon=mark-location-symbolic NoDisplay=true Terminal=true Type=Application X-Geoclue-Reason=Allows your current location to be shown on terminal. geoclue-2.5.2/demo/install-file.py000066400000000000000000000010451341441426700170320ustar00rootroot00000000000000#!/usr/bin/env python3 # A simple script that copies a given file (first arg) to a given location # (second arg). import sys import os from shutil import copy if len(sys.argv) < 3: print('Usage: ' + sys.argv[0] + ' SOURCE_FILE DESTINATION_DIR') sys.exit(-1) try: dest_dir = os.environ['DESTDIR'] + '/' + sys.argv[2] except KeyError: dest_dir = sys.argv[2] try: if not os.path.exists(dest_dir): os.makedirs(dest_dir) except OSError: print ('Error: Creating directory. ' + dest_dir) copy(sys.argv[1], dest_dir) geoclue-2.5.2/demo/meson.build000066400000000000000000000047151341441426700162460ustar00rootroot00000000000000desktop_dir = join_paths(datadir, 'applications') demo_dir = join_paths(libexecdir, 'geoclue-2.0', 'demos') i18n = import('i18n') desktop_conf = configuration_data() desktop_conf.set('libexecdir', libexecdir) if get_option('libgeoclue') include_dirs = [ configinc, libgeoclue_public_api_inc, include_directories('../libgeoclue') ] executable('where-am-i', 'where-am-i.c', include_directories: include_dirs, dependencies: [base_deps, libgeoclue_dep], install: true, install_dir: demo_dir) desktop_in = configure_file(output: 'geoclue-where-am-i.desktop.in', input: 'geoclue-where-am-i.desktop.in.in', configuration: desktop_conf) i18n.merge_file(output: 'geoclue-where-am-i.desktop', input: desktop_in, type: 'desktop', po_dir: '../po', install: true, install_dir: desktop_dir) endif if get_option('demo-agent') include_dirs = [ configinc, libgeoclue_public_api_inc, libgeoclue_agent_inc ] sources = [ 'gclue-service-agent.h', 'gclue-service-agent.c', 'agent.c', libgeoclue_agent_sources[1] ] deps = base_deps + [ dependency('libnotify') ] executable('agent', sources, include_directories: include_dirs, link_whole: [ libgeoclue_agent ], dependencies: deps, install: true, install_dir: demo_dir) desktop_in = configure_file(output: 'geoclue-demo-agent.desktop.in', input: 'geoclue-demo-agent.desktop.in.in', configuration: desktop_conf) desktop_file = i18n.merge_file(output: 'geoclue-demo-agent.desktop', input: desktop_in, type: 'desktop', po_dir: '../po', install: true, install_dir: desktop_dir) # Also install in the autostart directory. autostart_dir = join_paths(sysconfdir, 'xdg', 'autostart') meson.add_install_script('install-file.py', desktop_file.full_path(), autostart_dir) endif geoclue-2.5.2/demo/where-am-i.c000066400000000000000000000142751341441426700162050ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* where-am-i.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include #include #include #include /* Commandline options */ static gint timeout = 30; /* seconds */ static GClueAccuracyLevel accuracy_level = GCLUE_ACCURACY_LEVEL_EXACT; static gint time_threshold; static GOptionEntry entries[] = { { "timeout", 't', 0, G_OPTION_ARG_INT, &timeout, N_("Exit after T seconds. Default: 30"), "T" }, { "time-threshold", 'i', 0, G_OPTION_ARG_INT, &time_threshold, N_("Only report location update after T seconds. " "Default: 0 (report new location without any delay)"), "T" }, { "accuracy-level", 'a', 0, G_OPTION_ARG_INT, &accuracy_level, N_("Request accuracy level A. " "Country = 1, " "City = 4, " "Neighborhood = 5, " "Street = 6, " "Exact = 8."), "A" }, { NULL } }; GClueSimple *simple = NULL; GClueClient *client = NULL; GMainLoop *main_loop; static gboolean on_location_timeout (gpointer user_data) { g_clear_object (&client); g_clear_object (&simple); g_main_loop_quit (main_loop); return FALSE; } static void print_location (GClueSimple *simple) { GClueLocation *location; gdouble altitude, speed, heading; GVariant *timestamp; GTimeVal tv = { 0 }; const char *desc; location = gclue_simple_get_location (simple); g_print ("\nNew location:\n"); g_print ("Latitude: %f°\nLongitude: %f°\nAccuracy: %f meters\n", gclue_location_get_latitude (location), gclue_location_get_longitude (location), gclue_location_get_accuracy (location)); altitude = gclue_location_get_altitude (location); if (altitude != -G_MAXDOUBLE) g_print ("Altitude: %f meters\n", altitude); speed = gclue_location_get_speed (location); if (speed >= 0) g_print ("Speed: %f meters/second\n", speed); heading = gclue_location_get_heading (location); if (heading >= 0) g_print ("Heading: %f°\n", heading); desc = gclue_location_get_description (location); if (strlen (desc) > 0) g_print ("Description: %s\n", desc); timestamp = gclue_location_get_timestamp (location); if (timestamp) { GDateTime *date_time; gchar *str; g_variant_get (timestamp, "(tt)", &tv.tv_sec, &tv.tv_usec); date_time = g_date_time_new_from_timeval_local (&tv); str = g_date_time_format (date_time, "%c (%s seconds since the Epoch)"); g_date_time_unref (date_time); g_print ("Timestamp: %s\n", str); g_free (str); } } static void on_client_active_notify (GClueClient *client, GParamSpec *pspec, gpointer user_data) { if (gclue_client_get_active (client)) return; g_print ("Geolocation disabled. Quitting..\n"); on_location_timeout (NULL); } static void on_simple_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; simple = gclue_simple_new_finish (res, &error); if (error != NULL) { g_critical ("Failed to connect to GeoClue2 service: %s", error->message); exit (-1); } client = gclue_simple_get_client (simple); g_object_ref (client); g_print ("Client object: %s\n", g_dbus_proxy_get_object_path (G_DBUS_PROXY (client))); if (time_threshold > 0) { gclue_client_set_time_threshold (client, time_threshold); } print_location (simple); g_signal_connect (simple, "notify::location", G_CALLBACK (print_location), NULL); g_signal_connect (client, "notify::active", G_CALLBACK (on_client_active_notify), NULL); } gint main (gint argc, gchar *argv[]) { GOptionContext *context; GError *error = NULL; setlocale (LC_ALL, ""); textdomain (GETTEXT_PACKAGE); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); context = g_option_context_new ("- Where am I?"); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_critical ("option parsing failed: %s\n", error->message); exit (-1); } g_option_context_free (context); g_timeout_add_seconds (timeout, on_location_timeout, NULL); gclue_simple_new ("geoclue-where-am-i", accuracy_level, NULL, on_simple_ready, NULL); main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); return EXIT_SUCCESS; } geoclue-2.5.2/docs/000077500000000000000000000000001341441426700141015ustar00rootroot00000000000000geoclue-2.5.2/docs/geoclue-docs.xml000066400000000000000000000057131341441426700172020ustar00rootroot00000000000000 ]> Geoclue Reference Manual Version &version; Zeeshan Ali (Khattak)
zeeshanak@gnome.org
2013, 2014 Red Hat, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, 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 GNU Free Documentation License from the Free Software Foundation by visiting their Web site or by writing to:
The Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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.
D-Bus API Reference This part documents the D-Bus interface used to access the Geoclue service. Agent D-Bus API Reference This part documents the D-Bus interface that application-authorizing agents must implement. Index License FIXME: MISSING XINCLUDE CONTENT
geoclue-2.5.2/docs/lib/000077500000000000000000000000001341441426700146475ustar00rootroot00000000000000geoclue-2.5.2/docs/lib/libgeoclue-docs.xml000066400000000000000000000056711341441426700204420ustar00rootroot00000000000000 ]> Libgeoclue Reference Manual Version &version; Zeeshan Ali (Khattak)
zeeshanak@gnome.org
2015 Red Hat, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, 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 GNU Free Documentation License from the Free Software Foundation by visiting their Web site or by writing to:
The Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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.
Common enums and flags helpers Convenience API The Manager object The Client object The Location object Index License FIXME: MISSING XINCLUDE CONTENT
geoclue-2.5.2/docs/lib/libgeoclue-sections.txt000066400000000000000000000140021341441426700213440ustar00rootroot00000000000000
GClueClient GClueClient GCLUE_CLIENT_SKELETON GCLUE_CLIENT_SKELETON_CLASS GCLUE_CLIENT_SKELETON_GET_CLASS GCLUE_IS_CLIENT_SKELETON GCLUE_IS_CLIENT_SKELETON_CLASS GCLUE_TYPE_CLIENT_SKELETON GClueClientSkeleton GClueClientSkeletonClass GClueClientSkeletonPrivate gclue_client_skeleton_get_type gclue_client_skeleton_new
gclue-client GClueClient gclue_client_interface_info gclue_client_override_properties gclue_client_emit_location_updated gclue_client_call_start gclue_client_call_start_finish gclue_client_call_start_sync gclue_client_call_stop gclue_client_call_stop_finish gclue_client_call_stop_sync gclue_client_get_location gclue_client_dup_location gclue_client_set_location gclue_client_get_distance_threshold gclue_client_set_distance_threshold gclue_client_get_desktop_id gclue_client_dup_desktop_id gclue_client_set_desktop_id gclue_client_get_requested_accuracy_level gclue_client_set_requested_accuracy_level gclue_client_get_active gclue_client_set_active GCLUE_CLIENT GCLUE_CLIENT_GET_IFACE GCLUE_IS_CLIENT GCLUE_TYPE_CLIENT GClueClient GClueClientIface gclue_client_get_type gclue_client_complete_start gclue_client_complete_stop
gclue-client-proxy GClueClientProxy gclue_client_proxy_create gclue_client_proxy_create_finish gclue_client_proxy_create_sync gclue_client_proxy_new gclue_client_proxy_new_finish gclue_client_proxy_new_sync gclue_client_proxy_new_for_bus gclue_client_proxy_new_for_bus_finish gclue_client_proxy_new_for_bus_sync gclue_client_get_time_threshold gclue_client_set_time_threshold GCLUE_CLIENT_PROXY GCLUE_CLIENT_PROXY_CLASS GCLUE_CLIENT_PROXY_GET_CLASS GCLUE_IS_CLIENT_PROXY GCLUE_IS_CLIENT_PROXY_CLASS GCLUE_TYPE_CLIENT_PROXY GClueClientProxy GClueClientProxyClass gclue_client_proxy_get_type GClueClientProxyPrivate
gclue-enums GClueAccuracyLevel GCLUE_TYPE_ACCURACY_LEVEL gclue_accuracy_level_get_type gclue_accuracy_level_build_string_from_mask gclue_accuracy_level_get_string
gclue-helpers
GClueLocation GClueLocation GCLUE_IS_LOCATION_SKELETON GCLUE_IS_LOCATION_SKELETON_CLASS GCLUE_LOCATION_SKELETON GCLUE_LOCATION_SKELETON_CLASS GCLUE_LOCATION_SKELETON_GET_CLASS GCLUE_TYPE_LOCATION_SKELETON GClueLocationSkeleton GClueLocationSkeletonClass GClueLocationSkeletonPrivate gclue_location_skeleton_get_type gclue_location_skeleton_new
gclue-location GClueLocation gclue_location_interface_info gclue_location_override_properties gclue_location_get_latitude gclue_location_set_latitude gclue_location_get_longitude gclue_location_set_longitude gclue_location_get_accuracy gclue_location_set_accuracy gclue_location_get_altitude gclue_location_set_altitude gclue_location_get_speed gclue_location_set_speed gclue_location_get_heading gclue_location_set_heading gclue_location_get_description gclue_location_dup_description gclue_location_set_description gclue_location_get_timestamp gclue_location_dup_timestamp gclue_location_set_timestamp GCLUE_IS_LOCATION GCLUE_LOCATION GCLUE_LOCATION_GET_IFACE GCLUE_TYPE_LOCATION GClueLocation GClueLocationIface gclue_location_get_type
gclue-location-proxy GClueLocationProxy gclue_location_proxy_new gclue_location_proxy_new_finish gclue_location_proxy_new_sync gclue_location_proxy_new_for_bus gclue_location_proxy_new_for_bus_finish gclue_location_proxy_new_for_bus_sync GCLUE_IS_LOCATION_PROXY GCLUE_IS_LOCATION_PROXY_CLASS GCLUE_LOCATION_PROXY GCLUE_LOCATION_PROXY_CLASS GCLUE_LOCATION_PROXY_GET_CLASS GCLUE_TYPE_LOCATION_PROXY GClueLocationProxy GClueLocationProxyClass GClueLocationProxyPrivate gclue_location_proxy_get_type
GClueManager GClueManager
gclue-manager GClueManager gclue_manager_interface_info gclue_manager_override_properties gclue_manager_call_get_client gclue_manager_call_get_client_finish gclue_manager_call_get_client_sync gclue_manager_call_add_agent gclue_manager_call_add_agent_finish gclue_manager_call_add_agent_sync gclue_manager_get_in_use gclue_manager_set_in_use gclue_manager_get_available_accuracy_level gclue_manager_set_available_accuracy_level GCLUE_IS_MANAGER GCLUE_MANAGER GCLUE_MANAGER_GET_IFACE GCLUE_TYPE_MANAGER GClueManager GClueManagerIface gclue_manager_get_type GCLUE_IS_MANAGER_SKELETON GCLUE_IS_MANAGER_SKELETON_CLASS GCLUE_MANAGER_SKELETON GCLUE_MANAGER_SKELETON_CLASS GCLUE_MANAGER_SKELETON_GET_CLASS GCLUE_TYPE_MANAGER_SKELETON GClueManagerSkeleton GClueManagerSkeletonClass GClueManagerSkeletonPrivate gclue_manager_skeleton_get_type gclue_manager_skeleton_new gclue_manager_complete_get_client gclue_manager_complete_add_agent
gclue-manager-proxy GClueManagerProxy gclue_manager_proxy_new gclue_manager_proxy_new_finish gclue_manager_proxy_new_sync gclue_manager_proxy_new_for_bus gclue_manager_proxy_new_for_bus_finish gclue_manager_proxy_new_for_bus_sync GCLUE_IS_MANAGER_PROXY GCLUE_IS_MANAGER_PROXY_CLASS GCLUE_MANAGER_PROXY GCLUE_MANAGER_PROXY_CLASS GCLUE_MANAGER_PROXY_GET_CLASS GCLUE_TYPE_MANAGER_PROXY GClueManagerProxy GClueManagerProxyClass gclue_manager_proxy_get_type GClueManagerProxyPrivate
gclue-simple GClueSimple gclue_simple_new gclue_simple_new_finish gclue_simple_new_sync gclue_simple_get_client gclue_simple_get_location GCLUE_IS_SIMPLE GCLUE_IS_SIMPLE_CLASS GCLUE_SIMPLE GCLUE_SIMPLE_CLASS GCLUE_SIMPLE_GET_CLASS GCLUE_TYPE_SIMPLE GClueSimple GClueSimpleClass GClueSimplePrivate gclue_simple_get_type
geoclue-2.5.2/docs/lib/meson.build000066400000000000000000000015771341441426700170230ustar00rootroot00000000000000conf = configuration_data() conf.set_quoted('VERSION', gclue_version) version_file = configure_file(output: 'version.xml', input: 'version.xml.in', configuration: conf) content_files = [ '../../COPYING.LIB' ] scan_options = [ '--ignore-headers=config.h', '--rebuild-types' ] # Extra options to supply to gtkdoc-mkdb mkdb_options = [ '--output-format=xml' ] src_dir = [ 'public-api', 'libgeoclue' ] fixxref_options = [ '--extra-dir=../html' ] gnome.gtkdoc('libgeoclue', main_xml: 'libgeoclue-docs.xml', content_files: content_files, gobject_typesfile: 'libgeoclue.types', dependencies: libgeoclue_dep, scan_args: scan_options, fixxref_args: fixxref_options, src_dir: src_dir, mkdb_args: mkdb_options, install: true) geoclue-2.5.2/docs/lib/version.xml.in000066400000000000000000000000121341441426700174540ustar00rootroot00000000000000@VERSION@ geoclue-2.5.2/docs/meson.build000066400000000000000000000016071341441426700162470ustar00rootroot00000000000000if get_option('libgeoclue') subdir('lib') endif conf = configuration_data() conf.set_quoted('VERSION', gclue_version) version_file = configure_file(output: 'version.xml', input: 'version.xml.in', configuration: conf) content_files = [ '../COPYING', dbus_gen_src, libgeoclue_agent_sources ] scan_options = [ '--ignore-headers=config.h', '--rebuild-sections', '--rebuild-types' ] # Extra options to supply to gtkdoc-mkdb mkdb_options = [ '--output-format=xml' ] gnome.gtkdoc('geoclue', main_xml: 'geoclue-docs.xml', content_files: content_files, scan_args: scan_options, src_dir: libgeoclue_public_api_inc, mkdb_args: mkdb_options, dependencies: libgeoclue_dep, install: true) geoclue-2.5.2/docs/version.xml.in000066400000000000000000000000121341441426700167060ustar00rootroot00000000000000@VERSION@ geoclue-2.5.2/geoclue.doap000066400000000000000000000017631341441426700154500ustar00rootroot00000000000000 GeoClue The Geoinformation Service No long description yet Zeeshan Ali (Khattak) zeeshanak geoclue-2.5.2/libgeoclue/000077500000000000000000000000001341441426700152635ustar00rootroot00000000000000geoclue-2.5.2/libgeoclue/gclue-helpers.c000066400000000000000000000206731341441426700201760ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Geoclue convenience library. * * Copyright 2015 Red Hat, Inc. * * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include "gclue-helpers.h" #define BUS_NAME "org.freedesktop.GeoClue2" #define MANAGER_PATH "/org/freedesktop/GeoClue2/Manager" /** * SECTION: gclue-helpers * @title: Geoclue helper API * @short_description: Geoclue helper API * * TODO */ typedef struct { char *desktop_id; GClueAccuracyLevel accuracy_level; gulong notify_id; } ClientCreateData; static ClientCreateData * client_create_data_new (const char *desktop_id, GClueAccuracyLevel accuracy_level) { ClientCreateData *data = g_slice_new0 (ClientCreateData); data->desktop_id = g_strdup (desktop_id); data->accuracy_level = accuracy_level; return data; } static void client_create_data_free (ClientCreateData *data) { g_free (data->desktop_id); g_slice_free (ClientCreateData, data); } static void on_client_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); ClientCreateData *data; GClueClient *client; GError *error = NULL; client = gclue_client_proxy_new_for_bus_finish (res, &error); if (error != NULL) { g_task_return_error (task, error); g_object_unref (task); return; } data = g_task_get_task_data (task); gclue_client_set_desktop_id (client, data->desktop_id); gclue_client_set_requested_accuracy_level (client, data->accuracy_level); g_task_return_pointer (task, client, g_object_unref); g_object_unref (task); } static void on_get_client_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); GClueManager *manager = GCLUE_MANAGER (source_object); char *client_path; GError *error = NULL; if (!gclue_manager_call_get_client_finish (manager, &client_path, res, &error)) { g_task_return_error (task, error); g_object_unref (task); g_object_unref (manager); return; } gclue_client_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, BUS_NAME, client_path, g_task_get_cancellable (task), on_client_proxy_ready, task); g_free (client_path); g_object_unref (manager); } static void on_manager_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); GClueManager *manager; GError *error = NULL; manager = gclue_manager_proxy_new_finish (res, &error); if (error != NULL) { g_task_return_error (task, error); g_object_unref (task); return; } gclue_manager_call_get_client (manager, g_task_get_cancellable (task), on_get_client_ready, task); } /** * gclue_client_proxy_create: * @desktop_id: The desktop file id (the basename of the desktop file). * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. * @cancellable: (allow-none): A #GCancellable or %NULL. * @callback: A #GAsyncReadyCallback to call when the results are ready. * @user_data: User data to pass to @callback. * * A utility function to create a #GClueClientProxy without having to deal with * a #GClueManager. * * See #gclue_client_proxy_create_sync() for the synchronous, blocking version * of this function. */ void gclue_client_proxy_create (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; ClientCreateData *data; task = g_task_new (NULL, cancellable, callback, user_data); data = client_create_data_new (desktop_id, accuracy_level); g_task_set_task_data (task, data, (GDestroyNotify) client_create_data_free); gclue_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, BUS_NAME, MANAGER_PATH, cancellable, on_manager_proxy_ready, task); } /** * gclue_client_proxy_create_finish: * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to * gclue_client_proxy_create(). * @error: Return location for error or %NULL. * * Finishes an operation started with gclue_client_proxy_create(). * * Returns: (transfer full) (type GClueClientProxy): The constructed proxy * object or %NULL if @error is set. */ GClueClient * gclue_client_proxy_create_finish (GAsyncResult *result, GError **error) { g_return_val_if_fail (g_task_is_valid (result, NULL), NULL); return g_task_propagate_pointer (G_TASK (result), error); } typedef struct { GClueClient *client; GError **error; GMainLoop *main_loop; } ClientCreateSyncData; static void on_client_proxy_created (GObject *source_object, GAsyncResult *res, gpointer user_data) { ClientCreateSyncData *data = (ClientCreateSyncData *) user_data; data->client = gclue_client_proxy_create_finish (res, data->error); g_main_loop_quit (data->main_loop); } /** * gclue_client_proxy_create_sync: * @desktop_id: The desktop file id (the basename of the desktop file). * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. * @cancellable: (allow-none): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * * The synchronous and blocking version of #gclue_client_proxy_create(). * * Returns: (transfer full) (type GClueClientProxy): The constructed proxy * object or %NULL if @error is set. */ GClueClient * gclue_client_proxy_create_sync (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GError **error) { GClueClient *client; ClientCreateSyncData *data = g_slice_new0 (ClientCreateSyncData); data->error = error; data->main_loop = g_main_loop_new (NULL, FALSE); gclue_client_proxy_create (desktop_id, accuracy_level, cancellable, on_client_proxy_created, data); g_main_loop_run (data->main_loop); g_main_loop_unref (data->main_loop); client = data->client; g_slice_free (ClientCreateSyncData, data); return client; } geoclue-2.5.2/libgeoclue/gclue-helpers.h000066400000000000000000000037121341441426700201760ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Geoclue convenience library. * * Copyright 2015 Red Hat, Inc. * * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef __GCLUE_HELPERS_H__ #define __GCLUE_HELPERS_H__ #include #include #include G_BEGIN_DECLS void gclue_client_proxy_create (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GClueClient * gclue_client_proxy_create_finish (GAsyncResult *result, GError **error); GClueClient * gclue_client_proxy_create_sync (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GError **error); G_END_DECLS #endif /* #ifndef __GCLUE_HELPERS_H__*/ geoclue-2.5.2/libgeoclue/gclue-simple.c000066400000000000000000000432511341441426700200220ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Geoclue convenience library. * * Copyright 2015 Red Hat, Inc. * * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ /** * SECTION: gclue-simple * @title: GClueSimple * @short_description: Simplified convenience API * * #GClueSimple make it very simple to get latest location and monitoring * location updates. It takes care of the boring tasks of creating a * #GClueClientProxy instance, starting it, waiting till we have a location fix * and then creating a #GClueLocationProxy instance for it. * * Use #gclue_simple_new() or #gclue_simple_new_sync() to create a new * #GClueSimple instance. Once you have a #GClueSimple instance, you can get the * latest location using #gclue_simple_get_location() or reading the * #GClueSimple:location property. To monitor location updates, connect to * notify signal for this property. * * While most applications will find this API very useful, it is most * useful for applications that simply want to get the current location as * quickly as possible and do not care about accuracy (much). */ #include #include "gclue-simple.h" #include "gclue-helpers.h" #define BUS_NAME "org.freedesktop.GeoClue2" static void gclue_simple_async_initable_init (GAsyncInitableIface *iface); struct _GClueSimplePrivate { char *desktop_id; GClueAccuracyLevel accuracy_level; GClueClient *client; GClueLocation *location; gulong update_id; GTask *task; GCancellable *cancellable; }; G_DEFINE_TYPE_WITH_CODE (GClueSimple, gclue_simple, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gclue_simple_async_initable_init) G_ADD_PRIVATE (GClueSimple)); enum { PROP_0, PROP_DESKTOP_ID, PROP_ACCURACY_LEVEL, PROP_CLIENT, PROP_LOCATION, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static void gclue_simple_finalize (GObject *object) { GClueSimplePrivate *priv = GCLUE_SIMPLE (object)->priv; g_clear_pointer (&priv->desktop_id, g_free); if (priv->update_id != 0) { g_signal_handler_disconnect (priv->client, priv->update_id); priv->update_id = 0; } if (priv->cancellable != NULL) g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); g_clear_object (&priv->client); g_clear_object (&priv->location); g_clear_object (&priv->task); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_simple_parent_class)->finalize (object); } static void gclue_simple_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueSimple *simple = GCLUE_SIMPLE (object); switch (prop_id) { case PROP_CLIENT: g_value_set_object (value, simple->priv->client); break; case PROP_LOCATION: g_value_set_object (value, simple->priv->location); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_simple_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueSimple *simple = GCLUE_SIMPLE (object); switch (prop_id) { case PROP_DESKTOP_ID: simple->priv->desktop_id = g_value_dup_string (value); break; case PROP_ACCURACY_LEVEL: simple->priv->accuracy_level = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_simple_class_init (GClueSimpleClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_simple_finalize; object_class->get_property = gclue_simple_get_property; object_class->set_property = gclue_simple_set_property; /** * GClueSimple:desktop-id: * * The Desktop ID of the application. */ gParamSpecs[PROP_DESKTOP_ID] = g_param_spec_string ("desktop-id", "DesktopID", "Desktop ID", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_DESKTOP_ID, gParamSpecs[PROP_DESKTOP_ID]); /** * GClueSimple:accuracy-level: * * The requested maximum accuracy level. */ gParamSpecs[PROP_ACCURACY_LEVEL] = g_param_spec_enum ("accuracy-level", "AccuracyLevel", "Requested accuracy level", GCLUE_TYPE_ACCURACY_LEVEL, GCLUE_ACCURACY_LEVEL_NONE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_ACCURACY_LEVEL, gParamSpecs[PROP_ACCURACY_LEVEL]); /** * GClueSimple:client: * * The client proxy. */ gParamSpecs[PROP_CLIENT] = g_param_spec_object ("client", "Client", "Client proxy", GCLUE_TYPE_CLIENT_PROXY, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_CLIENT, gParamSpecs[PROP_CLIENT]); /** * GClueSimple:location: * * The current location. */ gParamSpecs[PROP_LOCATION] = g_param_spec_object ("location", "Location", "Location proxy", GCLUE_TYPE_LOCATION_PROXY, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_LOCATION, gParamSpecs[PROP_LOCATION]); } static void on_location_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueSimplePrivate *priv = GCLUE_SIMPLE (user_data)->priv; GClueLocation *location; GError *error = NULL; location = gclue_location_proxy_new_for_bus_finish (res, &error); if (error != NULL) { if (priv->task != NULL) { g_task_return_error (priv->task, error); g_clear_object (&priv->task); } else { g_warning ("Failed to create location proxy: %s", error->message); } return; } g_clear_object (&priv->location); priv->location = location; if (priv->task != NULL) { g_task_return_boolean (priv->task, TRUE); g_clear_object (&priv->task); } else { g_object_notify (G_OBJECT (user_data), "location"); } } static void on_location_updated (GClueClient *client, const char *old_location, const char *new_location, gpointer user_data) { GClueSimplePrivate *priv = GCLUE_SIMPLE (user_data)->priv; if (new_location == NULL || g_strcmp0 (new_location, "/") == 0) return; gclue_location_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, BUS_NAME, new_location, priv->cancellable, on_location_proxy_ready, user_data); } static void on_client_started (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); GClueClient *client = GCLUE_CLIENT (source_object); GClueSimple *simple; const char *location; GError *error = NULL; simple = g_task_get_source_object (task); gclue_client_call_start_finish (client, res, &error); if (error != NULL) { g_task_return_error (task, error); g_clear_object (&simple->priv->task); return; } location = gclue_client_get_location (client); on_location_updated (client, NULL, location, simple); } static void on_client_created (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); GClueSimple *simple = g_task_get_source_object (task); GClueSimplePrivate *priv = simple->priv; GError *error = NULL; priv->client = gclue_client_proxy_create_finish (res, &error); if (error != NULL) { g_task_return_error (task, error); g_clear_object (&priv->task); return; } priv->task = task; priv->update_id = g_signal_connect (priv->client, "location-updated", G_CALLBACK (on_location_updated), simple); gclue_client_call_start (priv->client, g_task_get_cancellable (task), on_client_started, task); } static void gclue_simple_init_async (GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; GClueSimple *simple = GCLUE_SIMPLE (initable); task = g_task_new (initable, cancellable, callback, user_data); gclue_client_proxy_create (simple->priv->desktop_id, simple->priv->accuracy_level, cancellable, on_client_created, task); } static gboolean gclue_simple_init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) { return g_task_propagate_boolean (G_TASK (result), error); } static void gclue_simple_async_initable_init (GAsyncInitableIface *iface) { iface->init_async = gclue_simple_init_async; iface->init_finish = gclue_simple_init_finish; } static void gclue_simple_init (GClueSimple *simple) { simple->priv = G_TYPE_INSTANCE_GET_PRIVATE (simple, GCLUE_TYPE_SIMPLE, GClueSimplePrivate); simple->priv->cancellable = g_cancellable_new (); } /** * gclue_simple_new: * @desktop_id: The desktop file id (the basename of the desktop file). * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. * @cancellable: (allow-none): A #GCancellable or %NULL. * @callback: A #GAsyncReadyCallback to call when the results are ready. * @user_data: User data to pass to @callback. * * Asynchronously creates a #GClueSimple instance. Use * #gclue_simple_new_finish() to get the created #GClueSimple instance. * * See #gclue_simple_new_sync() for the synchronous, blocking version * of this function. */ void gclue_simple_new (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async (GCLUE_TYPE_SIMPLE, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "desktop-id", desktop_id, "accuracy-level", accuracy_level, NULL); } /** * gclue_simple_new_finish: * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to * #gclue_simple_new(). * @error: Return location for error or %NULL. * * Finishes an operation started with #gclue_simple_new(). * * Returns: (transfer full) (type GClueSimple): The constructed proxy * object or %NULL if @error is set. */ GClueSimple * gclue_simple_new_finish (GAsyncResult *result, GError **error) { GObject *object; GObject *source_object; source_object = g_async_result_get_source_object (result); object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error); g_object_unref (source_object); if (object != NULL) return GCLUE_SIMPLE (object); else return NULL; } static void on_simple_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueSimple *simple; GTask *task = G_TASK (user_data); GMainLoop *main_loop; GError *error = NULL; simple = gclue_simple_new_finish (res, &error); if (error != NULL) { g_task_return_error (task, error); goto out; } g_task_return_pointer (task, simple, g_object_unref); out: main_loop = g_task_get_task_data (task); g_main_loop_quit (main_loop); } /** * gclue_simple_new_sync: * @desktop_id: The desktop file id (the basename of the desktop file). * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. * @cancellable: (allow-none): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * * The synchronous and blocking version of #gclue_simple_new(). * * Returns: (transfer full) (type GClueSimple): The new #GClueSimple object or * %NULL if @error is set. */ GClueSimple * gclue_simple_new_sync (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GError **error) { GClueSimple *simple; GMainLoop *main_loop; GTask *task; task = g_task_new (NULL, cancellable, NULL, NULL); main_loop = g_main_loop_new (NULL, FALSE); g_task_set_task_data (task, main_loop, (GDestroyNotify) g_main_loop_unref); gclue_simple_new (desktop_id, accuracy_level, cancellable, on_simple_ready, task); g_main_loop_run (main_loop); simple = g_task_propagate_pointer (task, error); g_object_unref (task); return simple; } /** * gclue_simple_get_client: * @simple: A #GClueSimple object. * * Gets the client proxy. * * Returns: (transfer none) (type GClueClientProxy): The client object. */ GClueClient * gclue_simple_get_client (GClueSimple *simple) { g_return_val_if_fail (GCLUE_IS_SIMPLE(simple), NULL); return simple->priv->client; } /** * gclue_simple_get_location: * @simple: A #GClueSimple object. * * Gets the current location. * * Returns: (transfer none) (type GClueLocationProxy): The last known location * as #GClueLocation. */ GClueLocation * gclue_simple_get_location (GClueSimple *simple) { g_return_val_if_fail (GCLUE_IS_SIMPLE(simple), NULL); return simple->priv->location; } geoclue-2.5.2/libgeoclue/gclue-simple.h000066400000000000000000000060001341441426700200160ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Geoclue convenience library. * * Copyright 2015 Red Hat, Inc. * * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_SIMPLE_H #define GCLUE_SIMPLE_H #include #include #include "gclue-client.h" #include "gclue-location.h" #include "gclue-enum-types.h" G_BEGIN_DECLS #define GCLUE_TYPE_SIMPLE (gclue_simple_get_type()) #define GCLUE_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SIMPLE, GClueSimple)) #define GCLUE_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_SIMPLE, GClueSimpleClass)) #define GCLUE_IS_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_SIMPLE)) #define GCLUE_IS_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_SIMPLE)) #define GCLUE_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_SIMPLE, GClueSimpleClass)) typedef struct _GClueSimple GClueSimple; typedef struct _GClueSimpleClass GClueSimpleClass; typedef struct _GClueSimplePrivate GClueSimplePrivate; struct _GClueSimple { GObject parent; /*< private >*/ GClueSimplePrivate *priv; }; struct _GClueSimpleClass { GObjectClass parent_class; }; GType gclue_simple_get_type (void) G_GNUC_CONST; void gclue_simple_new (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GClueSimple * gclue_simple_new_finish (GAsyncResult *result, GError **error); GClueSimple * gclue_simple_new_sync (const char *desktop_id, GClueAccuracyLevel accuracy_level, GCancellable *cancellable, GError **error); GClueClient * gclue_simple_get_client (GClueSimple *simple); GClueLocation * gclue_simple_get_location (GClueSimple *simple); G_END_DECLS #endif /* GCLUE_SIMPLE_H */ geoclue-2.5.2/libgeoclue/geoclue.h000066400000000000000000000021611341441426700170570ustar00rootroot00000000000000/* * geoclue.h: Geoclue convenience library. * * Copyright 2010-2011,2015 Red Hat, Inc. * * 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.1 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, see * . * * Author: Zeeshan Ali (Khattak) */ #ifndef __GEOCLUE_H__ #define __GEOCLUE_H__ #include #include #include #include #include #include #include #include #include #endif /* __GEOCLUE_H__ */ geoclue-2.5.2/libgeoclue/libgeoclue-2.0.deps000066400000000000000000000000521341441426700205440ustar00rootroot00000000000000glib-2.0 gobject-2.0 gio-2.0 gio-unix-2.0 geoclue-2.5.2/libgeoclue/libgeoclue.pc.in000066400000000000000000000005401341441426700203250ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ datarootdir=@datarootdir@ datadir=@datadir@ libdir=@libdir@ includedir=@includedir@ Name: Geoclue Client Library Description: A convenience library to interact with Geoclue service Version: @VERSION@ Requires: glib-2.0 gio-2.0 gio-unix-2.0 Libs: -L${libdir} -lgeoclue-2 Cflags: -I${includedir}/libgeoclue-2.0 geoclue-2.5.2/libgeoclue/meson.build000066400000000000000000000105001341441426700174210ustar00rootroot00000000000000# FIXME: meson 0.46 doesn't seem to be actually installing the headers # generated by gnome.gdbus_codegen: # # https://github.com/mesonbuild/meson/pull/3487 # Client interface gclue_client = gnome.gdbus_codegen('gclue-client', '../src/org.freedesktop.GeoClue2.Client.xml', interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClue', install_header: true, install_dir: include_subdir) # Location interface gclue_location = gnome.gdbus_codegen('gclue-location', '../src/org.freedesktop.GeoClue2.Location.xml', interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClue', install_header: true, install_dir: include_subdir) # Manager interface gclue_manager = gnome.gdbus_codegen('gclue-manager', '../src/org.freedesktop.GeoClue2.Manager.xml', interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClue', install_header: true, install_dir: include_subdir) libgeoclue_sources = files('gclue-helpers.c', 'gclue-simple.c') libgeoclue_sources += gclue_client[0] libgeoclue_sources += gclue_location[0] libgeoclue_sources += gclue_manager[0] libgeoclue_sources += libgeoclue_public_api_gen_sources[1] libgeoclue_headers = files('geoclue.h', 'gclue-helpers.h', 'gclue-simple.h') install_headers(libgeoclue_headers, subdir: header_dir) libgeoclue_headers += gclue_client[1] libgeoclue_headers += gclue_location[1] libgeoclue_headers += gclue_manager[1] c_args = [ '-DG_LOG_DOMAIN="Geoclue"' ] include_dirs = [ libgeoclue_public_api_inc, include_directories('.', '..') ] link_whole = [ libgeoclue_public_api ] libgeoclue = library('geoclue-2', libgeoclue_sources, libgeoclue_headers, include_directories: include_dirs, dependencies: base_deps, link_whole: link_whole, soversion: '0', version: '0.0.0', install: true) gir = find_program('g-ir-scanner', required: false) vapigen = find_program('vapigen', required: false) enable_gir = get_option('introspection') pkg_requirements = ['glib-2.0', 'gio-2.0', 'gio-unix-2.0'] gir_sources = [ libgeoclue_sources, libgeoclue_headers, libgeoclue_public_api_gen_sources[1] ] if gir.found() and enable_gir geo_gir = gnome.generate_gir(libgeoclue, sources: gir_sources, namespace: 'Geoclue', nsversion: gclue_api_version, identifier_prefix: 'GClue', symbol_prefix: 'gclue', export_packages: 'libgeoclue-' + gclue_api_version, dependencies: base_deps, includes: [ 'GObject-2.0', 'Gio-2.0' ], include_directories: include_dirs, install: true, header: 'geoclue.h', extra_args: [ '--quiet' ]) if vapigen.found() gnome.generate_vapi('libgeoclue-' + gclue_api_version, sources: geo_gir[0], packages: pkg_requirements, install: true) endif endif description = 'A convenience library to interact with Geoclue service' pkgconf = import('pkgconfig') pkgconf.generate(version: gclue_version, name: 'Geoclue Client Library', description: description, filebase: 'libgeoclue-' + gclue_api_version, libraries: libgeoclue, subdirs: [ header_dir ], requires: pkg_requirements) libgeoclue_dep = declare_dependency(link_with: libgeoclue, include_directories: include_dirs, dependencies: base_deps, sources: [ libgeoclue_sources, libgeoclue_headers ]) geoclue-2.5.2/meson.build000066400000000000000000000071551341441426700153230ustar00rootroot00000000000000project('geoclue', 'c', version: '2.5.2', meson_version : '>= 0.47.2') gclue_version = meson.project_version() ver_arr = gclue_version.split('.') gclue_major_version = ver_arr[0] gclue_minor_version = ver_arr[1] gclue_micro_version = ver_arr[2] gclue_api_version='2.0' datadir = join_paths(get_option('prefix'), get_option('datadir')) includedir = join_paths(get_option('prefix'), get_option('includedir')) libexecdir = join_paths(get_option('prefix'), get_option('libexecdir')) sysconfdir = join_paths(get_option('prefix'), get_option('sysconfdir')) localedir = join_paths(datadir, 'locale') header_dir = 'libgeoclue-' + gclue_api_version include_subdir = join_paths(includedir, header_dir) conf = configuration_data() conf.set_quoted('VERSION', gclue_version) conf.set_quoted('PACKAGE_VERSION', gclue_version) conf.set_quoted('PACKAGE_NAME', 'geoclue') conf.set_quoted('GETTEXT_PACKAGE', 'geoclue') conf.set_quoted('PACKAGE_TARNAME', 'geoclue') conf.set_quoted('PACKAGE_STRING', 'geoclue ' + gclue_version) conf.set_quoted('PACKAGE_URL', 'http://www.freedesktop.org/wiki/Software/GeoClue') conf.set_quoted('PACKAGE_BUGREPORT', 'http://bugs.freedesktop.org/enter_bug.cgi?product=GeoClue') conf.set_quoted('TEST_SRCDIR', meson.source_root() + '/data/') conf.set_quoted('LOCALEDIR', localedir) conf.set_quoted('SYSCONFDIR', sysconfdir) conf.set10('GCLUE_USE_3G_SOURCE', get_option('3g-source')) conf.set10('GCLUE_USE_CDMA_SOURCE', get_option('cdma-source')) conf.set10('GCLUE_USE_MODEM_GPS_SOURCE', get_option('modem-gps-source')) conf.set10('GCLUE_USE_NMEA_SOURCE', get_option('nmea-source')) configure_file(output: 'config.h', configuration : conf) configinc = include_directories('.') gnome = import('gnome') cc = meson.get_compiler('c') base_deps = [ dependency('glib-2.0', version: '>= 2.44.0'), dependency('gio-2.0', version: '>= 2.44.0'), dependency('gio-unix-2.0', version: '>= 2.44.0') ] libm = cc.find_library('m', required: false) if libm.found() base_deps += [ libm ] endif subdir('public-api') if get_option('enable-backend') subdir('src') endif if get_option('libgeoclue') subdir('libgeoclue') endif subdir('data') subdir('demo') subdir('po') # FIXME: The D-Bus docs should not need libgeoclue but after a few hours of # banging my head agaist gtk-doc+meson and asking on IRC, I failed to find a # way to tell gtk-doc to link to the uninstalled public-api static library. A # non-working solution is in 'wip/fix-srv-docs' branch. # # If you look into this issue, you might also want to see how we can fix the # dependency issue that stops the user to run `ninja -C build geoclue-doc` # before `ninja -C build`. if get_option('gtk-doc') and get_option('libgeoclue') subdir('docs') endif # FIXME: Remove this once meson does it itself: https://github.com/mesonbuild/meson/issues/757 summary = ''' GeoClue @0@ ================= prefix: @1@ c compiler: @2@ Systemd system unit dir: @3@ Backend: @4@ Convenience library: @5@ Introspection: @6@ 3G source: @7@ CDMA source: @8@ Modem GPS source: @9@ Network NMEA source: @10@ '''.format(gclue_version, get_option('prefix'), cc.get_id(), systemd_unit_dir, get_option('enable-backend'), get_option('libgeoclue'), get_option('introspection'), get_option('3g-source'), get_option('cdma-source'), get_option('modem-gps-source'), get_option('nmea-source')) message(summary) geoclue-2.5.2/meson_options.txt000066400000000000000000000026751341441426700166200ustar00rootroot00000000000000option('libgeoclue', type: 'boolean', value: true, description: 'Enable convenience library') option('introspection', type: 'boolean', value: true, description: 'Enable convenience library introspection generation') option('gtk-doc', type: 'boolean', value: true, description: 'Whether to generate the API reference for Geocode-GLib') option('3g-source', type: 'boolean', value: true, description: 'Enable 3G source (requires ModemManager') option('cdma-source', type: 'boolean', value: true, description: 'Enable CDMA source (requires ModemManager') option('modem-gps-source', type: 'boolean', value: true, description: 'Enable modem GPS source (requires ModemManager') option('nmea-source', type: 'boolean', value: true, description: 'Enable network NMEA source (requires Avahi libraries)') option('enable-backend', type: 'boolean', value: true, description: 'Enable backend (the geoclue service)') option('demo-agent', type: 'boolean', value: true, description: 'Build demo agent') option('dbus-sys-dir', type: 'string', description: 'where D-BUS system.d directory is') option('systemd-system-unit-dir', type: 'string', description: 'Directory for systemd service files') option('dbus-srv-user', type: 'string', value: 'root', description: 'The user (existing) as which the service will run') geoclue-2.5.2/po/000077500000000000000000000000001341441426700135675ustar00rootroot00000000000000geoclue-2.5.2/po/LINGUAS000066400000000000000000000000001341441426700146020ustar00rootroot00000000000000geoclue-2.5.2/po/POTFILES.in000066400000000000000000000002271341441426700153450ustar00rootroot00000000000000demo/agent.c demo/gclue-service-agent.c demo/where-am-i.c demo/geoclue-demo-agent.desktop.in.in demo/geoclue-where-am-i.desktop.in.in src/gclue-main.c geoclue-2.5.2/po/POTFILES.skip000066400000000000000000000002241341441426700157020ustar00rootroot00000000000000demo/geoclue-demo-agent.desktop.in demo/geoclue-where-am-i.desktop.in sub/demo/geoclue-demo-agent.desktop.in sub/demo/geoclue-where-am-i.desktop.in geoclue-2.5.2/po/meson.build000066400000000000000000000002301341441426700157240ustar00rootroot00000000000000api_name = meson.project_name() + '-' + gclue_api_version gettext_domain = api_name i18n = import('i18n') i18n.gettext(gettext_domain, preset: 'glib') geoclue-2.5.2/public-api/000077500000000000000000000000001341441426700151765ustar00rootroot00000000000000geoclue-2.5.2/public-api/gclue-enums.c000066400000000000000000000030711341441426700175670ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-enum.c * * Copyright 2018 Collabora Ltd. * * 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.1 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, see * . * * Author: Zeeshan Ali */ #include "gclue-enum-types.h" /** * gclue_accuracy_level_get_string: * @val: a GClueAccuracyLevel. * * Gets the nickname string for the #GClueAccuracyLevel specified at @val. * * Returns: (transfer none): a string with the nickname, or %NULL if not found. Do not free the returned value. */ const char * gclue_accuracy_level_get_string (GClueAccuracyLevel val) { static GEnumClass *enum_class = NULL; GEnumValue *value; if (enum_class == NULL) { enum_class = g_type_class_ref (GCLUE_TYPE_ACCURACY_LEVEL); g_return_val_if_fail (enum_class != NULL, NULL); } value = g_enum_get_value (enum_class, val); if (value == NULL) return NULL; /* Leaking enum_class ref on purpose here */ return value->value_nick; } geoclue-2.5.2/public-api/gclue-enums.h000066400000000000000000000034421341441426700175760ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-enum.h * * Copyright 2013 Red Hat, Inc. * * 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.1 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, see * . * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_ENUMS_H #define GCLUE_ENUMS_H #include G_BEGIN_DECLS /** * GClueAccuracyLevel: * @GCLUE_ACCURACY_LEVEL_NONE: Accuracy level unknown or unset. * @GCLUE_ACCURACY_LEVEL_COUNTRY: Country-level accuracy. * @GCLUE_ACCURACY_LEVEL_CITY: City-level accuracy. * @GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD: neighborhood-level accuracy. * @GCLUE_ACCURACY_LEVEL_STREET: Street-level accuracy. * @GCLUE_ACCURACY_LEVEL_EXACT: Exact accuracy. Typically requires GPS receiver. * * Used to specify level of accuracy requested by, or allowed for a client. **/ typedef enum {/*< underscore_name=gclue_accuracy_level>*/ GCLUE_ACCURACY_LEVEL_NONE = 0, GCLUE_ACCURACY_LEVEL_COUNTRY = 1, GCLUE_ACCURACY_LEVEL_CITY = 4, GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD = 5, GCLUE_ACCURACY_LEVEL_STREET = 6, GCLUE_ACCURACY_LEVEL_EXACT = 8, } GClueAccuracyLevel; const char *gclue_accuracy_level_get_string (GClueAccuracyLevel val); G_END_DECLS #endif /* GCLUE_ENUMS_H */ geoclue-2.5.2/public-api/meson.build000066400000000000000000000013511341441426700173400ustar00rootroot00000000000000headers = [ 'gclue-enums.h' ] install_headers(headers, subdir: header_dir) libgeoclue_public_api_gen_sources = gnome.mkenums_simple( 'gclue-enum-types', sources: headers, header_prefix: '#include ', decorator : 'GCLUE_ENUMS_H', install_header: true, install_dir: include_subdir) libgeoclue_public_api_sources = [ libgeoclue_public_api_gen_sources, 'gclue-enums.c' ] libgeoclue_public_api_inc = include_directories('.') libgeoclue_public_api = static_library('geoclue-public-api', libgeoclue_public_api_sources, dependencies: base_deps, install: false) geoclue-2.5.2/src/000077500000000000000000000000001341441426700137405ustar00rootroot00000000000000geoclue-2.5.2/src/agent/000077500000000000000000000000001341441426700150365ustar00rootroot00000000000000geoclue-2.5.2/src/agent/meson.build000066400000000000000000000012361341441426700172020ustar00rootroot00000000000000libgeoclue_agent_sources = gnome.gdbus_codegen( 'geoclue-agent-interface', 'org.freedesktop.GeoClue2.Agent.xml', interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClue', docbook: 'docs') libgeoclue_agent_inc = include_directories('.', '../..') libgeoclue_agent = static_library('geoclue-agent', libgeoclue_agent_sources, dependencies: base_deps, include_directories: libgeoclue_agent_inc, install: false) install_data('org.freedesktop.GeoClue2.Agent.xml', install_dir: dbus_interface_dir) geoclue-2.5.2/src/agent/org.freedesktop.GeoClue2.Agent.xml000066400000000000000000000036511341441426700233270ustar00rootroot00000000000000 geoclue-2.5.2/src/create-unified-xml.py000077500000000000000000000010531341441426700177760ustar00rootroot00000000000000#!/usr/bin/env python3 from xml.etree import ElementTree as et import sys # FIXME: This script looses the doc comments but it's not that big a deal since # we also install the individual interface XMLs and they have the docs. # We need at least one input and one output file path if len(sys.argv) < 3: print('Usage: OUTPUT_FILE INPUT_FILE..') sys.exit(-1) u = et.fromstring('') for x in sys.argv[2:]: d = et.parse(x) u.extend(d.getroot()) f = open(sys.argv[1], 'w') f.write(et.tostring(u, encoding="unicode")) f.close() geoclue-2.5.2/src/fi.w1.wpa_supplicant1.xml000066400000000000000000000023411341441426700205170ustar00rootroot00000000000000 geoclue-2.5.2/src/gclue-3g-tower.h000066400000000000000000000021121341441426700166510ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_3G_TOWER_H #define GCLUE_3G_TOWER_H G_BEGIN_DECLS typedef struct _GClue3GTower GClue3GTower; struct _GClue3GTower { guint mcc; guint mnc; gulong lac; gulong cell_id; }; G_END_DECLS #endif /* GCLUE_3G_TOWER_H */ geoclue-2.5.2/src/gclue-3g.c000066400000000000000000000244641341441426700155240ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include #include "gclue-3g.h" #include "gclue-modem-manager.h" #include "gclue-location.h" #include "gclue-mozilla.h" /** * SECTION:gclue-3g * @short_description: 3GPP-based geolocation * * Contains functions to get the geolocation based on 3GPP cell towers. **/ struct _GClue3GPrivate { GClueModem *modem; GCancellable *cancellable; gulong threeg_notify_id; GClue3GTower *tower; }; G_DEFINE_TYPE_WITH_CODE (GClue3G, gclue_3g, GCLUE_TYPE_WEB_SOURCE, G_ADD_PRIVATE (GClue3G)) static gboolean gclue_3g_start (GClueLocationSource *source); static gboolean gclue_3g_stop (GClueLocationSource *source); static SoupMessage * gclue_3g_create_query (GClueWebSource *web, GError **error); static SoupMessage * gclue_3g_create_submit_query (GClueWebSource *web, GClueLocation *location, GError **error); static GClueAccuracyLevel gclue_3g_get_available_accuracy_level (GClueWebSource *web, gboolean available); static GClueLocation * gclue_3g_parse_response (GClueWebSource *web, const char *xml, GError **error); static void on_3g_enabled (GObject *source_object, GAsyncResult *result, gpointer user_data) { GClue3G *source = GCLUE_3G (user_data); GError *error = NULL; if (!gclue_modem_enable_3g_finish (source->priv->modem, result, &error)) { g_warning ("Failed to enable 3GPP: %s", error->message); g_error_free (error); } } static void on_is_3g_available_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClue3G *source = GCLUE_3G (user_data); GClue3GPrivate *priv = source->priv; gclue_web_source_refresh (GCLUE_WEB_SOURCE (source)); if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (source)) && gclue_modem_get_is_3g_available (priv->modem)) gclue_modem_enable_3g (priv->modem, priv->cancellable, on_3g_enabled, source); } static GClueLocation * gclue_3g_parse_response (GClueWebSource *web, const char *content, GError **error) { return gclue_mozilla_parse_response (content, error); } static void gclue_3g_finalize (GObject *g3g) { GClue3G *source = (GClue3G *) g3g; GClue3GPrivate *priv = source->priv; G_OBJECT_CLASS (gclue_3g_parent_class)->finalize (g3g); g_cancellable_cancel (priv->cancellable); g_signal_handler_disconnect (priv->modem, priv->threeg_notify_id); priv->threeg_notify_id = 0; g_clear_object (&priv->modem); g_clear_object (&priv->cancellable); } static void gclue_3g_class_init (GClue3GClass *klass) { GClueWebSourceClass *web_class = GCLUE_WEB_SOURCE_CLASS (klass); GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *g3g_class = G_OBJECT_CLASS (klass); g3g_class->finalize = gclue_3g_finalize; source_class->start = gclue_3g_start; source_class->stop = gclue_3g_stop; web_class->create_query = gclue_3g_create_query; web_class->create_submit_query = gclue_3g_create_submit_query; web_class->parse_response = gclue_3g_parse_response; web_class->get_available_accuracy_level = gclue_3g_get_available_accuracy_level; } static void gclue_3g_init (GClue3G *source) { GClue3GPrivate *priv; source->priv = G_TYPE_INSTANCE_GET_PRIVATE ((source), GCLUE_TYPE_3G, GClue3GPrivate); priv = source->priv; priv->cancellable = g_cancellable_new (); priv->modem = gclue_modem_manager_get_singleton (); priv->threeg_notify_id = g_signal_connect (priv->modem, "notify::is-3g-available", G_CALLBACK (on_is_3g_available_notify), source); } static void on_3g_destroyed (gpointer data, GObject *where_the_object_was) { GClue3G **source = (GClue3G **) data; *source = NULL; } /** * gclue_3g_new: * * Get the #GClue3G singleton. * * Returns: (transfer full): a new ref to #GClue3G. Use g_object_unref() * when done. **/ GClue3G * gclue_3g_get_singleton (void) { static GClue3G *source = NULL; if (source == NULL) { source = g_object_new (GCLUE_TYPE_3G, NULL); g_object_weak_ref (G_OBJECT (source), on_3g_destroyed, &source); } else g_object_ref (source); return source; } static SoupMessage * gclue_3g_create_query (GClueWebSource *web, GError **error) { GClue3GPrivate *priv = GCLUE_3G (web)->priv; if (priv->tower == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, "3GPP cell tower info unavailable"); return NULL; /* Not initialized yet */ } return gclue_mozilla_create_query (NULL, priv->tower, error); } static SoupMessage * gclue_3g_create_submit_query (GClueWebSource *web, GClueLocation *location, GError **error) { GClue3GPrivate *priv = GCLUE_3G (web)->priv; if (priv->tower == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, "3GPP cell tower info unavailable"); return NULL; /* Not initialized yet */ } return gclue_mozilla_create_submit_query (location, NULL, priv->tower, error); } static GClueAccuracyLevel gclue_3g_get_available_accuracy_level (GClueWebSource *web, gboolean network_available) { if (gclue_modem_get_is_3g_available (GCLUE_3G (web)->priv->modem) && network_available) return GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD; else return GCLUE_ACCURACY_LEVEL_NONE; } static void on_fix_3g (GClueModem *modem, guint mcc, guint mnc, gulong lac, gulong cell_id, gpointer user_data) { GClue3GPrivate *priv = GCLUE_3G (user_data)->priv; if (priv->tower == NULL) priv->tower = g_slice_new0 (GClue3GTower); priv->tower->mcc = mcc; priv->tower->mnc = mnc; priv->tower->lac = lac; priv->tower->cell_id = cell_id; gclue_web_source_refresh (GCLUE_WEB_SOURCE (user_data)); } static gboolean gclue_3g_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; GClue3GPrivate *priv; g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); priv = GCLUE_3G (source)->priv; base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_3g_parent_class); if (!base_class->start (source)) return FALSE; if (priv->tower != NULL) { g_slice_free (GClue3GTower, priv->tower); priv->tower = NULL; } g_signal_connect (priv->modem, "fix-3g", G_CALLBACK (on_fix_3g), source); if (gclue_modem_get_is_3g_available (priv->modem)) gclue_modem_enable_3g (priv->modem, priv->cancellable, on_3g_enabled, source); return TRUE; } static gboolean gclue_3g_stop (GClueLocationSource *source) { GClue3GPrivate *priv = GCLUE_3G (source)->priv; GClueLocationSourceClass *base_class; GError *error = NULL; g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_3g_parent_class); if (!base_class->stop (source)) return FALSE; g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modem), G_CALLBACK (on_fix_3g), source); if (gclue_modem_get_is_3g_available (priv->modem)) if (!gclue_modem_disable_3g (priv->modem, priv->cancellable, &error)) { g_warning ("Failed to disable 3GPP: %s", error->message); g_error_free (error); } return TRUE; } geoclue-2.5.2/src/gclue-3g.h000066400000000000000000000042531341441426700155230ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_3G_H #define GCLUE_3G_H #include #include #include "gclue-web-source.h" G_BEGIN_DECLS GType gclue_3g_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_3G (gclue_3g_get_type ()) #define GCLUE_3G(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_3G, GClue3G)) #define GCLUE_IS_3G(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_3G)) #define GCLUE_3G_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_3G, GClue3GClass)) #define GCLUE_IS_3G_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_3G)) #define GCLUE_3G_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_3G, GClue3GClass)) /** * GClue3G: * * All the fields in the #GClue3G structure are private and should never be accessed directly. **/ typedef struct _GClue3G GClue3G; typedef struct _GClue3GClass GClue3GClass; typedef struct _GClue3GPrivate GClue3GPrivate; struct _GClue3G { /* */ GClueWebSource parent_instance; GClue3GPrivate *priv; }; /** * GClue3GClass: * * All the fields in the #GClue3GClass structure are private and should never be accessed directly. **/ struct _GClue3GClass { /* */ GClueWebSourceClass parent_class; }; GClue3G * gclue_3g_get_singleton (void); G_END_DECLS #endif /* GCLUE_3G_H */ geoclue-2.5.2/src/gclue-cdma.c000066400000000000000000000200071341441426700161040ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include "gclue-cdma.h" #include "gclue-modem-manager.h" #include "gclue-location.h" /** * SECTION:gclue-cdma * @short_description: WiFi-based geolocation * @include: gclue-glib/gclue-cdma.h * * Contains functions to get the geolocation from a CDMA cell tower. **/ struct _GClueCDMAPrivate { GClueModem *modem; GCancellable *cancellable; gulong cdma_notify_id; }; G_DEFINE_TYPE_WITH_CODE (GClueCDMA, gclue_cdma, GCLUE_TYPE_LOCATION_SOURCE, G_ADD_PRIVATE (GClueCDMA)) static gboolean gclue_cdma_start (GClueLocationSource *source); static gboolean gclue_cdma_stop (GClueLocationSource *source); static void refresh_accuracy_level (GClueCDMA *source) { GClueAccuracyLevel new, existing; existing = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (source)); if (gclue_modem_get_is_cdma_available (source->priv->modem)) new = GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD; else new = GCLUE_ACCURACY_LEVEL_NONE; if (new != existing) { g_debug ("Available accuracy level from %s: %u", G_OBJECT_TYPE_NAME (source), new); g_object_set (G_OBJECT (source), "available-accuracy-level", new, NULL); } } static void on_cdma_enabled (GObject *source_object, GAsyncResult *result, gpointer user_data) { GClueCDMA *source = GCLUE_CDMA (user_data); GError *error = NULL; if (!gclue_modem_enable_cdma_finish (source->priv->modem, result, &error)) { g_warning ("Failed to enable CDMA: %s", error->message); g_error_free (error); } } static void on_is_cdma_available_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueCDMA *source = GCLUE_CDMA (user_data); GClueCDMAPrivate *priv = source->priv; refresh_accuracy_level (source); if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (source)) && gclue_modem_get_is_cdma_available (priv->modem)) gclue_modem_enable_cdma (priv->modem, priv->cancellable, on_cdma_enabled, source); } static void gclue_cdma_finalize (GObject *gcdma) { GClueCDMAPrivate *priv = GCLUE_CDMA (gcdma)->priv; G_OBJECT_CLASS (gclue_cdma_parent_class)->finalize (gcdma); g_signal_handler_disconnect (priv->modem, priv->cdma_notify_id); priv->cdma_notify_id = 0; g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); g_clear_object (&priv->modem); } static void gclue_cdma_class_init (GClueCDMAClass *klass) { GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *gcdma_class = G_OBJECT_CLASS (klass); gcdma_class->finalize = gclue_cdma_finalize; source_class->start = gclue_cdma_start; source_class->stop = gclue_cdma_stop; } static void gclue_cdma_init (GClueCDMA *source) { GClueCDMAPrivate *priv; source->priv = G_TYPE_INSTANCE_GET_PRIVATE ((source), GCLUE_TYPE_CDMA, GClueCDMAPrivate); priv = source->priv; priv->cancellable = g_cancellable_new (); priv->modem = gclue_modem_manager_get_singleton (); priv->cdma_notify_id = g_signal_connect (priv->modem, "notify::is-cdma-available", G_CALLBACK (on_is_cdma_available_notify), source); } static void on_cdma_destroyed (gpointer data, GObject *where_the_object_was) { GClueCDMA **source = (GClueCDMA **) data; *source = NULL; } /** * gclue_cdma_get_singleton: * * Get the #GClueCDMA singleton. * * Returns: (transfer full): a new ref to #GClueCDMA. Use g_object_unref() * when done. **/ GClueCDMA * gclue_cdma_get_singleton (void) { static GClueCDMA *source = NULL; if (source == NULL) { source = g_object_new (GCLUE_TYPE_CDMA, NULL); g_object_weak_ref (G_OBJECT (source), on_cdma_destroyed, &source); } else g_object_ref (source); return source; } static void on_fix_cdma (GClueModem *modem, gdouble latitude, gdouble longitude, gpointer user_data) { GClueLocation *location; location = gclue_location_new (latitude, longitude, 1000); /* Assume 1 km accuracy */ gclue_location_source_set_location (GCLUE_LOCATION_SOURCE (user_data), location); g_object_unref (location); } static gboolean gclue_cdma_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; GClueCDMAPrivate *priv; g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); priv = GCLUE_CDMA (source)->priv; base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_cdma_parent_class); if (!base_class->start (source)) return FALSE; g_signal_connect (priv->modem, "fix-cdma", G_CALLBACK (on_fix_cdma), source); if (gclue_modem_get_is_cdma_available (priv->modem)) gclue_modem_enable_cdma (priv->modem, priv->cancellable, on_cdma_enabled, source); return TRUE; } static gboolean gclue_cdma_stop (GClueLocationSource *source) { GClueCDMAPrivate *priv = GCLUE_CDMA (source)->priv; GClueLocationSourceClass *base_class; GError *error = NULL; g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_cdma_parent_class); if (!base_class->stop (source)) return FALSE; g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modem), G_CALLBACK (on_fix_cdma), source); if (gclue_modem_get_is_cdma_available (priv->modem)) if (!gclue_modem_disable_cdma (priv->modem, priv->cancellable, &error)) { g_warning ("Failed to disable CDMA: %s", error->message); g_error_free (error); } return TRUE; } geoclue-2.5.2/src/gclue-cdma.h000066400000000000000000000043761341441426700161240ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_CDMA_H #define GCLUE_CDMA_H #include #include #include "gclue-location-source.h" G_BEGIN_DECLS GType gclue_cdma_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_CDMA (gclue_cdma_get_type ()) #define GCLUE_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_CDMA, GClueCDMA)) #define GCLUE_IS_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_CDMA)) #define GCLUE_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_CDMA, GClueCDMAClass)) #define GCLUE_IS_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_CDMA)) #define GCLUE_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_CDMA, GClueCDMAClass)) /** * GClueCDMA: * * All the fields in the #GClueCDMA structure are private and should never be accessed directly. **/ typedef struct _GClueCDMA GClueCDMA; typedef struct _GClueCDMAClass GClueCDMAClass; typedef struct _GClueCDMAPrivate GClueCDMAPrivate; struct _GClueCDMA { /* */ GClueLocationSource parent_instance; GClueCDMAPrivate *priv; }; /** * GClueCDMAClass: * * All the fields in the #GClueCDMAClass structure are private and should never be accessed directly. **/ struct _GClueCDMAClass { /* */ GClueLocationSourceClass parent_class; }; GClueCDMA * gclue_cdma_get_singleton (void); G_END_DECLS #endif /* GCLUE_CDMA_H */ geoclue-2.5.2/src/gclue-client-info.c000066400000000000000000000352541341441426700174210ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-client-info.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include "gclue-client-info.h" #define MAX_CMDLINE_LEN 4096 static void gclue_client_info_async_initable_init (GAsyncInitableIface *iface); struct _GClueClientInfoPrivate { char *bus_name; GDBusConnection *connection; GDBusProxy *dbus_proxy; guint watch_id; guint32 user_id; char *xdg_id; }; G_DEFINE_TYPE_WITH_CODE (GClueClientInfo, gclue_client_info, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gclue_client_info_async_initable_init) G_ADD_PRIVATE (GClueClientInfo)); enum { PROP_0, PROP_PEER, PROP_CONNECTION, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; enum { PEER_VANISHED, SIGNAL_LAST }; static guint signals[SIGNAL_LAST]; static void gclue_client_info_finalize (GObject *object) { GClueClientInfoPrivate *priv = GCLUE_CLIENT_INFO (object)->priv; if (priv->watch_id != 0) { g_bus_unwatch_name (priv->watch_id); priv->watch_id = 0; } g_clear_pointer (&priv->bus_name, g_free); g_clear_pointer (&priv->xdg_id, g_free); g_clear_object (&priv->connection); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_client_info_parent_class)->finalize (object); } static void gclue_client_info_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueClientInfo *info = GCLUE_CLIENT_INFO (object); switch (prop_id) { case PROP_PEER: g_value_set_string (value, info->priv->bus_name); break; case PROP_CONNECTION: g_value_set_object (value, info->priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_client_info_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueClientInfo *info = GCLUE_CLIENT_INFO (object); switch (prop_id) { case PROP_PEER: info->priv->bus_name = g_value_dup_string (value); break; case PROP_CONNECTION: info->priv->connection = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_client_info_class_init (GClueClientInfoClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_client_info_finalize; object_class->get_property = gclue_client_info_get_property; object_class->set_property = gclue_client_info_set_property; gParamSpecs[PROP_PEER] = g_param_spec_string ("bus-name", "BusName", "Bus name of client", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_PEER, gParamSpecs[PROP_PEER]); gParamSpecs[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", "DBus Connection", G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, gParamSpecs[PROP_CONNECTION]); signals[PEER_VANISHED] = g_signal_new ("peer-vanished", GCLUE_TYPE_CLIENT_INFO, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GClueClientInfoClass, peer_vanished), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); } static void on_name_vanished (GDBusConnection *connection, const gchar *name, gpointer user_data) { g_signal_emit (GCLUE_CLIENT_INFO (user_data), signals[PEER_VANISHED], 0); } /* Based on got_credentials_cb() from xdg-app source code */ static char * get_xdg_id (guint32 pid) { char *xdg_id = NULL; g_autofree char *path = NULL; g_autofree char *content = NULL; gchar **lines; int i; path = g_strdup_printf ("/proc/%u/cgroup", pid); if (!g_file_get_contents (path, &content, NULL, NULL)) return NULL; lines = g_strsplit (content, "\n", -1); for (i = 0; lines[i] != NULL; i++) { const char *unit = lines[i] + strlen ("1:name=systemd:"); g_autofree char *scope = NULL; const char *name; char *dash; if (!g_str_has_prefix (lines[i], "1:name=systemd:")) continue; scope = g_path_get_basename (unit); if ((!g_str_has_prefix (scope, "xdg-app-") && !g_str_has_prefix (scope, "flatpak-")) || !g_str_has_suffix (scope, ".scope")) break; /* strlen("flatpak-") == strlen("xdg-app-") * so all is good here */ name = scope + strlen("xdg-app-"); dash = strchr (name, '-'); if (dash == NULL) break; *dash = 0; xdg_id = g_strdup (name); } g_strfreev (lines); return xdg_id; } static void on_get_pid_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); gpointer *info = g_task_get_source_object (task); GClueClientInfoPrivate *priv = GCLUE_CLIENT_INFO (info)->priv; guint32 pid; GError *error = NULL; GVariant *results = NULL; results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (results == NULL) { g_task_return_error (task, error); g_object_unref (task); return; } g_assert (g_variant_n_children (results) > 0); g_variant_get_child (results, 0, "u", &pid); g_variant_unref (results); priv->xdg_id = get_xdg_id (pid); priv->watch_id = g_bus_watch_name_on_connection (priv->connection, priv->bus_name, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, on_name_vanished, info, NULL); g_task_return_boolean (task, TRUE); g_object_unref (task); } static void on_get_user_id_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); gpointer *info = g_task_get_source_object (task); GClueClientInfoPrivate *priv = GCLUE_CLIENT_INFO (info)->priv; GError *error = NULL; GVariant *results = NULL; results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (results == NULL) { g_task_return_error (task, error); g_object_unref (task); return; } g_assert (g_variant_n_children (results) > 0); g_variant_get_child (results, 0, "u", &priv->user_id); g_variant_unref (results); g_dbus_proxy_call (priv->dbus_proxy, "GetConnectionUnixProcessID", g_variant_new ("(s)", priv->bus_name), G_DBUS_CALL_FLAGS_NONE, -1, g_task_get_cancellable (task), on_get_pid_ready, task); } static void on_dbus_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); gpointer *info = g_task_get_source_object (task); GClueClientInfoPrivate *priv = GCLUE_CLIENT_INFO (info)->priv; GError *error = NULL; priv->dbus_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (priv->dbus_proxy == NULL) { g_task_return_error (task, error); g_object_unref (task); return; } g_dbus_proxy_call (priv->dbus_proxy, "GetConnectionUnixUser", g_variant_new ("(s)", priv->bus_name), G_DBUS_CALL_FLAGS_NONE, -1, g_task_get_cancellable (task), on_get_user_id_ready, task); } static void gclue_client_info_init_async (GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; task = g_task_new (initable, cancellable, callback, user_data); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", cancellable, on_dbus_proxy_ready, task); } static gboolean gclue_client_info_init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) { return g_task_propagate_boolean (G_TASK (result), error); } static void gclue_client_info_async_initable_init (GAsyncInitableIface *iface) { iface->init_async = gclue_client_info_init_async; iface->init_finish = gclue_client_info_init_finish; } static void gclue_client_info_init (GClueClientInfo *info) { info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info, GCLUE_TYPE_CLIENT_INFO, GClueClientInfoPrivate); } void gclue_client_info_new_async (const char *bus_name, GDBusConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async (GCLUE_TYPE_CLIENT_INFO, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "bus-name", bus_name, "connection", connection, NULL); } GClueClientInfo * gclue_client_info_new_finish (GAsyncResult *res, GError **error) { GObject *object; GObject *source_object; source_object = g_async_result_get_source_object (res); object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); g_object_unref (source_object); if (object != NULL) return GCLUE_CLIENT_INFO (object); else return NULL; } const gchar * gclue_client_info_get_bus_name (GClueClientInfo *info) { g_return_val_if_fail (GCLUE_IS_CLIENT_INFO(info), NULL); return info->priv->bus_name; } guint32 gclue_client_info_get_user_id (GClueClientInfo *info) { g_return_val_if_fail (GCLUE_IS_CLIENT_INFO(info), 0); return info->priv->user_id; } gboolean gclue_client_info_check_bus_name (GClueClientInfo *info, const char *bus_name) { g_return_val_if_fail (GCLUE_IS_CLIENT_INFO(info), FALSE); return (strcmp (bus_name, info->priv->bus_name) == 0); } const char * gclue_client_info_get_xdg_id (GClueClientInfo *info) { g_return_val_if_fail (GCLUE_IS_CLIENT_INFO(info), FALSE); return info->priv->xdg_id; } geoclue-2.5.2/src/gclue-client-info.h000066400000000000000000000063271341441426700174250ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-client.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_CLIENT_INFO_H #define GCLUE_CLIENT_INFO_H #include #include G_BEGIN_DECLS #define GCLUE_TYPE_CLIENT_INFO (gclue_client_info_get_type()) #define GCLUE_CLIENT_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_CLIENT_INFO, GClueClientInfo)) #define GCLUE_CLIENT_INFO_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_CLIENT_INFO, GClueClientInfo const)) #define GCLUE_CLIENT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_CLIENT_INFO, GClueClientInfoClass)) #define GCLUE_IS_CLIENT_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_CLIENT_INFO)) #define GCLUE_IS_CLIENT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_CLIENT_INFO)) #define GCLUE_CLIENT_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_CLIENT_INFO, GClueClientInfoClass)) typedef struct _GClueClientInfo GClueClientInfo; typedef struct _GClueClientInfoClass GClueClientInfoClass; typedef struct _GClueClientInfoPrivate GClueClientInfoPrivate; struct _GClueClientInfo { GObject parent; /*< private >*/ GClueClientInfoPrivate *priv; }; struct _GClueClientInfoClass { GObjectClass parent_class; /* signals */ void (* peer_vanished) (GClueClientInfo *info); }; GType gclue_client_info_get_type (void) G_GNUC_CONST; void gclue_client_info_new_async (const char *bus_name, GDBusConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GClueClientInfo * gclue_client_info_new_finish (GAsyncResult *res, GError **error); const char * gclue_client_info_get_bus_name (GClueClientInfo *info); guint32 gclue_client_info_get_user_id (GClueClientInfo *info); gboolean gclue_client_info_check_bus_name (GClueClientInfo *info, const char *bus_name); const char * gclue_client_info_get_xdg_id (GClueClientInfo *info); G_END_DECLS #endif /* GCLUE_CLIENT_INFO_H */ geoclue-2.5.2/src/gclue-compass.c000066400000000000000000000221011341441426700166420ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include "gclue-compass.h" #include "gclue-location.h" #include "compass-interface.h" /** * SECTION:gclue-compass * @short_description: IIO compass support * @include: gclue-glib/gclue-compass.h **/ struct _GClueCompassPrivate { Compass *proxy; GCancellable *cancellable; }; G_DEFINE_TYPE_WITH_CODE (GClueCompass, gclue_compass, G_TYPE_OBJECT, G_ADD_PRIVATE (GClueCompass)) enum { PROP_0, PROP_HEADING, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static void gclue_compass_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueCompass *compass = GCLUE_COMPASS (object); switch (prop_id) { case PROP_HEADING: g_value_set_double (value, gclue_compass_get_heading (compass)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_compass_finalize (GObject *object) { GClueCompassPrivate *priv = GCLUE_COMPASS (object)->priv; g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); if (priv->proxy != NULL) { GError *error = NULL; if (!compass_call_release_compass_sync (priv->proxy, NULL, &error)) { g_warning ("Failed to release compass: %s", error->message); g_error_free (error); } g_debug ("IIO compass released"); g_object_unref (priv->proxy); } G_OBJECT_CLASS (gclue_compass_parent_class)->finalize (object); } static void gclue_compass_class_init (GClueCompassClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->get_property = gclue_compass_get_property; object_class->finalize = gclue_compass_finalize; /** * GClueCompass:heading * * The positive angle between the direction of movement and the North * direction, in clockwise direction. The angle is measured in degrees. */ gParamSpecs[PROP_HEADING] = g_param_spec_double ("heading", "Heading", "The positive angle between the direction" " of movement and the North direction, in" " clockwise direction. The angle is " "measured in degrees.", GCLUE_LOCATION_HEADING_UNKNOWN, G_MAXDOUBLE, GCLUE_LOCATION_HEADING_UNKNOWN, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_HEADING, gParamSpecs[PROP_HEADING]); } static void on_compass_heading_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { g_object_notify_by_pspec (G_OBJECT (user_data), gParamSpecs[PROP_HEADING]); } static void on_compass_claimed (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueCompass *compass; Compass *proxy = COMPASS (source_object); GError *error = NULL; if (!compass_call_claim_compass_finish (proxy, res, &error)) { if (error->code != G_IO_ERROR_CANCELLED) g_debug ("Failed to claim IIO proxy compass: %s", error->message); g_error_free (error); g_object_unref (proxy); return; } g_debug ("IIO compass claimed"); compass = GCLUE_COMPASS (user_data); compass->priv->proxy = proxy; g_object_notify_by_pspec (G_OBJECT (compass), gParamSpecs[PROP_HEADING]); g_signal_connect_object (G_OBJECT (proxy), "notify::compass-heading", G_CALLBACK (on_compass_heading_changed), compass, G_CONNECT_AFTER); } static void on_compass_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueCompass *compass; Compass *proxy; GError *error = NULL; proxy = compass_proxy_new_for_bus_finish (res, &error); if (proxy == NULL) { if (error->code != G_IO_ERROR_CANCELLED) g_debug ("Failed to connect to IIO compass proxy: %s", error->message); g_error_free (error); return; } compass = GCLUE_COMPASS (user_data); compass_call_claim_compass (proxy, compass->priv->cancellable, on_compass_claimed, compass); } static void gclue_compass_init (GClueCompass *compass) { compass->priv = G_TYPE_INSTANCE_GET_PRIVATE (compass, GCLUE_TYPE_COMPASS, GClueCompassPrivate); compass->priv->cancellable = g_cancellable_new (); compass_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, "net.hadess.SensorProxy", "/net/hadess/SensorProxy/Compass", compass->priv->cancellable, on_compass_proxy_ready, compass); } static void on_compass_destroyed (gpointer data, GObject *where_the_object_was) { GClueCompass **compass = (GClueCompass **) data; *compass = NULL; } /** * gclue_compass_get_singleton: * * Get the #GClueCompass singleton. * * Returns: (transfer full): a new ref to #GClueCompass. Use g_object_unref() * when done. **/ GClueCompass * gclue_compass_get_singleton (void) { static GClueCompass *compass = NULL; if (compass == NULL) { compass = g_object_new (GCLUE_TYPE_COMPASS, NULL); g_object_weak_ref (G_OBJECT (compass), on_compass_destroyed, &compass); } else g_object_ref (compass); return compass; } /** * gclue_compass_get_heading: * @compass: a #GClueCompass * * Gets the positive angle between direction of movement and North direction. * The angle is measured in degrees. * * Returns: The heading, or %GCLUE_LOCATION_HEADING_UNKNOWN if heading is * unknown. **/ gdouble gclue_compass_get_heading (GClueCompass *compass) { gdouble ret = GCLUE_LOCATION_HEADING_UNKNOWN; g_return_val_if_fail (GCLUE_IS_COMPASS (compass), ret); if (compass->priv->proxy == NULL) return GCLUE_LOCATION_HEADING_UNKNOWN; /* FIXME: * * IIO compass gives us raw magnetic heading so we need to translate it * to true heading here. Some pointers on that from elad: * * A Python implementation: * https://github.com/cmweiss/geomag/blob/master/geomag/geomag/geomag.py * * It seems to use the magnetic model from NOAA: * http://www.ngdc.noaa.gov/geomag/WMM/ * * C implementation: http://www.ngdc.noaa.gov/geomag/WMM/soft.shtml */ ret = compass_get_compass_heading (compass->priv->proxy); if (ret >= 0) return ret; else return GCLUE_LOCATION_HEADING_UNKNOWN; } geoclue-2.5.2/src/gclue-compass.h000066400000000000000000000042151341441426700166550ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2015 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_COMPASS_H #define GCLUE_COMPASS_H #include #include G_BEGIN_DECLS #define GCLUE_TYPE_COMPASS (gclue_compass_get_type()) #define GCLUE_COMPASS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_COMPASS, GClueCompass)) #define GCLUE_COMPASS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_COMPASS, GClueCompass const)) #define GCLUE_COMPASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_COMPASS, GClueCompassClass)) #define GCLUE_IS_COMPASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_COMPASS)) #define GCLUE_IS_COMPASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_COMPASS)) #define GCLUE_COMPASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_COMPASS, GClueCompassClass)) typedef struct _GClueCompass GClueCompass; typedef struct _GClueCompassClass GClueCompassClass; typedef struct _GClueCompassPrivate GClueCompassPrivate; struct _GClueCompass { GObject parent; /*< private >*/ GClueCompassPrivate *priv; }; struct _GClueCompassClass { GObjectClass parent_class; }; GType gclue_compass_get_type (void) G_GNUC_CONST; GClueCompass * gclue_compass_get_singleton (void); gdouble gclue_compass_get_heading (GClueCompass *compass); G_END_DECLS #endif /* GCLUE_COMPASS_H */ geoclue-2.5.2/src/gclue-config.c000066400000000000000000000352561341441426700164610ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-config.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include "gclue-config.h" #define CONFIG_FILE_PATH SYSCONFDIR "/geoclue/geoclue.conf" /* This class will be responsible for fetching configuration. */ struct _GClueConfigPrivate { GKeyFile *key_file; char **agents; gsize num_agents; char *wifi_url; gboolean wifi_submit; gboolean enable_nmea_source; gboolean enable_3g_source; gboolean enable_cdma_source; gboolean enable_modem_gps_source; gboolean enable_wifi_source; char *wifi_submit_url; char *wifi_submit_nick; GList *app_configs; }; G_DEFINE_TYPE_WITH_CODE (GClueConfig, gclue_config, G_TYPE_OBJECT, G_ADD_PRIVATE (GClueConfig)) typedef struct { char *id; gboolean allowed; gboolean system; int* users; gsize num_users; } AppConfig; static void app_config_free (AppConfig *app_config) { g_free (app_config->id); g_free (app_config->users); g_slice_free (AppConfig, app_config); } static void gclue_config_finalize (GObject *object) { GClueConfigPrivate *priv; priv = GCLUE_CONFIG (object)->priv; g_clear_pointer (&priv->key_file, g_key_file_unref); g_clear_pointer (&priv->agents, g_strfreev); g_clear_pointer (&priv->wifi_url, g_free); g_clear_pointer (&priv->wifi_submit_url, g_free); g_clear_pointer (&priv->wifi_submit_nick, g_free); g_list_foreach (priv->app_configs, (GFunc) app_config_free, NULL); G_OBJECT_CLASS (gclue_config_parent_class)->finalize (object); } static void gclue_config_class_init (GClueConfigClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_config_finalize; } static void load_agent_config (GClueConfig *config) { GClueConfigPrivate *priv = config->priv; GError *error = NULL; priv->agents = g_key_file_get_string_list (priv->key_file, "agent", "whitelist", &priv->num_agents, &error); if (error != NULL) { g_critical ("Failed to read 'agent/whitelist' key: %s", error->message); g_error_free (error); } } static void load_app_configs (GClueConfig *config) { const char *known_groups[] = { "agent", "wifi", "3g", "cdma", "modem-gps", "network-nmea", NULL }; GClueConfigPrivate *priv = config->priv; gsize num_groups = 0, i; char **groups; groups = g_key_file_get_groups (priv->key_file, &num_groups); if (num_groups == 0) return; for (i = 0; i < num_groups; i++) { AppConfig *app_config; int* users; gsize num_users = 0, j; gboolean allowed, system; gboolean ignore = FALSE; GError *error = NULL; for (j = 0; known_groups[j] != NULL; j++) if (strcmp (groups[i], known_groups[j]) == 0) { ignore = TRUE; continue; } if (ignore) continue; allowed = g_key_file_get_boolean (priv->key_file, groups[i], "allowed", &error); if (error != NULL) goto error_out; system = g_key_file_get_boolean (priv->key_file, groups[i], "system", &error); if (error != NULL) goto error_out; users = g_key_file_get_integer_list (priv->key_file, groups[i], "users", &num_users, &error); if (error != NULL) goto error_out; app_config = g_slice_new0 (AppConfig); app_config->id = g_strdup (groups[i]); app_config->allowed = allowed; app_config->system = system; app_config->users = users; app_config->num_users = num_users; priv->app_configs = g_list_prepend (priv->app_configs, app_config); continue; error_out: g_warning ("Failed to load configuration for app '%s': %s", groups[i], error->message); g_error_free (error); } g_strfreev (groups); } static gboolean load_enable_source_config (GClueConfig *config, const char *source_name) { GClueConfigPrivate *priv = config->priv; GError *error = NULL; gboolean enable; enable = g_key_file_get_boolean (priv->key_file, source_name, "enable", &error); if (error != NULL) { g_debug ("Failed to get config %s/enable:" " %s", source_name, error->message); g_error_free (error); /* Source should be enabled by default */ return TRUE; } return enable; } #define DEFAULT_WIFI_URL "https://location.services.mozilla.com/v1/geolocate?key=geoclue" #define DEFAULT_WIFI_SUBMIT_URL "https://location.services.mozilla.com/v1/submit?key=geoclue" static void load_wifi_config (GClueConfig *config) { GClueConfigPrivate *priv = config->priv; GError *error = NULL; priv->enable_wifi_source = load_enable_source_config (config, "wifi"); priv->wifi_url = g_key_file_get_string (priv->key_file, "wifi", "url", &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); priv->wifi_url = g_strdup (DEFAULT_WIFI_URL); } priv->wifi_submit = g_key_file_get_boolean (priv->key_file, "wifi", "submit-data", &error); if (error != NULL) { g_debug ("Failed to get config wifi/submit-data: %s", error->message); g_error_free (error); return; } priv->wifi_submit_url = g_key_file_get_string (priv->key_file, "wifi", "submission-url", &error); if (error != NULL) { g_debug ("No wifi submission URL: %s", error->message); g_error_free (error); priv->wifi_submit_url = g_strdup (DEFAULT_WIFI_SUBMIT_URL); } priv->wifi_submit_nick = g_key_file_get_string (priv->key_file, "wifi", "submission-nick", &error); if (error != NULL) { g_debug ("No wifi submission nick: %s", error->message); g_error_free (error); } } static void load_3g_config (GClueConfig *config) { config->priv->enable_3g_source = load_enable_source_config (config, "3g"); } static void load_cdma_config (GClueConfig *config) { config->priv->enable_cdma_source = load_enable_source_config (config, "cdma"); } static void load_modem_gps_config (GClueConfig *config) { config->priv->enable_modem_gps_source = load_enable_source_config (config, "modem-gps"); } static void load_network_nmea_config (GClueConfig *config) { config->priv->enable_nmea_source = load_enable_source_config (config, "network-nmea"); } static void gclue_config_init (GClueConfig *config) { GError *error = NULL; config->priv = G_TYPE_INSTANCE_GET_PRIVATE (config, GCLUE_TYPE_CONFIG, GClueConfigPrivate); config->priv->key_file = g_key_file_new (); g_key_file_load_from_file (config->priv->key_file, CONFIG_FILE_PATH, 0, &error); if (error != NULL) { g_critical ("Failed to load configuration file '%s': %s", CONFIG_FILE_PATH, error->message); g_error_free (error); return; } load_agent_config (config); load_app_configs (config); load_wifi_config (config); load_3g_config (config); load_cdma_config (config); load_modem_gps_config (config); load_network_nmea_config (config); } GClueConfig * gclue_config_get_singleton (void) { static GClueConfig *config = NULL; if (config == NULL) config = g_object_new (GCLUE_TYPE_CONFIG, NULL); return config; } gboolean gclue_config_is_agent_allowed (GClueConfig *config, const char *desktop_id, GClueClientInfo *agent_info) { gsize i; for (i = 0; i < config->priv->num_agents; i++) { if (g_strcmp0 (desktop_id, config->priv->agents[i]) == 0) return TRUE; } return FALSE; } gsize gclue_config_get_num_allowed_agents (GClueConfig *config) { return config->priv->num_agents; } GClueAppPerm gclue_config_get_app_perm (GClueConfig *config, const char *desktop_id, GClueClientInfo *app_info) { GClueConfigPrivate *priv = config->priv; GList *node; AppConfig *app_config = NULL; gsize i; guint64 uid; g_return_val_if_fail (desktop_id != NULL, GCLUE_APP_PERM_DISALLOWED); for (node = priv->app_configs; node != NULL; node = node->next) { if (strcmp (((AppConfig *) node->data)->id, desktop_id) == 0) { app_config = (AppConfig *) node->data; break; } } if (app_config == NULL) { g_debug ("'%s' not in configuration", desktop_id); return GCLUE_APP_PERM_ASK_AGENT; } if (!app_config->allowed) { g_debug ("'%s' disallowed by configuration", desktop_id); return GCLUE_APP_PERM_DISALLOWED; } if (app_config->num_users == 0) return GCLUE_APP_PERM_ALLOWED; uid = gclue_client_info_get_user_id (app_info); for (i = 0; i < app_config->num_users; i++) { if (app_config->users[i] == uid) return GCLUE_APP_PERM_ALLOWED; } return GCLUE_APP_PERM_DISALLOWED; } gboolean gclue_config_is_system_component (GClueConfig *config, const char *desktop_id) { GClueConfigPrivate *priv = config->priv; GList *node; AppConfig *app_config = NULL; g_return_val_if_fail (desktop_id != NULL, FALSE); for (node = priv->app_configs; node != NULL; node = node->next) { if (strcmp (((AppConfig *) node->data)->id, desktop_id) == 0) { app_config = (AppConfig *) node->data; break; } } return (app_config != NULL && app_config->system); } const char * gclue_config_get_wifi_url (GClueConfig *config) { return config->priv->wifi_url; } const char * gclue_config_get_wifi_submit_url (GClueConfig *config) { return config->priv->wifi_submit_url; } const char * gclue_config_get_wifi_submit_nick (GClueConfig *config) { return config->priv->wifi_submit_nick; } void gclue_config_set_wifi_submit_nick (GClueConfig *config, const char *nick) { config->priv->wifi_submit_nick = g_strdup (nick); } gboolean gclue_config_get_wifi_submit_data (GClueConfig *config) { return config->priv->wifi_submit; } gboolean gclue_config_get_enable_wifi_source (GClueConfig *config) { return config->priv->enable_wifi_source; } gboolean gclue_config_get_enable_3g_source (GClueConfig *config) { return config->priv->enable_3g_source; } gboolean gclue_config_get_enable_modem_gps_source (GClueConfig *config) { return config->priv->enable_modem_gps_source; } gboolean gclue_config_get_enable_cdma_source (GClueConfig *config) { return config->priv->enable_cdma_source; } gboolean gclue_config_get_enable_nmea_source (GClueConfig *config) { return config->priv->enable_nmea_source; } void gclue_config_set_wifi_submit_data (GClueConfig *config, gboolean submit) { config->priv->wifi_submit = submit; } geoclue-2.5.2/src/gclue-config.h000066400000000000000000000101771341441426700164610ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-config.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_CONFIG_H #define GCLUE_CONFIG_H #include #include "gclue-location.h" #include "gclue-client-info.h" #include "gclue-config.h" G_BEGIN_DECLS #define GCLUE_TYPE_CONFIG (gclue_config_get_type()) #define GCLUE_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_CONFIG, GClueConfig)) #define GCLUE_CONFIG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_CONFIG, GClueConfig const)) #define GCLUE_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_CONFIG, GClueConfigClass)) #define GCLUE_IS_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_CONFIG)) #define GCLUE_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_CONFIG)) #define GCLUE_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_CONFIG, GClueConfigClass)) typedef enum { GCLUE_APP_PERM_ALLOWED, GCLUE_APP_PERM_DISALLOWED, GCLUE_APP_PERM_ASK_AGENT } GClueAppPerm; typedef struct _GClueConfig GClueConfig; typedef struct _GClueConfigClass GClueConfigClass; typedef struct _GClueConfigPrivate GClueConfigPrivate; struct _GClueConfig { GObject parent; /*< private >*/ GClueConfigPrivate *priv; }; struct _GClueConfigClass { GObjectClass parent_class; }; GType gclue_config_get_type (void) G_GNUC_CONST; GClueConfig * gclue_config_get_singleton (void); gboolean gclue_config_is_agent_allowed (GClueConfig *config, const char *desktop_id, GClueClientInfo *agent_info); gsize gclue_config_get_num_allowed_agents (GClueConfig *config); GClueAppPerm gclue_config_get_app_perm (GClueConfig *config, const char *desktop_id, GClueClientInfo *app_info); gboolean gclue_config_is_system_component (GClueConfig *config, const char *desktop_id); const char * gclue_config_get_wifi_url (GClueConfig *config); const char * gclue_config_get_wifi_submit_url (GClueConfig *config); const char * gclue_config_get_wifi_submit_nick (GClueConfig *config); void gclue_config_set_wifi_submit_nick (GClueConfig *config, const char *nick); gboolean gclue_config_get_wifi_submit_data (GClueConfig *config); gboolean gclue_config_get_enable_wifi_source (GClueConfig *config); gboolean gclue_config_get_enable_3g_source (GClueConfig *config); gboolean gclue_config_get_enable_cdma_source (GClueConfig *config); gboolean gclue_config_get_enable_modem_gps_source (GClueConfig *config); gboolean gclue_config_get_enable_nmea_source (GClueConfig *config); void gclue_config_set_wifi_submit_data (GClueConfig *config, gboolean submit); G_END_DECLS #endif /* GCLUE_CONFIG_H */ geoclue-2.5.2/src/gclue-error.c000066400000000000000000000024111341441426700163300ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-error.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Bastien Nocera */ #include "gclue-error.h" /** * SECTION:gclue-error * @short_description: Error helper functions * @include: gclue-glib/gclue-glib.h * * Contains helper functions for reporting errors to the user. **/ /** * gclue_error_quark: * * Gets the gclue-glib error quark. * * Return value: a #GQuark. **/ GQuark gclue_error_quark (void) { static GQuark quark; if (!quark) quark = g_quark_from_static_string ("gclue_error"); return quark; } geoclue-2.5.2/src/gclue-error.h000066400000000000000000000035041341441426700163410ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-error.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Bastien Nocera */ #ifndef GCLUE_ERROR_H #define GCLUE_ERROR_H #include G_BEGIN_DECLS /** * GCLUE_ERROR: * * Error domain for gclue-glib. Errors from this domain will be from * the #GClueError enumeration. * See #GError for more information on error domains. **/ #define GCLUE_ERROR (gclue_error_quark ()) /** * GClueError: * @GCLUE_ERROR_PARSE: An error occured parsing the response from the web service. * @GCLUE_ERROR_NOT_SUPPORTED: The request made was not supported. * @GCLUE_ERROR_NO_MATCHES: The requests made didn't have any matches. * @GCLUE_ERROR_INVALID_ARGUMENTS: The request made contained invalid arguments. * @GCLUE_ERROR_INTERNAL_SERVER: The server encountered an (possibly unrecoverable) internal error. * * Error codes returned by gclue-glib functions. **/ typedef enum { GCLUE_ERROR_PARSE, GCLUE_ERROR_NOT_SUPPORTED, GCLUE_ERROR_NO_MATCHES, GCLUE_ERROR_INVALID_ARGUMENTS, GCLUE_ERROR_INTERNAL_SERVER } GClueError; GQuark gclue_error_quark (void); G_END_DECLS #endif /* GCLUE_ERROR_H */ geoclue-2.5.2/src/gclue-location-source.c000066400000000000000000000434711341441426700203200ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include "gclue-location-source.h" #include "gclue-compass.h" /** * SECTION:gclue-location-source * @short_description: GeoIP client * @include: gclue-glib/gclue-location-source.h * * The interface all geolocation sources must implement. **/ static gboolean start_source (GClueLocationSource *source); static gboolean stop_source (GClueLocationSource *source); struct _GClueLocationSourcePrivate { GClueLocation *location; guint active_counter; GClueMinUINT *time_threshold; GClueAccuracyLevel avail_accuracy_level; gboolean compute_movement; gboolean scramble_location; GClueCompass *compass; guint heading_changed_id; }; G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GClueLocationSource, gclue_location_source, G_TYPE_OBJECT, G_ADD_PRIVATE (GClueLocationSource)) enum { PROP_0, PROP_LOCATION, PROP_ACTIVE, PROP_TIME_THRESHOLD, PROP_AVAILABLE_ACCURACY_LEVEL, PROP_COMPUTE_MOVEMENT, PROP_SCRAMBLE_LOCATION, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static gboolean set_heading_from_compass (GClueLocationSource *source, GClueLocation *location) { GClueLocationSourcePrivate *priv = source->priv; gdouble heading, curr_heading; if (priv->compass == NULL) return FALSE; heading = gclue_compass_get_heading (priv->compass); curr_heading = gclue_location_get_heading (location); if (heading == GCLUE_LOCATION_HEADING_UNKNOWN || heading == curr_heading) return FALSE; g_debug ("%s got new heading %f", G_OBJECT_TYPE_NAME (source), heading); /* We trust heading from compass more than any other source so we always * override existing heading */ gclue_location_set_heading (location, heading); return TRUE; } static void on_compass_heading_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueLocationSource* source = GCLUE_LOCATION_SOURCE (user_data); if (source->priv->location == NULL) return; if (set_heading_from_compass (source, source->priv->location)) g_object_notify (G_OBJECT (source), "location"); } static void gclue_location_source_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueLocationSource *source = GCLUE_LOCATION_SOURCE (object); switch (prop_id) { case PROP_LOCATION: g_value_set_object (value, source->priv->location); break; case PROP_ACTIVE: g_value_set_boolean (value, gclue_location_source_get_active (source)); break; case PROP_TIME_THRESHOLD: g_value_set_object (value, source->priv->time_threshold); break; case PROP_AVAILABLE_ACCURACY_LEVEL: g_value_set_enum (value, source->priv->avail_accuracy_level); break; case PROP_COMPUTE_MOVEMENT: g_value_set_boolean (value, source->priv->compute_movement); break; case PROP_SCRAMBLE_LOCATION: g_value_set_boolean (value, source->priv->scramble_location); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_location_source_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueLocationSource *source = GCLUE_LOCATION_SOURCE (object); switch (prop_id) { case PROP_LOCATION: { GClueLocation *location = g_value_get_object (value); gclue_location_source_set_location (source, location); break; } case PROP_AVAILABLE_ACCURACY_LEVEL: source->priv->avail_accuracy_level = g_value_get_enum (value); break; case PROP_COMPUTE_MOVEMENT: source->priv->compute_movement = g_value_get_boolean (value); break; case PROP_SCRAMBLE_LOCATION: source->priv->scramble_location = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_location_source_finalize (GObject *object) { GClueLocationSourcePrivate *priv = GCLUE_LOCATION_SOURCE (object)->priv; gclue_location_source_stop (GCLUE_LOCATION_SOURCE (object)); g_clear_object (&priv->location); G_OBJECT_CLASS (gclue_location_source_parent_class)->finalize (object); } static void gclue_location_source_class_init (GClueLocationSourceClass *klass) { GObjectClass *object_class; klass->start = start_source; klass->stop = stop_source; object_class = G_OBJECT_CLASS (klass); object_class->get_property = gclue_location_source_get_property; object_class->set_property = gclue_location_source_set_property; object_class->finalize = gclue_location_source_finalize; gParamSpecs[PROP_LOCATION] = g_param_spec_object ("location", "Location", "Location", GCLUE_TYPE_LOCATION, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_LOCATION, gParamSpecs[PROP_LOCATION]); gParamSpecs[PROP_ACTIVE] = g_param_spec_boolean ("active", "Active", "Active", FALSE, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_ACTIVE, gParamSpecs[PROP_ACTIVE]); gParamSpecs[PROP_TIME_THRESHOLD] = g_param_spec_object ("time-threshold", "TimeThreshold", "TimeThreshold", GCLUE_TYPE_MIN_UINT, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_TIME_THRESHOLD, gParamSpecs[PROP_TIME_THRESHOLD]); gParamSpecs[PROP_AVAILABLE_ACCURACY_LEVEL] = g_param_spec_enum ("available-accuracy-level", "AvailableAccuracyLevel", "Available accuracy level", GCLUE_TYPE_ACCURACY_LEVEL, 0, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_AVAILABLE_ACCURACY_LEVEL, gParamSpecs[PROP_AVAILABLE_ACCURACY_LEVEL]); gParamSpecs[PROP_COMPUTE_MOVEMENT] = g_param_spec_boolean ("compute-movement", "ComputeMovement", "Whether or not, speed and heading should " "be automatically computed (or fetched " "from hardware) and set on new locations.", TRUE, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_COMPUTE_MOVEMENT, gParamSpecs[PROP_COMPUTE_MOVEMENT]); gParamSpecs[PROP_SCRAMBLE_LOCATION] = g_param_spec_boolean ("scramble-location", "ScrambleLocation", "Enable location scrambling", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_SCRAMBLE_LOCATION, gParamSpecs[PROP_SCRAMBLE_LOCATION]); } static void gclue_location_source_init (GClueLocationSource *source) { source->priv = G_TYPE_INSTANCE_GET_PRIVATE (source, GCLUE_TYPE_LOCATION_SOURCE, GClueLocationSourcePrivate); source->priv->compute_movement = TRUE; source->priv->time_threshold = gclue_min_uint_new (); } static gboolean start_source (GClueLocationSource *source) { source->priv->active_counter++; if (source->priv->active_counter > 1) { g_debug ("%s already active, not starting.", G_OBJECT_TYPE_NAME (source)); return FALSE; } if (source->priv->compute_movement) { source->priv->compass = gclue_compass_get_singleton (); source->priv->heading_changed_id = g_signal_connect (G_OBJECT (source->priv->compass), "notify::heading", G_CALLBACK (on_compass_heading_changed), source); } g_object_notify (G_OBJECT (source), "active"); g_debug ("%s now active", G_OBJECT_TYPE_NAME (source)); return TRUE; } static gboolean stop_source (GClueLocationSource *source) { if (source->priv->active_counter == 0) { g_debug ("%s already inactive, not stopping.", G_OBJECT_TYPE_NAME (source)); return FALSE; } source->priv->active_counter--; if (source->priv->active_counter > 0) { g_debug ("%s still in use, not stopping.", G_OBJECT_TYPE_NAME (source)); return FALSE; } if (source->priv->compass) { g_signal_handler_disconnect (source->priv->compass, source->priv->heading_changed_id); g_clear_object (&source->priv->compass); } g_object_notify (G_OBJECT (source), "active"); g_debug ("%s now inactive", G_OBJECT_TYPE_NAME (source)); return TRUE; } /** * gclue_location_source_start: * @source: a #GClueLocationSource * * Start searching for location and keep an eye on location changes. **/ void gclue_location_source_start (GClueLocationSource *source) { g_return_if_fail (GCLUE_IS_LOCATION_SOURCE (source)); GCLUE_LOCATION_SOURCE_GET_CLASS (source)->start (source); } /** * gclue_location_source_stop: * @source: a #GClueLocationSource * * Stop searching for location and no need to keep an eye on location changes * anymore. **/ void gclue_location_source_stop (GClueLocationSource *source) { g_return_if_fail (GCLUE_IS_LOCATION_SOURCE (source)); GCLUE_LOCATION_SOURCE_GET_CLASS (source)->stop (source); } /** * gclue_location_source_get_location: * @source: a #GClueLocationSource * * Returns: (transfer none): The location, or NULL if unknown. **/ GClueLocation * gclue_location_source_get_location (GClueLocationSource *source) { g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), NULL); return source->priv->location; } /* 1 km in latitude is always .00899928005759539236 degrees */ #define LATITUDE_IN_KM .00899928005759539236 /** * gclue_location_source_set_location: * @source: a #GClueLocationSource * * Set the current location to @location. Its meant to be only used by * subclasses. **/ void gclue_location_source_set_location (GClueLocationSource *source, GClueLocation *location) { GClueLocationSourcePrivate *priv = source->priv; GClueLocation *cur_location; gdouble speed, heading; cur_location = priv->location; priv->location = gclue_location_duplicate (location); if (priv->scramble_location) { gdouble latitude, distance, accuracy; latitude = gclue_location_get_latitude (priv->location); accuracy = gclue_location_get_accuracy (priv->location); /* Randomization is needed to stop apps from calculationg the * actual location. */ distance = (gdouble) g_random_int_range (1, 3); if (g_random_boolean ()) latitude += distance * LATITUDE_IN_KM; else latitude -= distance * LATITUDE_IN_KM; accuracy += 3000; g_object_set (G_OBJECT (priv->location), "latitude", latitude, "accuracy", accuracy, NULL); g_debug ("location scrambled"); } speed = gclue_location_get_speed (location); if (speed == GCLUE_LOCATION_SPEED_UNKNOWN) { if (cur_location != NULL && priv->compute_movement) { guint64 cur_timestamp, timestamp; timestamp = gclue_location_get_timestamp (location); cur_timestamp = gclue_location_get_timestamp (cur_location); if (timestamp != cur_timestamp) gclue_location_set_speed_from_prev_location (priv->location, cur_location); } } else { gclue_location_set_speed (priv->location, speed); } set_heading_from_compass (source, location); heading = gclue_location_get_heading (location); if (heading == GCLUE_LOCATION_HEADING_UNKNOWN) { if (cur_location != NULL && priv->compute_movement) gclue_location_set_heading_from_prev_location (priv->location, cur_location); } else { gclue_location_set_heading (priv->location, heading); } g_object_notify (G_OBJECT (source), "location"); g_clear_object (&cur_location); } /** * gclue_location_source_get_active: * @source: a #GClueLocationSource * * Returns: TRUE if source is active, FALSE otherwise. **/ gboolean gclue_location_source_get_active (GClueLocationSource *source) { g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); return (source->priv->active_counter > 0); } /** * gclue_location_source_get_available_accuracy_level: * @source: a #GClueLocationSource * * Returns: The currently available accuracy level. **/ GClueAccuracyLevel gclue_location_source_get_available_accuracy_level (GClueLocationSource *source) { g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), 0); return source->priv->avail_accuracy_level; } /** * gclue_location_source_get_compute_movement * @source: a #GClueLocationSource * * Returns: %TRUE if speed and heading will be automatically computed (or * fetched from hardware) and set on new locations, %FALSE otherwise. **/ gboolean gclue_location_source_get_compute_movement (GClueLocationSource *source) { g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); return source->priv->compute_movement; } /** * gclue_location_source_set_compute_movement * @source: a #GClueLocationSource * @compute: a #gboolean * * Use this to specify whether or not you want @source to automatically compute * (or fetch from hardware) and set speed and heading on new locations. **/ void gclue_location_source_set_compute_movement (GClueLocationSource *source, gboolean compute) { g_return_if_fail (GCLUE_IS_LOCATION_SOURCE (source)); source->priv->compute_movement = compute; } /** * gclue_location_source_get_time_threshold * @source: a #GClueLocationSource * * Returns: (transfer none): The current time-threshold object, or NULL if * @source is not a valid #GClueLocationSource instance. **/ GClueMinUINT * gclue_location_source_get_time_threshold (GClueLocationSource *source) { g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), NULL); return source->priv->time_threshold; } geoclue-2.5.2/src/gclue-location-source.h000066400000000000000000000071271341441426700203230ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_LOCATION_SOURCE_H #define GCLUE_LOCATION_SOURCE_H #include #include #include "gclue-enum-types.h" #include "gclue-location.h" #include "gclue-min-uint.h" G_BEGIN_DECLS #define GCLUE_TYPE_LOCATION_SOURCE (gclue_location_source_get_type()) #define GCLUE_LOCATION_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_LOCATION_SOURCE, GClueLocationSource)) #define GCLUE_LOCATION_SOURCE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_LOCATION_SOURCE, GClueLocationSource const)) #define GCLUE_LOCATION_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_LOCATION_SOURCE, GClueLocationSourceClass)) #define GCLUE_IS_LOCATION_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_LOCATION_SOURCE)) #define GCLUE_IS_LOCATION_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_LOCATION_SOURCE)) #define GCLUE_LOCATION_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_LOCATION_SOURCE, GClueLocationSourceClass)) typedef struct _GClueLocationSource GClueLocationSource; typedef struct _GClueLocationSourceClass GClueLocationSourceClass; typedef struct _GClueLocationSourcePrivate GClueLocationSourcePrivate; struct _GClueLocationSource { GObject parent; /*< private >*/ GClueLocationSourcePrivate *priv; }; struct _GClueLocationSourceClass { GObjectClass parent_class; gboolean (*start) (GClueLocationSource *source); gboolean (*stop) (GClueLocationSource *source); }; GType gclue_location_source_get_type (void) G_GNUC_CONST; void gclue_location_source_start (GClueLocationSource *source); void gclue_location_source_stop (GClueLocationSource *source); GClueLocation *gclue_location_source_get_location (GClueLocationSource *source); void gclue_location_source_set_location (GClueLocationSource *source, GClueLocation *location); gboolean gclue_location_source_get_active (GClueLocationSource *source); GClueAccuracyLevel gclue_location_source_get_available_accuracy_level (GClueLocationSource *source); GClueMinUINT *gclue_location_source_get_time_threshold (GClueLocationSource *source); gboolean gclue_location_source_get_compute_movement (GClueLocationSource *source); void gclue_location_source_set_compute_movement (GClueLocationSource *source, gboolean compute); G_END_DECLS #endif /* GCLUE_LOCATION_SOURCE_H */ geoclue-2.5.2/src/gclue-location.c000066400000000000000000000764411341441426700170250ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-location.c * * Copyright 2012 Bastien Nocera * Copyright 2015 Ankit (Verma) * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Bastien Nocera * Zeeshan Ali (Khattak) * Ankit (Verma) */ #include "gclue-location.h" #include #include #include #define TIME_DIFF_THRESHOLD 60000000 /* 60 seconds */ #define EARTH_RADIUS_KM 6372.795 struct _GClueLocationPrivate { char *description; gdouble longitude; gdouble latitude; gdouble altitude; gdouble accuracy; guint64 timestamp; gdouble speed; gdouble heading; }; enum { PROP_0, PROP_LATITUDE, PROP_LONGITUDE, PROP_ACCURACY, PROP_DESCRIPTION, PROP_TIMESTAMP, PROP_ALTITUDE, PROP_SPEED, PROP_HEADING, }; G_DEFINE_TYPE_WITH_CODE (GClueLocation, gclue_location, G_TYPE_OBJECT, G_ADD_PRIVATE (GClueLocation)); static void gclue_location_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GClueLocation *location = GCLUE_LOCATION (object); switch (property_id) { case PROP_DESCRIPTION: g_value_set_string (value, gclue_location_get_description (location)); break; case PROP_LATITUDE: g_value_set_double (value, gclue_location_get_latitude (location)); break; case PROP_LONGITUDE: g_value_set_double (value, gclue_location_get_longitude (location)); break; case PROP_ALTITUDE: g_value_set_double (value, gclue_location_get_altitude (location)); break; case PROP_ACCURACY: g_value_set_double (value, gclue_location_get_accuracy (location)); break; case PROP_TIMESTAMP: g_value_set_uint64 (value, gclue_location_get_timestamp (location)); break; case PROP_SPEED: g_value_set_double (value, gclue_location_get_speed (location)); break; case PROP_HEADING: g_value_set_double (value, gclue_location_get_heading (location)); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gclue_location_set_latitude (GClueLocation *loc, gdouble latitude) { g_return_if_fail (latitude >= -90.0 && latitude <= 90.0); loc->priv->latitude = latitude; } static void gclue_location_set_longitude (GClueLocation *loc, gdouble longitude) { g_return_if_fail (longitude >= -180.0 && longitude <= 180.0); loc->priv->longitude = longitude; } static void gclue_location_set_altitude (GClueLocation *loc, gdouble altitude) { loc->priv->altitude = altitude; } static void gclue_location_set_accuracy (GClueLocation *loc, gdouble accuracy) { g_return_if_fail (accuracy >= GCLUE_LOCATION_ACCURACY_UNKNOWN); loc->priv->accuracy = accuracy; } static void gclue_location_set_timestamp (GClueLocation *loc, guint64 timestamp) { g_return_if_fail (GCLUE_IS_LOCATION (loc)); loc->priv->timestamp = timestamp; } void gclue_location_set_description (GClueLocation *loc, const char *description) { g_return_if_fail (GCLUE_IS_LOCATION (loc)); g_free (loc->priv->description); loc->priv->description = g_strdup (description); } static void gclue_location_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GClueLocation *location = GCLUE_LOCATION (object); switch (property_id) { case PROP_DESCRIPTION: gclue_location_set_description (location, g_value_get_string (value)); break; case PROP_LATITUDE: gclue_location_set_latitude (location, g_value_get_double (value)); break; case PROP_LONGITUDE: gclue_location_set_longitude (location, g_value_get_double (value)); break; case PROP_ALTITUDE: gclue_location_set_altitude (location, g_value_get_double (value)); break; case PROP_ACCURACY: gclue_location_set_accuracy (location, g_value_get_double (value)); break; case PROP_TIMESTAMP: gclue_location_set_timestamp (location, g_value_get_uint64 (value)); break; case PROP_SPEED: gclue_location_set_speed (location, g_value_get_double (value)); break; case PROP_HEADING: gclue_location_set_heading (location, g_value_get_double (value)); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gclue_location_constructed (GObject *object) { GClueLocation *location = GCLUE_LOCATION (object); GTimeVal tv; if (location->priv->timestamp != 0) return; g_get_current_time (&tv); gclue_location_set_timestamp (location, tv.tv_sec); } static void gclue_location_finalize (GObject *glocation) { g_clear_pointer (&GCLUE_LOCATION (glocation)->priv->description, g_free); G_OBJECT_CLASS (gclue_location_parent_class)->finalize (glocation); } static void gclue_location_class_init (GClueLocationClass *klass) { GObjectClass *glocation_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; glocation_class->constructed = gclue_location_constructed; glocation_class->finalize = gclue_location_finalize; glocation_class->get_property = gclue_location_get_property; glocation_class->set_property = gclue_location_set_property; /** * GClueLocation:description: * * The description of this location. */ pspec = g_param_spec_string ("description", "Description", "Description of this location", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_DESCRIPTION, pspec); /** * GClueLocation:latitude: * * The latitude of this location in degrees. */ pspec = g_param_spec_double ("latitude", "Latitude", "The latitude of this location in degrees", -90.0, 90.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_LATITUDE, pspec); /** * GClueLocation:longitude: * * The longitude of this location in degrees. */ pspec = g_param_spec_double ("longitude", "Longitude", "The longitude of this location in degrees", -180.0, 180.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_LONGITUDE, pspec); /** * GClueLocation:altitude: * * The altitude of this location in meters. */ pspec = g_param_spec_double ("altitude", "Altitude", "The altitude of this location in meters", GCLUE_LOCATION_ALTITUDE_UNKNOWN, G_MAXDOUBLE, GCLUE_LOCATION_ALTITUDE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_ALTITUDE, pspec); /** * GClueLocation:accuracy: * * The accuracy of this location in meters. */ pspec = g_param_spec_double ("accuracy", "Accuracy", "The accuracy of this location in meters", GCLUE_LOCATION_ACCURACY_UNKNOWN, G_MAXDOUBLE, GCLUE_LOCATION_ACCURACY_UNKNOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_ACCURACY, pspec); /** * GClueLocation:timestamp: * * A timestamp in seconds since * Epoch, * giving when the location was resolved from an address. * * A value of 0 (zero) will be interpreted as the current time. */ pspec = g_param_spec_uint64 ("timestamp", "Timestamp", "The timestamp of this location " "in seconds since Epoch", 0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_TIMESTAMP, pspec); /** * GClueLocation:speed * * The speed in meters per second. */ pspec = g_param_spec_double ("speed", "Speed", "Speed in meters per second", GCLUE_LOCATION_SPEED_UNKNOWN, G_MAXDOUBLE, GCLUE_LOCATION_SPEED_UNKNOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_SPEED, pspec); /** * GClueLocation:heading * * The positive angle between the direction of movement and the North * direction, in clockwise direction. The angle is measured in degrees. */ pspec = g_param_spec_double ("heading", "Heading", "The positive Angle between the direction" " of movement and the North direction, in" " clockwise direction. The angle is " "measured in degrees.", GCLUE_LOCATION_HEADING_UNKNOWN, G_MAXDOUBLE, GCLUE_LOCATION_HEADING_UNKNOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (glocation_class, PROP_HEADING, pspec); } static void gclue_location_init (GClueLocation *location) { location->priv = G_TYPE_INSTANCE_GET_PRIVATE ((location), GCLUE_TYPE_LOCATION, GClueLocationPrivate); location->priv->altitude = GCLUE_LOCATION_ALTITUDE_UNKNOWN; location->priv->accuracy = GCLUE_LOCATION_ACCURACY_UNKNOWN; location->priv->speed = GCLUE_LOCATION_SPEED_UNKNOWN; location->priv->heading = GCLUE_LOCATION_HEADING_UNKNOWN; } static gdouble get_accuracy_from_hdop (gdouble hdop) { /* FIXME: These are really just rough estimates based on: * http://en.wikipedia.org/wiki/Dilution_of_precision_%28GPS%29#Meaning_of_DOP_Values */ if (hdop <= 1) return 0; else if (hdop <= 2) return 1; else if (hdop <= 5) return 3; else if (hdop <= 10) return 50; else if (hdop <= 20) return 100; else return 300; } static gdouble parse_coordinate_string (const char *coordinate, const char *direction) { gdouble minutes, degrees, out; gchar *degrees_str; gchar *dot_str; gint dot_offset; if (coordinate[0] == '\0' || direction[0] == '\0' || direction[0] == '\0') return INVALID_COORDINATE; if (direction[0] != 'N' && direction[0] != 'S' && direction[0] != 'E' && direction[0] != 'W') { g_warning ("Unknown direction '%s' for coordinates, ignoring..", direction); return INVALID_COORDINATE; } dot_str = g_strstr_len (coordinate, 6, "."); if (dot_str == NULL) return INVALID_COORDINATE; dot_offset = dot_str - coordinate; degrees_str = g_strndup (coordinate, dot_offset - 2); degrees = g_ascii_strtod (degrees_str, NULL); g_free (degrees_str); minutes = g_ascii_strtod (dot_str - 2, NULL); /* Include the minutes as part of the degrees */ out = degrees + (minutes / 60.0); if (direction[0] == 'S' || direction[0] == 'W') out = 0 - out; return out; } static gdouble parse_altitude_string (const char *altitude, const char *unit) { if (altitude[0] == '\0' || unit[0] == '\0') return GCLUE_LOCATION_ALTITUDE_UNKNOWN; if (unit[0] != 'M') { g_warning ("Unknown unit '%s' for altitude, ignoring..", unit); return GCLUE_LOCATION_ALTITUDE_UNKNOWN; } return g_ascii_strtod (altitude, NULL); } static gint64 parse_nmea_timestamp (const char *nmea_ts) { char parts[3][3]; int i, hours, minutes, seconds; GDateTime *now, *ts = NULL; guint64 ret; now = g_date_time_new_now_utc (); ret = g_date_time_to_unix (now); if (strlen (nmea_ts) < 6) { if (strlen (nmea_ts) >= 1) /* Empty string just means no ts, so no warning */ g_warning ("Failed to parse NMEA timestamp '%s'", nmea_ts); goto parse_error; } for (i = 0; i < 3; i++) { memmove (parts[i], nmea_ts + (i * 2), 2); parts[i][2] = '\0'; } hours = atoi (parts[0]); minutes = atoi (parts[1]); seconds = atoi (parts[2]); ts = g_date_time_new_utc (g_date_time_get_year (now), g_date_time_get_month (now), g_date_time_get_day_of_month (now), hours, minutes, seconds); if (g_date_time_difference (ts, now) > TIME_DIFF_THRESHOLD) { g_debug ("NMEA timestamp '%s' in future. Assuming yesterday's.", nmea_ts); g_date_time_unref (ts); ts = g_date_time_new_utc (g_date_time_get_year (now), g_date_time_get_month (now), g_date_time_get_day_of_month (now) - 1, hours, minutes, seconds); } ret = g_date_time_to_unix (ts); g_date_time_unref (ts); parse_error: g_date_time_unref (now); return ret; } /** * gclue_location_new: * @latitude: a valid latitude * @longitude: a valid longitude * @accuracy: accuracy of location in meters * * Creates a new #GClueLocation object. * * Returns: a new #GClueLocation object. Use g_object_unref() when done. **/ GClueLocation * gclue_location_new (gdouble latitude, gdouble longitude, gdouble accuracy) { return g_object_new (GCLUE_TYPE_LOCATION, "latitude", latitude, "longitude", longitude, "accuracy", accuracy, NULL); } /** * gclue_location_new_full: * @latitude: a valid latitude * @longitude: a valid longitude * @accuracy: accuracy of location in meters * @speed: speed in meters per second * @heading: heading in degrees * @altitude: altitude of location in meters * @timestamp: timestamp in seconds since the Epoch * @description: a description for the location * * Creates a new #GClueLocation object. * * Returns: a new #GClueLocation object. Use g_object_unref() when done. **/ GClueLocation * gclue_location_new_full (gdouble latitude, gdouble longitude, gdouble accuracy, gdouble speed, gdouble heading, gdouble altitude, guint64 timestamp, const char *description) { return g_object_new (GCLUE_TYPE_LOCATION, "latitude", latitude, "longitude", longitude, "accuracy", accuracy, "speed", speed, "heading", heading, "altitude", altitude, "timestamp", timestamp, "description", description, NULL); } /** * gclue_location_create_from_gga: * @gga: NMEA GGA sentence * @error: Place-holder for errors. * * Creates a new #GClueLocation object from a GGA sentence. * * Returns: a new #GClueLocation object, or %NULL on error. Unref using * #g_object_unref() when done with it. **/ GClueLocation * gclue_location_create_from_gga (const char *gga, GError **error) { GClueLocation *location = NULL; gdouble latitude, longitude, accuracy, altitude; gdouble hdop; /* Horizontal Dilution Of Precision */ guint64 timestamp; char **parts; parts = g_strsplit (gga, ",", -1); if (g_strv_length (parts) < 14) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "Invalid NMEA GGA sentence"); goto out; } /* For syntax of GGA sentences: * http://www.gpsinformation.org/dale/nmea.htm#GGA */ timestamp = parse_nmea_timestamp (parts[1]); latitude = parse_coordinate_string (parts[2], parts[3]); longitude = parse_coordinate_string (parts[4], parts[5]); if (latitude == INVALID_COORDINATE || longitude == INVALID_COORDINATE) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "Invalid NMEA GGA sentence"); goto out; } altitude = parse_altitude_string (parts[9], parts[10]); hdop = g_ascii_strtod (parts[8], NULL); accuracy = get_accuracy_from_hdop (hdop); location = g_object_new (GCLUE_TYPE_LOCATION, "latitude", latitude, "longitude", longitude, "accuracy", accuracy, "timestamp", timestamp, NULL); if (altitude != GCLUE_LOCATION_ALTITUDE_UNKNOWN) g_object_set (location, "altitude", altitude, NULL); out: g_strfreev (parts); return location; } /** * gclue_location_duplicate: * @location: the #GClueLocation instance to duplicate. * * Creates a new copy of @location object. * * Returns: a new #GClueLocation object. Use g_object_unref() when done. **/ GClueLocation * gclue_location_duplicate (GClueLocation *location) { g_return_val_if_fail (GCLUE_IS_LOCATION (location), NULL); return g_object_new (GCLUE_TYPE_LOCATION, "latitude", location->priv->latitude, "longitude", location->priv->longitude, "accuracy", location->priv->accuracy, "altitude", location->priv->altitude, "timestamp", location->priv->timestamp, "speed", location->priv->speed, "heading", location->priv->heading, NULL); } const char * gclue_location_get_description (GClueLocation *loc) { g_return_val_if_fail (GCLUE_IS_LOCATION (loc), NULL); return loc->priv->description; } /** * gclue_location_get_latitude: * @loc: a #GClueLocation * * Gets the latitude of location @loc. * * Returns: The latitude of location @loc. **/ gdouble gclue_location_get_latitude (GClueLocation *loc) { g_return_val_if_fail (GCLUE_IS_LOCATION (loc), 0.0); return loc->priv->latitude; } /** * gclue_location_get_longitude: * @loc: a #GClueLocation * * Gets the longitude of location @loc. * * Returns: The longitude of location @loc. **/ gdouble gclue_location_get_longitude (GClueLocation *loc) { g_return_val_if_fail (GCLUE_IS_LOCATION (loc), 0.0); return loc->priv->longitude; } /** * gclue_location_get_altitude: * @loc: a #GClueLocation * * Gets the altitude of location @loc. * * Returns: The altitude of location @loc. **/ gdouble gclue_location_get_altitude (GClueLocation *loc) { g_return_val_if_fail (GCLUE_IS_LOCATION (loc), GCLUE_LOCATION_ALTITUDE_UNKNOWN); return loc->priv->altitude; } /** * gclue_location_get_accuracy: * @loc: a #GClueLocation * * Gets the accuracy (in meters) of location @loc. * * Returns: The accuracy of location @loc. **/ gdouble gclue_location_get_accuracy (GClueLocation *loc) { g_return_val_if_fail (GCLUE_IS_LOCATION (loc), GCLUE_LOCATION_ACCURACY_UNKNOWN); return loc->priv->accuracy; } /** * gclue_location_get_timestamp: * @loc: a #GClueLocation * * Gets the timestamp (in seconds since the Epoch) of location @loc. See * #GClueLocation:timestamp. * * Returns: The timestamp of location @loc. **/ guint64 gclue_location_get_timestamp (GClueLocation *loc) { g_return_val_if_fail (GCLUE_IS_LOCATION (loc), 0); return loc->priv->timestamp; } /** * gclue_location_get_speed: * @location: a #GClueLocation * * Gets the speed in meters per second. * * Returns: The speed, or %GCLUE_LOCATION_SPEED_UNKNOWN if speed in unknown. **/ gdouble gclue_location_get_speed (GClueLocation *location) { g_return_val_if_fail (GCLUE_IS_LOCATION (location), GCLUE_LOCATION_SPEED_UNKNOWN); return location->priv->speed; } /** * gclue_location_set_speed: * @location: a #GClueLocation * @speed: speed in meters per second * * Sets the speed. **/ void gclue_location_set_speed (GClueLocation *location, gdouble speed) { location->priv->speed = speed; g_object_notify (G_OBJECT (location), "speed"); } /** * gclue_location_set_speed_from_prev_location: * @location: a #GClueLocation * @prev_location: a #GClueLocation * * Calculates the speed based on provided previous location @prev_location * and sets it on @location. **/ void gclue_location_set_speed_from_prev_location (GClueLocation *location, GClueLocation *prev_location) { gdouble speed; guint64 timestamp, prev_timestamp; g_return_if_fail (GCLUE_IS_LOCATION (location)); g_return_if_fail (prev_location == NULL || GCLUE_IS_LOCATION (prev_location)); if (prev_location == NULL) { speed = GCLUE_LOCATION_SPEED_UNKNOWN; goto out; } timestamp = gclue_location_get_timestamp (location); prev_timestamp = gclue_location_get_timestamp (prev_location); if (timestamp <= prev_timestamp) { speed = GCLUE_LOCATION_SPEED_UNKNOWN; goto out; } speed = gclue_location_get_distance_from (location, prev_location) * 1000.0 / (timestamp - prev_timestamp); out: location->priv->speed = speed; g_object_notify (G_OBJECT (location), "speed"); } /** * gclue_location_get_heading: * @location: a #GClueLocation * * Gets the positive angle between direction of movement and North direction. * The angle is measured in degrees. * * Returns: The heading, or %GCLUE_LOCATION_HEADING_UNKNOWN if heading is * unknown. **/ gdouble gclue_location_get_heading (GClueLocation *location) { g_return_val_if_fail (GCLUE_IS_LOCATION (location), GCLUE_LOCATION_HEADING_UNKNOWN); return location->priv->heading; } /** * gclue_location_set_heading: * @location: a #GClueLocation * @heading: heading in degrees * * Sets the heading. **/ void gclue_location_set_heading (GClueLocation *location, gdouble heading) { location->priv->heading = heading; g_object_notify (G_OBJECT (location), "heading"); } /** * gclue_location_set_heading_from_prev_location: * @location: a #GClueLocation * @prev_location: a #GClueLocation * * Calculates the heading direction in degrees with respect to North direction * based on provided @prev_location and sets it on @location. **/ void gclue_location_set_heading_from_prev_location (GClueLocation *location, GClueLocation *prev_location) { gdouble dx, dy, angle, lat, lon, prev_lat, prev_lon; g_return_if_fail (GCLUE_IS_LOCATION (location)); g_return_if_fail (prev_location == NULL || GCLUE_IS_LOCATION (prev_location)); if (prev_location == NULL) { location->priv->heading = GCLUE_LOCATION_HEADING_UNKNOWN; return; } lat = gclue_location_get_latitude (location); lon = gclue_location_get_longitude (location); prev_lat = gclue_location_get_latitude (prev_location); prev_lon = gclue_location_get_longitude (prev_location); dx = (lat - prev_lat); dy = (lon - prev_lon); /* atan2 takes in coordinate values of a 2D space and returns the angle * which the line from origin to that coordinate makes with the positive * X-axis, in the range (-PI,+PI]. Converting it into degrees we get the * angle in range (-180,180]. This means East = 0 degree, * West = -180 degrees, North = 90 degrees, South = -90 degrees. * * Passing atan2 a negative value of dx will flip the angles about * Y-axis. This means the angle now returned will be the angle with * respect to negative X-axis. Which makes West = 0 degree, * East = 180 degrees, North = 90 degrees, South = -90 degrees. */ angle = atan2(dy, -dx) * 180.0 / M_PI; /* Now, North is supposed to be 0 degree. Lets subtract 90 degrees * from angle. After this step West = -90 degrees, East = 90 degrees, * North = 0 degree, South = -180 degrees. */ angle -= 90.0; /* As we know, angle ~= angle + 360; using this on negative values would * bring the the angle in range [0,360). * * After this step West = 270 degrees, East = 90 degrees, * North = 0 degree, South = 180 degrees. */ if (angle < 0) angle += 360.0; location->priv->heading = angle; g_object_notify (G_OBJECT (location), "heading"); } /** * gclue_location_get_distance_from: * @loca: a #GClueLocation * @locb: a #GClueLocation * * Calculates the distance in km, along the curvature of the Earth, * between 2 locations. Note that altitude changes are not * taken into account. * * Returns: a distance in km. **/ double gclue_location_get_distance_from (GClueLocation *loca, GClueLocation *locb) { gdouble dlat, dlon, lat1, lat2; gdouble a, c; g_return_val_if_fail (GCLUE_IS_LOCATION (loca), 0.0); g_return_val_if_fail (GCLUE_IS_LOCATION (locb), 0.0); /* Algorithm from: * http://www.movable-type.co.uk/scripts/latlong.html */ dlat = (locb->priv->latitude - loca->priv->latitude) * M_PI / 180.0; dlon = (locb->priv->longitude - loca->priv->longitude) * M_PI / 180.0; lat1 = loca->priv->latitude * M_PI / 180.0; lat2 = locb->priv->latitude * M_PI / 180.0; a = sin (dlat / 2) * sin (dlat / 2) + sin (dlon / 2) * sin (dlon / 2) * cos (lat1) * cos (lat2); c = 2 * atan2 (sqrt (a), sqrt (1-a)); return EARTH_RADIUS_KM * c; } geoclue-2.5.2/src/gclue-location.h000066400000000000000000000136601341441426700170240ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-location.h * * Copyright 2012 Bastien Nocera * Copyright 2015 Ankit (Verma) * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Bastien Nocera * Zeeshan Ali (Khattak) * Ankit (Verma) */ #ifndef GCLUE_LOCATION_H #define GCLUE_LOCATION_H #include #include G_BEGIN_DECLS #define GCLUE_TYPE_LOCATION (gclue_location_get_type ()) #define GCLUE_LOCATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_LOCATION, GClueLocation)) #define GCLUE_IS_LOCATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_LOCATION)) #define GCLUE_LOCATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_LOCATION, GClueLocationClass)) #define GCLUE_IS_LOCATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_LOCATION)) #define GCLUE_LOCATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_LOCATION, GClueLocationClass)) #define INVALID_COORDINATE -G_MAXDOUBLE typedef struct _GClueLocation GClueLocation; typedef struct _GClueLocationClass GClueLocationClass; typedef struct _GClueLocationPrivate GClueLocationPrivate; struct _GClueLocation { /* Parent instance structure */ GObject parent_instance; GClueLocationPrivate *priv; }; struct _GClueLocationClass { /* Parent class structure */ GObjectClass parent_class; }; GType gclue_location_get_type (void); /** * GCLUE_LOCATION_ALTITUDE_UNKNOWN: * * Constant representing unknown altitude. */ #define GCLUE_LOCATION_ALTITUDE_UNKNOWN -G_MAXDOUBLE /** * GCLUE_LOCATION_ACCURACY_UNKNOWN: * * Constant representing unknown accuracy. */ #define GCLUE_LOCATION_ACCURACY_UNKNOWN -1 /** * GCLUE_LOCATION_ACCURACY_STREET: * * Constant representing street-level accuracy. */ #define GCLUE_LOCATION_ACCURACY_STREET 1000 /* 1 km */ /** * GCLUE_LOCATION_ACCURACY_CITY: * * Constant representing city-level accuracy. */ #define GCLUE_LOCATION_ACCURACY_CITY 15000 /* 15 km */ /** * GCLUE_LOCATION_ACCURACY_REGION: * * Constant representing region-level accuracy. */ #define GCLUE_LOCATION_ACCURACY_REGION 50000 /* 50 km */ /** * GCLUE_LOCATION_ACCURACY_COUNTRY: * * Constant representing country-level accuracy. */ #define GCLUE_LOCATION_ACCURACY_COUNTRY 300000 /* 300 km */ /** * GCLUE_LOCATION_ACCURACY_CONTINENT: * * Constant representing continent-level accuracy. */ #define GCLUE_LOCATION_ACCURACY_CONTINENT 3000000 /* 3000 km */ /** * GCLUE_LOCATION_HEADING_UNKNOWN: * * Constant representing unknown heading. */ #define GCLUE_LOCATION_HEADING_UNKNOWN -1.0 /** * GCLUE_LOCATION_SPEED_UNKNOWN: * * Constant representing unknown speed. */ #define GCLUE_LOCATION_SPEED_UNKNOWN -1.0 GClueLocation *gclue_location_new (gdouble latitude, gdouble longitude, gdouble accuracy); GClueLocation *gclue_location_new_full (gdouble latitude, gdouble longitude, gdouble accuracy, gdouble speed, gdouble heading, gdouble altitude, guint64 timestamp, const char *description); GClueLocation *gclue_location_create_from_gga (const char *gga, GError **error); GClueLocation *gclue_location_duplicate (GClueLocation *location); void gclue_location_set_description (GClueLocation *loc, const char *description); const char *gclue_location_get_description (GClueLocation *loc); gdouble gclue_location_get_latitude (GClueLocation *loc); gdouble gclue_location_get_longitude (GClueLocation *loc); gdouble gclue_location_get_altitude (GClueLocation *loc); gdouble gclue_location_get_accuracy (GClueLocation *loc); guint64 gclue_location_get_timestamp (GClueLocation *loc); void gclue_location_set_speed (GClueLocation *loc, gdouble speed); void gclue_location_set_speed_from_prev_location (GClueLocation *location, GClueLocation *prev_location); gdouble gclue_location_get_speed (GClueLocation *loc); void gclue_location_set_heading (GClueLocation *loc, gdouble heading); void gclue_location_set_heading_from_prev_location (GClueLocation *location, GClueLocation *prev_location); gdouble gclue_location_get_heading (GClueLocation *loc); double gclue_location_get_distance_from (GClueLocation *loca, GClueLocation *locb); #endif /* GCLUE_LOCATION_H */ geoclue-2.5.2/src/gclue-locator.c000066400000000000000000000475221341441426700166560ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-locator.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include "config.h" #include #include "gclue-locator.h" #include "gclue-wifi.h" #include "gclue-config.h" #if GCLUE_USE_3G_SOURCE #include "gclue-3g.h" #endif #if GCLUE_USE_CDMA_SOURCE #include "gclue-cdma.h" #endif #if GCLUE_USE_MODEM_GPS_SOURCE #include "gclue-modem-gps.h" #endif #if GCLUE_USE_NMEA_SOURCE #include "gclue-nmea-source.h" #endif /* This class is like a master location source that hides all individual * location sources from rest of the code */ static gboolean gclue_locator_start (GClueLocationSource *source); static gboolean gclue_locator_stop (GClueLocationSource *source); struct _GClueLocatorPrivate { GList *sources; GList *active_sources; GClueAccuracyLevel accuracy_level; guint time_threshold; }; G_DEFINE_TYPE_WITH_CODE (GClueLocator, gclue_locator, GCLUE_TYPE_LOCATION_SOURCE, G_ADD_PRIVATE (GClueLocator)) enum { PROP_0, PROP_ACCURACY_LEVEL, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static void set_location (GClueLocator *locator, GClueLocation *location) { GClueLocation *cur_location; cur_location = gclue_location_source_get_location (GCLUE_LOCATION_SOURCE (locator)); g_debug ("New location available"); if (cur_location != NULL) { if (gclue_location_get_timestamp (location) < gclue_location_get_timestamp (cur_location)) { g_debug ("New location older than current, ignoring."); return; } if (gclue_location_get_distance_from (location, cur_location) * 1000 < gclue_location_get_accuracy (location) && gclue_location_get_accuracy (location) > gclue_location_get_accuracy (cur_location)) { /* We only take the new location if either the previous one * lies outside its accuracy circle or its more or as * accurate as previous one. */ g_debug ("Ignoring less accurate new location"); return; } } gclue_location_source_set_location (GCLUE_LOCATION_SOURCE (locator), location); } static gint compare_accuracy_level (GClueLocationSource *src_a, GClueLocationSource *src_b) { GClueAccuracyLevel level_a, level_b; level_a = gclue_location_source_get_available_accuracy_level (src_a); level_b = gclue_location_source_get_available_accuracy_level (src_b); return (level_b - level_a); } static void refresh_available_accuracy_level (GClueLocator *locator) { GClueAccuracyLevel new, existing; /* Sort the sources according to their accuracy level so that the head * of the list will have the highest level. The goal is to start the * most accurate source first and when all sources are already active * for an app, a second app to get the most accurate location only. */ locator->priv->sources = g_list_sort (locator->priv->sources, (GCompareFunc) compare_accuracy_level); new = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (locator->priv->sources->data)); existing = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (locator)); if (new != existing) g_object_set (G_OBJECT (locator), "available-accuracy-level", new, NULL); } static void on_location_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueLocator *locator = GCLUE_LOCATOR (user_data); GClueLocationSource *source = GCLUE_LOCATION_SOURCE (gobject); GClueLocation *location; location = gclue_location_source_get_location (source); set_location (locator, location); } static gboolean is_source_active (GClueLocator *locator, GClueLocationSource *src) { return (g_list_find (locator->priv->active_sources, src) != NULL); } static void start_source (GClueLocator *locator, GClueLocationSource *src) { GClueLocation *location; g_signal_connect (G_OBJECT (src), "notify::location", G_CALLBACK (on_location_changed), locator); location = gclue_location_source_get_location (src); if (gclue_location_source_get_active (src) && location != NULL) set_location (locator, location); gclue_location_source_start (src); } static void on_avail_accuracy_level_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueLocationSource *src = GCLUE_LOCATION_SOURCE (gobject); GClueLocator *locator = GCLUE_LOCATOR (user_data); GClueLocatorPrivate *priv = locator->priv; GClueAccuracyLevel level; gboolean active; refresh_available_accuracy_level (locator); active = gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (locator)); if (!active) return; level = gclue_location_source_get_available_accuracy_level (src); if (level != GCLUE_ACCURACY_LEVEL_NONE && priv->accuracy_level >= level && !is_source_active (locator, src)) { start_source (locator, src); priv->active_sources = g_list_append (locator->priv->active_sources, src); } else if ((level == GCLUE_ACCURACY_LEVEL_NONE || priv->accuracy_level < level) && is_source_active (locator, src)) { g_signal_handlers_disconnect_by_func (G_OBJECT (src), G_CALLBACK (on_location_changed), locator); gclue_location_source_stop (src); priv->active_sources = g_list_remove (priv->active_sources, src); } } static void reset_time_threshold (GClueLocator *locator, GClueLocationSource *source, guint value) { GClueMinUINT *threshold; threshold = gclue_location_source_get_time_threshold (source); gclue_min_uint_add_value (threshold, value, G_OBJECT (locator)); } static void on_time_threshold_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueMinUINT *threshold = GCLUE_MIN_UINT (gobject); GClueLocator *locator = GCLUE_LOCATOR (user_data); guint value = gclue_min_uint_get_value (threshold); GList *node; for (node = locator->priv->sources; node != NULL; node = node->next) { reset_time_threshold (locator, GCLUE_LOCATION_SOURCE (node->data), value); } } static void gclue_locator_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueLocator *locator = GCLUE_LOCATOR (object); switch (prop_id) { case PROP_ACCURACY_LEVEL: g_value_set_enum (value, locator->priv->accuracy_level); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_locator_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueLocator *locator = GCLUE_LOCATOR (object); switch (prop_id) { case PROP_ACCURACY_LEVEL: locator->priv->accuracy_level = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_locator_finalize (GObject *gsource) { GClueLocator *locator = GCLUE_LOCATOR (gsource); GClueLocatorPrivate *priv = locator->priv; GList *node; GClueMinUINT *threshold; G_OBJECT_CLASS (gclue_locator_parent_class)->finalize (gsource); threshold = gclue_location_source_get_time_threshold (GCLUE_LOCATION_SOURCE (locator)); g_signal_handlers_disconnect_by_func (G_OBJECT (threshold), G_CALLBACK (on_time_threshold_changed), locator); for (node = locator->priv->sources; node != NULL; node = node->next) { g_signal_handlers_disconnect_by_func (G_OBJECT (node->data), G_CALLBACK (on_avail_accuracy_level_changed), locator); } for (node = locator->priv->active_sources; node != NULL; node = node->next) { g_signal_handlers_disconnect_by_func (G_OBJECT (node->data), G_CALLBACK (on_location_changed), locator); gclue_location_source_stop (GCLUE_LOCATION_SOURCE (node->data)); } g_list_free_full (priv->sources, g_object_unref); priv->sources = NULL; priv->active_sources = NULL; } static void gclue_locator_constructed (GObject *object) { GClueLocator *locator = GCLUE_LOCATOR (object); GClueLocationSource *submit_source = NULL; GClueConfig *gconfig = gclue_config_get_singleton (); GClueWifi *wifi; GList *node; GClueMinUINT *threshold; G_OBJECT_CLASS (gclue_locator_parent_class)->constructed (object); #if GCLUE_USE_3G_SOURCE if (gclue_config_get_enable_3g_source (gconfig)) { GClue3G *source = gclue_3g_get_singleton (); locator->priv->sources = g_list_append (locator->priv->sources, source); } #endif #if GCLUE_USE_CDMA_SOURCE if (gclue_config_get_enable_cdma_source (gconfig)) { GClueCDMA *cdma = gclue_cdma_get_singleton (); locator->priv->sources = g_list_append (locator->priv->sources, cdma); } #endif if (gclue_config_get_enable_wifi_source (gconfig)) wifi = gclue_wifi_get_singleton (locator->priv->accuracy_level); else /* City-level accuracy will give us GeoIP-only source */ wifi = gclue_wifi_get_singleton (GCLUE_ACCURACY_LEVEL_CITY); locator->priv->sources = g_list_append (locator->priv->sources, wifi); #if GCLUE_USE_MODEM_GPS_SOURCE if (gclue_config_get_enable_modem_gps_source (gconfig)) { GClueModemGPS *gps = gclue_modem_gps_get_singleton (); locator->priv->sources = g_list_append (locator->priv->sources, gps); submit_source = GCLUE_LOCATION_SOURCE (gps); } #endif #if GCLUE_USE_NMEA_SOURCE if (gclue_config_get_enable_nmea_source (gconfig)) { GClueNMEASource *nmea = gclue_nmea_source_get_singleton (); locator->priv->sources = g_list_append (locator->priv->sources, nmea); } #endif for (node = locator->priv->sources; node != NULL; node = node->next) { g_signal_connect (G_OBJECT (node->data), "notify::available-accuracy-level", G_CALLBACK (on_avail_accuracy_level_changed), locator); if (submit_source != NULL && GCLUE_IS_WEB_SOURCE (node->data)) gclue_web_source_set_submit_source (GCLUE_WEB_SOURCE (node->data), submit_source); } threshold = gclue_location_source_get_time_threshold (GCLUE_LOCATION_SOURCE (locator)); g_signal_connect (G_OBJECT (threshold), "notify::value", G_CALLBACK (on_time_threshold_changed), locator); refresh_available_accuracy_level (locator); } static void gclue_locator_class_init (GClueLocatorClass *klass) { GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *object_class; source_class->start = gclue_locator_start; source_class->stop = gclue_locator_stop; object_class = G_OBJECT_CLASS (klass); object_class->get_property = gclue_locator_get_property; object_class->set_property = gclue_locator_set_property; object_class->finalize = gclue_locator_finalize; object_class->constructed = gclue_locator_constructed; gParamSpecs[PROP_ACCURACY_LEVEL] = g_param_spec_enum ("accuracy-level", "AccuracyLevel", "Accuracy level", GCLUE_TYPE_ACCURACY_LEVEL, GCLUE_ACCURACY_LEVEL_CITY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_ACCURACY_LEVEL, gParamSpecs[PROP_ACCURACY_LEVEL]); } static void gclue_locator_init (GClueLocator *locator) { locator->priv = G_TYPE_INSTANCE_GET_PRIVATE (locator, GCLUE_TYPE_LOCATOR, GClueLocatorPrivate); } static gboolean gclue_locator_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; GClueLocator *locator; GList *node; g_return_val_if_fail (GCLUE_IS_LOCATOR (source), FALSE); locator = GCLUE_LOCATOR (source); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_locator_parent_class); if (!base_class->start (source)) return FALSE; for (node = locator->priv->sources; node != NULL; node = node->next) { GClueLocationSource *src = GCLUE_LOCATION_SOURCE (node->data); GClueAccuracyLevel level; level = gclue_location_source_get_available_accuracy_level (src); if (level > locator->priv->accuracy_level || level == GCLUE_ACCURACY_LEVEL_NONE) { g_debug ("Not starting %s (accuracy level: %u). " "Requested accuracy level: %u.", G_OBJECT_TYPE_NAME (src), level, locator->priv->accuracy_level); continue; } locator->priv->active_sources = g_list_append (locator->priv->active_sources, src); start_source (locator, src); } return TRUE; } static gboolean gclue_locator_stop (GClueLocationSource *source) { GClueLocationSourceClass *base_class; GClueLocator *locator; GList *node; g_return_val_if_fail (GCLUE_IS_LOCATOR (source), FALSE); locator = GCLUE_LOCATOR (source); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_locator_parent_class); if (!base_class->stop (source)) return FALSE; for (node = locator->priv->active_sources; node != NULL; node = node->next) { GClueLocationSource *src = GCLUE_LOCATION_SOURCE (node->data); g_signal_handlers_disconnect_by_func (G_OBJECT (src), G_CALLBACK (on_location_changed), locator); gclue_location_source_stop (src); g_debug ("Requested %s to stop", G_OBJECT_TYPE_NAME (src)); } g_list_free (locator->priv->active_sources); locator->priv->active_sources = NULL; return TRUE; } GClueLocator * gclue_locator_new (GClueAccuracyLevel level) { GClueAccuracyLevel accuracy_level = level; if (accuracy_level == GCLUE_ACCURACY_LEVEL_COUNTRY) /* There is no source that provides country-level accuracy. * Since Wifi (as geoip) source is the best we can do, accuracy * really is country-level many times from this source and its * doubtful app (or user) will mind being given slighly more * accurate location, lets just map this to city-level accuracy. */ accuracy_level = GCLUE_ACCURACY_LEVEL_CITY; return g_object_new (GCLUE_TYPE_LOCATOR, "accuracy-level", accuracy_level, "compute-movement", FALSE, NULL); } GClueAccuracyLevel gclue_locator_get_accuracy_level (GClueLocator *locator) { g_return_val_if_fail (GCLUE_IS_LOCATOR (locator), GCLUE_ACCURACY_LEVEL_NONE); return locator->priv->accuracy_level; } /** * gclue_locator_get_time_threshold * @locator: a #GClueLocator * * Returns: The current time-threshold in seconds. **/ guint gclue_locator_get_time_threshold (GClueLocator *locator) { GClueMinUINT *threshold; g_return_val_if_fail (GCLUE_IS_LOCATOR (locator), 0); threshold = gclue_location_source_get_time_threshold (GCLUE_LOCATION_SOURCE (locator)); return gclue_min_uint_get_value (threshold); } /** * gclue_locator_set_time_threshold * @locator: a #GClueLocator * @value: The new threshold value * * Sets the time-threshold to @value. * * Unlike other (real) location sources, Locator instances are unique for each * client application. Which means we only need just one time-threshold value * and hence the reason we have these getter and setters, instead of making use * of the #GClueLocationSource:time-threshold property. **/ void gclue_locator_set_time_threshold (GClueLocator *locator, guint value) { g_return_if_fail (GCLUE_IS_LOCATOR (locator)); reset_time_threshold (locator, GCLUE_LOCATION_SOURCE (locator), value); } geoclue-2.5.2/src/gclue-locator.h000066400000000000000000000050351341441426700166540ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-locator.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_LOCATOR_H #define GCLUE_LOCATOR_H #include #include "gclue-location.h" #include "gclue-enum-types.h" #include "gclue-location-source.h" G_BEGIN_DECLS #define GCLUE_TYPE_LOCATOR (gclue_locator_get_type()) #define GCLUE_LOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_LOCATOR, GClueLocator)) #define GCLUE_LOCATOR_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_LOCATOR, GClueLocator const)) #define GCLUE_LOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_LOCATOR, GClueLocatorClass)) #define GCLUE_IS_LOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_LOCATOR)) #define GCLUE_IS_LOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_LOCATOR)) #define GCLUE_LOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_LOCATOR, GClueLocatorClass)) typedef struct _GClueLocator GClueLocator; typedef struct _GClueLocatorClass GClueLocatorClass; typedef struct _GClueLocatorPrivate GClueLocatorPrivate; struct _GClueLocator { GClueLocationSource parent; /*< private >*/ GClueLocatorPrivate *priv; }; struct _GClueLocatorClass { GClueLocationSourceClass parent_class; }; GType gclue_locator_get_type (void) G_GNUC_CONST; GClueLocator * gclue_locator_new (GClueAccuracyLevel level); GClueAccuracyLevel gclue_locator_get_accuracy_level (GClueLocator *locator); guint gclue_locator_get_time_threshold (GClueLocator *locator); void gclue_locator_set_time_threshold (GClueLocator *locator, guint threshold); G_END_DECLS #endif /* GCLUE_LOCATOR_H */ geoclue-2.5.2/src/gclue-main.c000066400000000000000000000136271341441426700161360ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* main.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include #include #include #include #include "gclue-service-manager.h" #include "gclue-config.h" #define BUS_NAME "org.freedesktop.GeoClue2" /* Commandline options */ static gboolean version = FALSE; static gint inactivity_timeout = 60; static gboolean submit_data = FALSE; static char *submit_nick = NULL; static GOptionEntry entries[] = { { "version", 0, 0, G_OPTION_ARG_NONE, &version, N_("Display version number"), NULL }, { "timeout", 't', 0, G_OPTION_ARG_INT, &inactivity_timeout, N_("Exit after T seconds of inactivity, 0 for never. Default: 60"), "T" }, { "submit-data", 's', 0, G_OPTION_ARG_NONE, &submit_data, N_("Enable submission of network data"), NULL }, { "submit-nick", 'n', 0, G_OPTION_ARG_STRING, &submit_nick, N_("Nickname to submit network data under (2-32 characters)"), "NICK" }, { NULL } }; GMainLoop *main_loop; GClueServiceManager *manager = NULL; guint inactivity_timeout_id = 0; static gboolean on_inactivity_timeout (gpointer user_data) { g_message ("Service not used for %d seconds. Shutting down..", inactivity_timeout); g_main_loop_quit (main_loop); return FALSE; } static void on_active_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueServiceManager *manager = GCLUE_SERVICE_MANAGER (gobject); gboolean active; active = gclue_service_manager_get_active (manager); if (inactivity_timeout <= 0) return; g_debug ("Service %s in use", active? "now" : "not"); if (!active) inactivity_timeout_id = g_timeout_add_seconds (inactivity_timeout, on_inactivity_timeout, NULL); else if (inactivity_timeout_id != 0) { g_source_remove (inactivity_timeout_id); inactivity_timeout_id = 0; } } static void on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { GError *error = NULL; manager = gclue_service_manager_new (connection, &error); if (manager == NULL) { g_critical ("Failed to register server: %s", error->message); g_error_free (error); exit (-2); } g_signal_connect (manager, "notify::active", G_CALLBACK (on_active_notify), NULL); if (inactivity_timeout > 0) inactivity_timeout_id = g_timeout_add_seconds (inactivity_timeout, on_inactivity_timeout, NULL); } static void on_name_lost (GDBusConnection *connection, const gchar *name, gpointer user_data) { g_critical ("Failed to acquire name '%s' on system bus or lost it.", name); exit (-3); } int main (int argc, char **argv) { guint owner_id; GError *error = NULL; GOptionContext *context; GClueConfig *config; setlocale (LC_ALL, ""); textdomain (GETTEXT_PACKAGE); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); g_set_application_name (_("GeoClue")); context = g_option_context_new ("- Geoclue D-Bus service"); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_critical ("option parsing failed: %s\n", error->message); exit (-1); } g_option_context_free (context); if (version) { g_print ("%s\n", PACKAGE_VERSION); exit (0); } config = gclue_config_get_singleton (); if (submit_data) gclue_config_set_wifi_submit_data (config, submit_data); if (submit_nick != NULL) gclue_config_set_wifi_submit_nick (config, submit_nick); owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM, BUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, NULL, on_name_lost, NULL, NULL); main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); if (manager != NULL) g_object_unref (manager); g_bus_unown_name (owner_id); g_main_loop_unref (main_loop); return 0; } geoclue-2.5.2/src/gclue-marshal.list000066400000000000000000000000561341441426700173620ustar00rootroot00000000000000VOID:UINT,UINT,ULONG,ULONG VOID:DOUBLE,DOUBLE geoclue-2.5.2/src/gclue-min-uint.c000066400000000000000000000150741341441426700167500ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-min-uint.c * * Copyright 2018 Collabora Ltd. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include "gclue-min-uint.h" /** * SECTION:gclue-min-uint * @short_description: Easy way to keep track of minimum of a bunch of values * @include: gclue-glib/gclue-location-source.h * * This is a helper class that keeps a list of guint values and the minimum * value from this list. It is used by location sources to use the minimum * time-threshold (location update rate) from all the time-thresholds requested * by different applications. **/ struct _GClueMinUINTPrivate { GHashTable *all_values; gboolean notify_value; }; G_DEFINE_TYPE_WITH_CODE (GClueMinUINT, gclue_min_uint, G_TYPE_OBJECT, G_ADD_PRIVATE (GClueMinUINT)) enum { PROP_0, PROP_VALUE, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; typedef struct { GClueMinUINT *muint; GObject *owner; } OwnerData; static gboolean on_owner_weak_ref_notify_defered (OwnerData *data) { gclue_min_uint_drop_value (data->muint, data->owner); g_object_unref (data->muint); g_slice_free (OwnerData, data); return FALSE; } static void on_owner_weak_ref_notify (gpointer data, GObject *object) { OwnerData *owner_data = g_slice_new (OwnerData); owner_data->muint = GCLUE_MIN_UINT (data); g_object_ref (owner_data->muint); owner_data->owner = object; // Let's ensure owner is really gone before we drop its value g_idle_add ((GSourceFunc) on_owner_weak_ref_notify_defered, owner_data); } static void gclue_min_uint_finalize (GObject *object) { g_clear_pointer (&GCLUE_MIN_UINT (object)->priv->all_values, g_hash_table_unref); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_min_uint_parent_class)->finalize (object); } static void gclue_min_uint_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueMinUINT *muint = GCLUE_MIN_UINT (object); switch (prop_id) { case PROP_VALUE: g_value_set_uint (value, gclue_min_uint_get_value (muint)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_min_uint_class_init (GClueMinUINTClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_min_uint_finalize; object_class->get_property = gclue_min_uint_get_property; gParamSpecs[PROP_VALUE] = g_param_spec_uint ("value", "Value", "The minimum value", 0, G_MAXINT, 0, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_VALUE, gParamSpecs[PROP_VALUE]); } static void gclue_min_uint_init (GClueMinUINT *muint) { muint->priv = G_TYPE_INSTANCE_GET_PRIVATE (muint, GCLUE_TYPE_MIN_UINT, GClueMinUINTPrivate); muint->priv->all_values = g_hash_table_new (g_direct_hash, g_direct_equal); muint->priv->notify_value = TRUE; } /** * gclue_min_uint_new * * Returns: A new #GClueMinUINT instance. **/ GClueMinUINT * gclue_min_uint_new (void) { return g_object_new (GCLUE_TYPE_MIN_UINT, NULL); } /** * gclue_min_uint_get_value * @muint: a #GClueMinUINT * * Returns: The current minimum value from the list. **/ guint gclue_min_uint_get_value (GClueMinUINT *muint) { guint value; GList *values, *l; g_return_val_if_fail (GCLUE_IS_MIN_UINT(muint), 0); if (g_hash_table_size (muint->priv->all_values) == 0) return 0; values = g_hash_table_get_values (muint->priv->all_values); value = GPOINTER_TO_UINT (values->data); for (l = values->next; l; l = l->next) { guint i = GPOINTER_TO_UINT (l->data); if (value > i) { value = i; } } return value; } /** * gclue_min_uint_add_value * @muint: a #GClueMinUINT * @value: A value to add to the list * @owner: the object adding this value * * If @owner has already added a value previously, this call will simply replace * that. i-e Each object can only add one value at a time. **/ void gclue_min_uint_add_value (GClueMinUINT *muint, guint value, GObject *owner) { g_return_if_fail (GCLUE_IS_MIN_UINT(muint)); g_hash_table_replace (muint->priv->all_values, owner, GUINT_TO_POINTER (value)); g_object_weak_ref (owner, on_owner_weak_ref_notify, muint); g_object_notify_by_pspec (G_OBJECT (muint), gParamSpecs[PROP_VALUE]); } /** * gclue_min_uint_drop_value * @muint: a #GClueMinUINT * @owner: the object that adadded a value previously **/ void gclue_min_uint_drop_value (GClueMinUINT *muint, GObject *owner) { g_return_if_fail (GCLUE_IS_MIN_UINT(muint)); if (!g_hash_table_remove (muint->priv->all_values, owner)) { return; } g_object_notify_by_pspec (G_OBJECT (muint), gParamSpecs[PROP_VALUE]); } geoclue-2.5.2/src/gclue-min-uint.h000066400000000000000000000050751341441426700167550ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-client.h * * Copyright 2018 Collabora Ltd. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_MIN_UINT_H #define GCLUE_MIN_UINT_H #include G_BEGIN_DECLS #define GCLUE_TYPE_MIN_UINT (gclue_min_uint_get_type()) #define GCLUE_MIN_UINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_MIN_UINT, GClueMinUINT)) #define GCLUE_MIN_UINT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_MIN_UINT, GClueMinUINT const)) #define GCLUE_MIN_UINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_MIN_UINT, GClueMinUINTClass)) #define GCLUE_IS_MIN_UINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_MIN_UINT)) #define GCLUE_IS_MIN_UINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_MIN_UINT)) #define GCLUE_MIN_UINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_MIN_UINT, GClueMinUINTClass)) typedef struct _GClueMinUINT GClueMinUINT; typedef struct _GClueMinUINTClass GClueMinUINTClass; typedef struct _GClueMinUINTPrivate GClueMinUINTPrivate; struct _GClueMinUINT { GObject parent; /*< private >*/ GClueMinUINTPrivate *priv; }; struct _GClueMinUINTClass { GObjectClass parent_class; }; GType gclue_min_uint_get_type (void) G_GNUC_CONST; GClueMinUINT * gclue_min_uint_new (void); guint gclue_min_uint_get_value (GClueMinUINT *muint); void gclue_min_uint_add_value (GClueMinUINT *muint, guint value, GObject *owner); void gclue_min_uint_drop_value (GClueMinUINT *muint, GObject *owner); G_END_DECLS #endif /* GCLUE_MIN_UINT_H */ geoclue-2.5.2/src/gclue-modem-gps.c000066400000000000000000000216671341441426700171050ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include "gclue-modem-gps.h" #include "gclue-modem-manager.h" #include "gclue-location.h" /** * SECTION:gclue-modem-gps * @short_description: GPS modem-based geolocation source * @include: gclue-glib/gclue-modem-gps.h * * Contains functions to get the geolocation from a GPS modem. **/ struct _GClueModemGPSPrivate { GClueModem *modem; GCancellable *cancellable; gulong gps_notify_id; }; G_DEFINE_TYPE_WITH_CODE (GClueModemGPS, gclue_modem_gps, GCLUE_TYPE_LOCATION_SOURCE, G_ADD_PRIVATE (GClueModemGPS)) static gboolean gclue_modem_gps_start (GClueLocationSource *source); static gboolean gclue_modem_gps_stop (GClueLocationSource *source); static void refresh_accuracy_level (GClueModemGPS *source) { GClueAccuracyLevel new, existing; existing = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (source)); if (gclue_modem_get_is_gps_available (source->priv->modem)) new = GCLUE_ACCURACY_LEVEL_EXACT; else new = GCLUE_ACCURACY_LEVEL_NONE; if (new != existing) { g_debug ("Available accuracy level from %s: %u", G_OBJECT_TYPE_NAME (source), new); g_object_set (G_OBJECT (source), "available-accuracy-level", new, NULL); } } static void on_gps_enabled (GObject *source_object, GAsyncResult *result, gpointer user_data) { GClueModemGPS *source = GCLUE_MODEM_GPS (user_data); GError *error = NULL; if (!gclue_modem_enable_gps_finish (source->priv->modem, result, &error)) { g_warning ("Failed to enable GPS: %s", error->message); g_error_free (error); } } static void on_is_gps_available_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueModemGPS *source = GCLUE_MODEM_GPS (user_data); GClueModemGPSPrivate *priv = source->priv; refresh_accuracy_level (source); if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (source)) && gclue_modem_get_is_gps_available (priv->modem)) gclue_modem_enable_gps (priv->modem, priv->cancellable, on_gps_enabled, source); } static void on_time_threshold_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueModemGPS *source = GCLUE_MODEM_GPS (user_data); guint threshold; threshold = gclue_min_uint_get_value (GCLUE_MIN_UINT (gobject)); gclue_modem_set_time_threshold (source->priv->modem, threshold); } static void gclue_modem_gps_finalize (GObject *ggps) { GClueModemGPSPrivate *priv = GCLUE_MODEM_GPS (ggps)->priv; G_OBJECT_CLASS (gclue_modem_gps_parent_class)->finalize (ggps); g_signal_handler_disconnect (priv->modem, priv->gps_notify_id); priv->gps_notify_id = 0; g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); g_clear_object (&priv->modem); } static void gclue_modem_gps_class_init (GClueModemGPSClass *klass) { GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *ggps_class = G_OBJECT_CLASS (klass); ggps_class->finalize = gclue_modem_gps_finalize; source_class->start = gclue_modem_gps_start; source_class->stop = gclue_modem_gps_stop; } static void gclue_modem_gps_init (GClueModemGPS *source) { GClueModemGPSPrivate *priv; GClueMinUINT *threshold; source->priv = G_TYPE_INSTANCE_GET_PRIVATE ((source), GCLUE_TYPE_MODEM_GPS, GClueModemGPSPrivate); priv = source->priv; priv->cancellable = g_cancellable_new (); priv->modem = gclue_modem_manager_get_singleton (); priv->gps_notify_id = g_signal_connect (priv->modem, "notify::is-gps-available", G_CALLBACK (on_is_gps_available_notify), source); threshold = gclue_location_source_get_time_threshold (GCLUE_LOCATION_SOURCE (source)); g_signal_connect (threshold, "notify::value", G_CALLBACK (on_time_threshold_changed), source); } static void on_modem_gps_destroyed (gpointer data, GObject *where_the_object_was) { GClueModemGPS **source = (GClueModemGPS **) data; *source = NULL; } /** * gclue_modem_gps_get_singleton: * * Get the #GClueModemGPS singleton. * * Returns: (transfer full): a new ref to #GClueModemGPS. Use g_object_unref() * when done. **/ GClueModemGPS * gclue_modem_gps_get_singleton (void) { static GClueModemGPS *source = NULL; if (source == NULL) { source = g_object_new (GCLUE_TYPE_MODEM_GPS, NULL); g_object_weak_ref (G_OBJECT (source), on_modem_gps_destroyed, &source); } else g_object_ref (source); return source; } static void on_fix_gps (GClueModem *modem, const char *gga, gpointer user_data) { GClueLocationSource *source = GCLUE_LOCATION_SOURCE (user_data); GClueLocation *location; GError *error = NULL; location = gclue_location_create_from_gga (gga, &error); if (error != NULL) { g_warning ("Error: %s", error->message); g_clear_error (&error); return; } gclue_location_source_set_location (source, location); } static gboolean gclue_modem_gps_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; GClueModemGPSPrivate *priv; g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); priv = GCLUE_MODEM_GPS (source)->priv; base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_modem_gps_parent_class); if (!base_class->start (source)) return FALSE; g_signal_connect (priv->modem, "fix-gps", G_CALLBACK (on_fix_gps), source); if (gclue_modem_get_is_gps_available (priv->modem)) gclue_modem_enable_gps (priv->modem, priv->cancellable, on_gps_enabled, source); return TRUE; } static gboolean gclue_modem_gps_stop (GClueLocationSource *source) { GClueModemGPSPrivate *priv = GCLUE_MODEM_GPS (source)->priv; GClueLocationSourceClass *base_class; GError *error = NULL; g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_modem_gps_parent_class); if (!base_class->stop (source)) return FALSE; g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modem), G_CALLBACK (on_fix_gps), source); if (gclue_modem_get_is_gps_available (priv->modem)) if (!gclue_modem_disable_gps (priv->modem, priv->cancellable, &error)) { g_warning ("Failed to disable GPS: %s", error->message); g_error_free (error); } return TRUE; } geoclue-2.5.2/src/gclue-modem-gps.h000066400000000000000000000046271341441426700171070ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_MODEM_GPS_H #define GCLUE_MODEM_GPS_H #include #include #include "gclue-location-source.h" G_BEGIN_DECLS GType gclue_modem_gps_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_MODEM_GPS (gclue_modem_gps_get_type ()) #define GCLUE_MODEM_GPS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_MODEM_GPS, GClueModemGPS)) #define GCLUE_IS_MODEM_GPS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_MODEM_GPS)) #define GCLUE_MODEM_GPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_MODEM_GPS, GClueModemGPSClass)) #define GCLUE_IS_MODEM_GPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_MODEM_GPS)) #define GCLUE_MODEM_GPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_MODEM_GPS, GClueModemGPSClass)) /** * GClueModemGPS: * * All the fields in the #GClueModemGPS structure are private and should never be accessed directly. **/ typedef struct _GClueModemGPS GClueModemGPS; typedef struct _GClueModemGPSClass GClueModemGPSClass; typedef struct _GClueModemGPSPrivate GClueModemGPSPrivate; struct _GClueModemGPS { /* */ GClueLocationSource parent_instance; GClueModemGPSPrivate *priv; }; /** * GClueModemGPSClass: * * All the fields in the #GClueModemGPSClass structure are private and should never be accessed directly. **/ struct _GClueModemGPSClass { /* */ GClueLocationSourceClass parent_class; }; GClueModemGPS * gclue_modem_gps_get_singleton (void); G_END_DECLS #endif /* GCLUE_MODEM_GPS_H */ geoclue-2.5.2/src/gclue-modem-manager.c000066400000000000000000001100161341441426700177110ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include #include "gclue-modem-manager.h" #include "gclue-marshal.h" /** * SECTION:gclue-modem-manager * @short_description: Modem handler * * This class is used by GClue3G and GClueModemGPS to deal with modem through * ModemManager. **/ static void gclue_modem_interface_init (GClueModemInterface *iface); struct _GClueModemManagerPrivate { MMManager *manager; MMObject *mm_object; MMModem *modem; MMModemLocation *modem_location; MMLocation3gpp *location_3gpp; MMLocationGpsNmea *location_nmea; GCancellable *cancellable; MMModemLocationSource caps; /* Caps we set or are going to set */ guint time_threshold; }; G_DEFINE_TYPE_WITH_CODE (GClueModemManager, gclue_modem_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GCLUE_TYPE_MODEM, gclue_modem_interface_init) G_ADD_PRIVATE (GClueModemManager)) enum { PROP_0, PROP_IS_3G_AVAILABLE, PROP_IS_CDMA_AVAILABLE, PROP_IS_GPS_AVAILABLE, PROP_TIME_THRESHOLD, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; enum { FIX_3G, FIX_CDMA, FIX_GPS, SIGNAL_LAST }; static guint signals[SIGNAL_LAST]; static gboolean gclue_modem_manager_get_is_3g_available (GClueModem *modem); static gboolean gclue_modem_manager_get_is_cdma_available (GClueModem *modem); static gboolean gclue_modem_manager_get_is_gps_available (GClueModem *modem); static guint gclue_modem_manager_get_time_threshold (GClueModem *modem); static void gclue_modem_manager_set_time_threshold (GClueModem *modem, guint time_threshold); static void gclue_modem_manager_enable_3g (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); static gboolean gclue_modem_manager_enable_3g_finish (GClueModem *modem, GAsyncResult *result, GError **error); static void gclue_modem_manager_enable_cdma (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); static gboolean gclue_modem_manager_enable_cdma_finish (GClueModem *modem, GAsyncResult *result, GError **error); static void gclue_modem_manager_enable_gps (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); static gboolean gclue_modem_manager_enable_gps_finish (GClueModem *modem, GAsyncResult *result, GError **error); static gboolean gclue_modem_manager_disable_3g (GClueModem *modem, GCancellable *cancellable, GError **error); static gboolean gclue_modem_manager_disable_cdma (GClueModem *modem, GCancellable *cancellable, GError **error); static gboolean gclue_modem_manager_disable_gps (GClueModem *modem, GCancellable *cancellable, GError **error); static void gclue_modem_manager_finalize (GObject *gmodem) { GClueModemManager *manager = GCLUE_MODEM_MANAGER (gmodem); GClueModemManagerPrivate *priv = manager->priv; G_OBJECT_CLASS (gclue_modem_manager_parent_class)->finalize (gmodem); g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); g_clear_object (&priv->manager); g_clear_object (&priv->mm_object); g_clear_object (&priv->modem); g_clear_object (&priv->modem_location); } static void gclue_modem_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueModem *modem = GCLUE_MODEM (object); switch (prop_id) { case PROP_IS_3G_AVAILABLE: g_value_set_boolean (value, gclue_modem_get_is_3g_available (modem)); break; case PROP_IS_CDMA_AVAILABLE: g_value_set_boolean (value, gclue_modem_get_is_cdma_available (modem)); break; case PROP_IS_GPS_AVAILABLE: g_value_set_boolean (value, gclue_modem_get_is_gps_available (modem)); break; case PROP_TIME_THRESHOLD: g_value_set_uint (value, gclue_modem_get_time_threshold (modem)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_modem_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueModem *modem = GCLUE_MODEM (object); switch (prop_id) { case PROP_TIME_THRESHOLD: gclue_modem_set_time_threshold (modem, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_modem_manager_constructed (GObject *object); static void gclue_modem_manager_class_init (GClueModemManagerClass *klass) { GObjectClass *gmodem_class = G_OBJECT_CLASS (klass); gmodem_class->get_property = gclue_modem_manager_get_property; gmodem_class->set_property = gclue_modem_manager_set_property; gmodem_class->finalize = gclue_modem_manager_finalize; gmodem_class->constructed = gclue_modem_manager_constructed; g_object_class_override_property (gmodem_class, PROP_IS_3G_AVAILABLE, "is-3g-available"); gParamSpecs[PROP_IS_3G_AVAILABLE] = g_object_class_find_property (gmodem_class, "is-3g-available"); g_object_class_override_property (gmodem_class, PROP_IS_CDMA_AVAILABLE, "is-cdma-available"); gParamSpecs[PROP_IS_CDMA_AVAILABLE] = g_object_class_find_property (gmodem_class, "is-cdma-available"); g_object_class_override_property (gmodem_class, PROP_IS_GPS_AVAILABLE, "is-gps-available"); gParamSpecs[PROP_IS_GPS_AVAILABLE] = g_object_class_find_property (gmodem_class, "is-gps-available"); g_object_class_override_property (gmodem_class, PROP_TIME_THRESHOLD, "time-threshold"); gParamSpecs[PROP_TIME_THRESHOLD] = g_object_class_find_property (gmodem_class, "time-threshold"); signals[FIX_3G] = g_signal_lookup ("fix-3g", GCLUE_TYPE_MODEM); signals[FIX_CDMA] = g_signal_lookup ("fix-cdma", GCLUE_TYPE_MODEM); signals[FIX_GPS] = g_signal_lookup ("fix-gps", GCLUE_TYPE_MODEM); } static void gclue_modem_interface_init (GClueModemInterface *iface) { iface->get_is_3g_available = gclue_modem_manager_get_is_3g_available; iface->get_is_cdma_available = gclue_modem_manager_get_is_cdma_available; iface->get_is_gps_available = gclue_modem_manager_get_is_gps_available; iface->get_time_threshold = gclue_modem_manager_get_time_threshold; iface->set_time_threshold = gclue_modem_manager_set_time_threshold; iface->enable_3g = gclue_modem_manager_enable_3g; iface->enable_3g_finish = gclue_modem_manager_enable_3g_finish; iface->enable_cdma = gclue_modem_manager_enable_cdma; iface->enable_cdma_finish = gclue_modem_manager_enable_cdma_finish; iface->enable_gps = gclue_modem_manager_enable_gps; iface->enable_gps_finish = gclue_modem_manager_enable_gps_finish; iface->disable_3g = gclue_modem_manager_disable_3g; iface->disable_cdma = gclue_modem_manager_disable_cdma; iface->disable_gps = gclue_modem_manager_disable_gps; } static gboolean is_location_3gpp_same (GClueModemManager *manager, guint new_mcc, guint new_mnc, gulong new_lac, gulong new_cell_id) { GClueModemManagerPrivate *priv = manager->priv; guint mcc, mnc; gulong lac, cell_id; if (priv->location_3gpp == NULL) return FALSE; mcc = mm_location_3gpp_get_mobile_country_code (priv->location_3gpp); mnc = mm_location_3gpp_get_mobile_network_code (priv->location_3gpp); lac = mm_location_3gpp_get_location_area_code (priv->location_3gpp); cell_id = mm_location_3gpp_get_cell_id (priv->location_3gpp); return (mcc == new_mcc && mnc == new_mnc && lac == new_lac && cell_id == new_cell_id); } static void on_get_3gpp_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); GClueModemManagerPrivate *priv = manager->priv; MMModemLocation *modem_location = MM_MODEM_LOCATION (source_object); MMLocation3gpp *location_3gpp; GError *error = NULL; guint mcc, mnc; gulong lac, cell_id; location_3gpp = mm_modem_location_get_3gpp_finish (modem_location, res, &error); if (error != NULL) { g_warning ("Failed to get location from 3GPP: %s", error->message); g_error_free (error); return; } if (location_3gpp == NULL) { g_debug ("No 3GPP"); return; } mcc = mm_location_3gpp_get_mobile_country_code (location_3gpp); mnc = mm_location_3gpp_get_mobile_network_code (location_3gpp); lac = mm_location_3gpp_get_location_area_code (location_3gpp); cell_id = mm_location_3gpp_get_cell_id (location_3gpp); if (is_location_3gpp_same (manager, mcc, mnc, lac, cell_id)) { g_debug ("New 3GPP location is same as last one"); return; } g_clear_object (&priv->location_3gpp); priv->location_3gpp = location_3gpp; g_signal_emit (manager, signals[FIX_3G], 0, mcc, mnc, lac, cell_id); } static void on_get_cdma_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); MMModemLocation *modem_location = MM_MODEM_LOCATION (source_object); MMLocationCdmaBs *location_cdma; GError *error = NULL; location_cdma = mm_modem_location_get_cdma_bs_finish (modem_location, res, &error); if (error != NULL) { g_warning ("Failed to get location from 3GPP: %s", error->message); g_error_free (error); return; } if (location_cdma == NULL) { g_debug ("No CDMA"); return; } g_signal_emit (manager, signals[FIX_CDMA], 0, mm_location_cdma_bs_get_latitude (location_cdma), mm_location_cdma_bs_get_longitude (location_cdma)); } static gboolean is_location_gga_same (GClueModemManager *manager, const char *new_gga) { GClueModemManagerPrivate *priv = manager->priv; const char *gga; if (priv->location_nmea == NULL) return FALSE; gga = mm_location_gps_nmea_get_trace (priv->location_nmea, "$GPGGA"); return (g_strcmp0 (gga, new_gga) == 0); } static void on_get_gps_nmea_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); GClueModemManagerPrivate *priv = manager->priv; MMModemLocation *modem_location = MM_MODEM_LOCATION (source_object); MMLocationGpsNmea *location_nmea; const char *gga; GError *error = NULL; location_nmea = mm_modem_location_get_gps_nmea_finish (modem_location, res, &error); if (error != NULL) { g_warning ("Failed to get location from NMEA information: %s", error->message); g_error_free (error); return; } if (location_nmea == NULL) { g_debug ("No NMEA"); return; } gga = mm_location_gps_nmea_get_trace (location_nmea, "$GPGGA"); if (gga == NULL) { g_debug ("No GGA trace"); return; } if (is_location_gga_same (manager, gga)) { g_debug ("New GGA trace is same as last one: %s", gga); return; } g_clear_object (&priv->location_nmea); priv->location_nmea = location_nmea; g_debug ("New GPGGA trace: %s", gga); g_signal_emit (manager, signals[FIX_GPS], 0, gga); } static void on_location_changed (GObject *modem_object, GParamSpec *pspec, gpointer user_data) { MMModemLocation *modem_location = MM_MODEM_LOCATION (modem_object); GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); if ((manager->priv->caps & MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI) != 0) mm_modem_location_get_3gpp (modem_location, manager->priv->cancellable, on_get_3gpp_ready, manager); if ((manager->priv->caps & MM_MODEM_LOCATION_SOURCE_CDMA_BS) != 0) mm_modem_location_get_cdma_bs (modem_location, manager->priv->cancellable, on_get_cdma_ready, manager); if ((manager->priv->caps & MM_MODEM_LOCATION_SOURCE_GPS_NMEA) != 0) mm_modem_location_get_gps_nmea (modem_location, manager->priv->cancellable, on_get_gps_nmea_ready, manager); } static void on_modem_location_setup (GObject *modem_object, GAsyncResult *res, gpointer user_data) { GTask *task = G_TASK (user_data); GClueModemManager *manager; GClueModemManagerPrivate *priv; GError *error = NULL; if (!mm_modem_location_setup_finish (MM_MODEM_LOCATION (modem_object), res, &error)) { g_task_return_error (task, error); goto out; } manager = GCLUE_MODEM_MANAGER (g_task_get_source_object (task)); priv = manager->priv; g_debug ("Modem '%s' setup.", mm_object_get_path (priv->mm_object)); on_location_changed (modem_object, NULL, manager); g_task_return_boolean (task, TRUE); out: g_object_unref (task); } static void enable_caps (GClueModemManager *manager, MMModemLocationSource caps, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GClueModemManagerPrivate *priv = manager->priv; GTask *task; priv->caps |= caps; task = g_task_new (manager, cancellable, callback, user_data); priv = GCLUE_MODEM_MANAGER (g_task_get_source_object (task))->priv; caps = mm_modem_location_get_enabled (priv->modem_location) | priv->caps; mm_modem_location_setup (priv->modem_location, caps, TRUE, g_task_get_cancellable (task), on_modem_location_setup, task); } static gboolean enable_caps_finish (GClueModemManager *manager, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (manager), FALSE); g_return_val_if_fail (g_task_is_valid (result, manager), FALSE); return g_task_propagate_boolean (G_TASK (result), error); } static gboolean clear_caps (GClueModemManager *manager, MMModemLocationSource caps, GCancellable *cancellable, GError **error) { GClueModemManagerPrivate *priv; priv = manager->priv; if (priv->modem_location == NULL) return TRUE; priv->caps &= ~caps; return mm_modem_location_setup_sync (priv->modem_location, priv->caps, FALSE, cancellable, error); } static gboolean modem_has_caps (GClueModemManager *manager, MMModemLocationSource caps) { MMModemLocation *modem_location = manager->priv->modem_location; MMModemLocationSource avail_caps; if (modem_location == NULL) return FALSE; avail_caps = mm_modem_location_get_capabilities (modem_location); return ((caps & avail_caps) != 0); } static void on_mm_object_added (GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data); static void on_mm_modem_state_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { MMModem *mm_modem = MM_MODEM (gobject); GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); GClueModemManagerPrivate *priv = manager->priv; GDBusObjectManager *obj_manager = G_DBUS_OBJECT_MANAGER (priv->manager); const char *path = mm_modem_get_path (mm_modem); GDBusObject *object; if (priv->mm_object != NULL) { // In the meantime another modem with location caps was found. g_signal_handlers_disconnect_by_func (mm_modem, on_mm_modem_state_notify, user_data); g_object_unref (gobject); return; } if (mm_modem_get_state (mm_modem) < MM_MODEM_STATE_ENABLED) return; g_debug ("Modem '%s' now enabled", path); g_signal_handlers_disconnect_by_func (mm_modem, on_mm_modem_state_notify, user_data); object = g_dbus_object_manager_get_object (obj_manager, path); on_mm_object_added (obj_manager, object, user_data); g_object_unref (mm_modem); } static void on_gps_refresh_rate_set (GObject *source_object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; ret = mm_modem_location_set_gps_refresh_rate_finish (MM_MODEM_LOCATION (source_object), res, &error); if (!ret) { g_warning ("Failed to set GPS refresh rate: %s", error->message); g_error_free (error); } } static void on_mm_object_added (GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data) { MMObject *mm_object = MM_OBJECT (object); GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); MMModem *mm_modem; MMModemLocation *modem_location; if (manager->priv->mm_object != NULL) return; g_debug ("New modem '%s'", mm_object_get_path (mm_object)); mm_modem = mm_object_get_modem (mm_object); if (mm_modem_get_state (mm_modem) < MM_MODEM_STATE_ENABLED) { g_debug ("Modem '%s' not enabled", mm_object_get_path (mm_object)); g_signal_connect_object (mm_modem, "notify::state", G_CALLBACK (on_mm_modem_state_notify), manager, 0); return; } modem_location = mm_object_peek_modem_location (mm_object); if (modem_location == NULL) return; g_debug ("Modem '%s' has location capabilities", mm_object_get_path (mm_object)); manager->priv->mm_object = g_object_ref (mm_object); manager->priv->modem = mm_modem; manager->priv->modem_location = mm_object_get_modem_location (mm_object); mm_modem_location_set_gps_refresh_rate (manager->priv->modem_location, manager->priv->time_threshold, manager->priv->cancellable, on_gps_refresh_rate_set, NULL); g_signal_connect (G_OBJECT (manager->priv->modem_location), "notify::location", G_CALLBACK (on_location_changed), manager); g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_IS_3G_AVAILABLE]); g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_IS_CDMA_AVAILABLE]); g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_IS_GPS_AVAILABLE]); } static void on_mm_object_removed (GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data) { MMObject *mm_object = MM_OBJECT (object); GClueModemManager *manager = GCLUE_MODEM_MANAGER (user_data); GClueModemManagerPrivate *priv = manager->priv; if (priv->mm_object == NULL || priv->mm_object != mm_object) return; g_debug ("Modem '%s' removed.", mm_object_get_path (priv->mm_object)); g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modem_location), G_CALLBACK (on_location_changed), user_data); g_clear_object (&priv->mm_object); g_clear_object (&priv->modem); g_clear_object (&priv->modem_location); g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_IS_3G_AVAILABLE]); g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_IS_CDMA_AVAILABLE]); g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_IS_GPS_AVAILABLE]); } static void on_manager_new_ready (GObject *modem_object, GAsyncResult *res, gpointer user_data) { GClueModemManagerPrivate *priv = GCLUE_MODEM_MANAGER (user_data)->priv; GList *objects, *node; GError *error = NULL; priv->manager = mm_manager_new_finish (res, &error); if (priv->manager == NULL) { g_warning ("Failed to connect to ModemManager: %s", error->message); g_error_free (error); return; } objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (priv->manager)); for (node = objects; node != NULL; node = node->next) { on_mm_object_added (G_DBUS_OBJECT_MANAGER (priv->manager), G_DBUS_OBJECT (node->data), user_data); /* FIXME: Currently we only support 1 modem device */ if (priv->modem != NULL) break; } g_list_free_full (objects, g_object_unref); g_signal_connect (G_OBJECT (priv->manager), "object-added", G_CALLBACK (on_mm_object_added), user_data); g_signal_connect (G_OBJECT (priv->manager), "object-removed", G_CALLBACK (on_mm_object_removed), user_data); } static void on_bus_get_ready (GObject *modem_object, GAsyncResult *res, gpointer user_data) { GClueModemManagerPrivate *priv = GCLUE_MODEM_MANAGER (user_data)->priv; GDBusConnection *connection; GError *error = NULL; connection = g_bus_get_finish (res, &error); if (connection == NULL) { g_warning ("Failed to connect to system D-Bus: %s", error->message); g_error_free (error); return; } mm_manager_new (connection, 0, priv->cancellable, on_manager_new_ready, user_data); } static void gclue_modem_manager_constructed (GObject *object) { GClueModemManagerPrivate *priv = GCLUE_MODEM_MANAGER (object)->priv; G_OBJECT_CLASS (gclue_modem_manager_parent_class)->constructed (object); priv->cancellable = g_cancellable_new (); g_bus_get (G_BUS_TYPE_SYSTEM, priv->cancellable, on_bus_get_ready, object); } static void gclue_modem_manager_init (GClueModemManager *manager) { manager->priv = G_TYPE_INSTANCE_GET_PRIVATE ((manager), GCLUE_TYPE_MODEM_MANAGER, GClueModemManagerPrivate); } static void on_modem_destroyed (gpointer data, GObject *where_the_object_was) { GClueModemManager **manager = (GClueModemManager **) data; *manager = NULL; } /** * gclue_modem_manager_get_singleton: * * Get the #GClueModemManager singleton. * * Returns: (transfer full): a #GClueModemManager as #GClueModem. **/ GClueModem * gclue_modem_manager_get_singleton (void) { static GClueModemManager *manager = NULL; if (manager == NULL) { manager = g_object_new (GCLUE_TYPE_MODEM_MANAGER, NULL); g_object_weak_ref (G_OBJECT (manager), on_modem_destroyed, &manager); } else g_object_ref (manager); return GCLUE_MODEM (manager); } static gboolean gclue_modem_manager_get_is_3g_available (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); return modem_has_caps (GCLUE_MODEM_MANAGER (modem), MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI); } static gboolean gclue_modem_manager_get_is_cdma_available (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); return modem_has_caps (GCLUE_MODEM_MANAGER (modem), MM_MODEM_LOCATION_SOURCE_CDMA_BS); } static gboolean gclue_modem_manager_get_is_gps_available (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); return modem_has_caps (GCLUE_MODEM_MANAGER (modem), MM_MODEM_LOCATION_SOURCE_GPS_NMEA); } static guint gclue_modem_manager_get_time_threshold (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), 0); return GCLUE_MODEM_MANAGER (modem)->priv->time_threshold; } static void gclue_modem_manager_set_time_threshold (GClueModem *modem, guint time_threshold) { GClueModemManager *manager; g_return_if_fail (GCLUE_IS_MODEM_MANAGER (modem)); manager = GCLUE_MODEM_MANAGER (modem); manager->priv->time_threshold = time_threshold; if (manager->priv->modem_location != NULL) { mm_modem_location_set_gps_refresh_rate (manager->priv->modem_location, time_threshold, manager->priv->cancellable, on_gps_refresh_rate_set, NULL); } g_object_notify_by_pspec (G_OBJECT (manager), gParamSpecs[PROP_TIME_THRESHOLD]); g_debug ("%s: New time-threshold: %u", G_OBJECT_TYPE_NAME (manager), time_threshold); } static void gclue_modem_manager_enable_3g (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (GCLUE_IS_MODEM_MANAGER (modem)); g_return_if_fail (gclue_modem_manager_get_is_3g_available (modem)); enable_caps (GCLUE_MODEM_MANAGER (modem), MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, cancellable, callback, user_data); } static gboolean gclue_modem_manager_enable_3g_finish (GClueModem *modem, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); return enable_caps_finish (GCLUE_MODEM_MANAGER (modem), result, error); } static void gclue_modem_manager_enable_cdma (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (GCLUE_IS_MODEM_MANAGER (modem)); g_return_if_fail (gclue_modem_manager_get_is_cdma_available (modem)); enable_caps (GCLUE_MODEM_MANAGER (modem), MM_MODEM_LOCATION_SOURCE_CDMA_BS, cancellable, callback, user_data); } static gboolean gclue_modem_manager_enable_cdma_finish (GClueModem *modem, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); return enable_caps_finish (GCLUE_MODEM_MANAGER (modem), result, error); } static void gclue_modem_manager_enable_gps (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (GCLUE_IS_MODEM_MANAGER (modem)); g_return_if_fail (gclue_modem_manager_get_is_gps_available (modem)); enable_caps (GCLUE_MODEM_MANAGER (modem), MM_MODEM_LOCATION_SOURCE_GPS_NMEA, cancellable, callback, user_data); } static gboolean gclue_modem_manager_enable_gps_finish (GClueModem *modem, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); return enable_caps_finish (GCLUE_MODEM_MANAGER (modem), result, error); } static gboolean gclue_modem_manager_disable_3g (GClueModem *modem, GCancellable *cancellable, GError **error) { GClueModemManager *manager; g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); g_return_val_if_fail (gclue_modem_manager_get_is_3g_available (modem), FALSE); manager = GCLUE_MODEM_MANAGER (modem); g_clear_object (&manager->priv->location_3gpp); g_debug ("Clearing 3GPP location caps from modem"); return clear_caps (manager, MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, cancellable, error); } static gboolean gclue_modem_manager_disable_cdma (GClueModem *modem, GCancellable *cancellable, GError **error) { GClueModemManager *manager; g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); g_return_val_if_fail (gclue_modem_manager_get_is_cdma_available (modem), FALSE); manager = GCLUE_MODEM_MANAGER (modem); g_clear_object (&manager->priv->location_3gpp); g_debug ("Clearing CDMA location caps from modem"); return clear_caps (manager, MM_MODEM_LOCATION_SOURCE_CDMA_BS, cancellable, error); } static gboolean gclue_modem_manager_disable_gps (GClueModem *modem, GCancellable *cancellable, GError **error) { GClueModemManager *manager; g_return_val_if_fail (GCLUE_IS_MODEM_MANAGER (modem), FALSE); g_return_val_if_fail (gclue_modem_manager_get_is_gps_available (modem), FALSE); manager = GCLUE_MODEM_MANAGER (modem); g_clear_object (&manager->priv->location_nmea); g_debug ("Clearing GPS NMEA caps from modem"); return clear_caps (manager, MM_MODEM_LOCATION_SOURCE_GPS_NMEA, cancellable, error); } geoclue-2.5.2/src/gclue-modem-manager.h000066400000000000000000000046771341441426700177350ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_MODEM_MANAGER_H #define GCLUE_MODEM_MANAGER_H #include #include "gclue-modem.h" G_BEGIN_DECLS GType gclue_modem_manager_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_MODEM_MANAGER (gclue_modem_manager_get_type ()) #define GCLUE_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_MODEM_MANAGER, GClueModemManager)) #define GCLUE_IS_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_MODEM_MANAGER)) #define GCLUE_MODEM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_MODEM_MANAGER, GClueModemManagerClass)) #define GCLUE_IS_MODEM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_MODEM_MANAGER)) #define GCLUE_MODEM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_MODEM_MANAGER, GClueModemManagerClass)) /** * GClueModemManager: * * All the fields in the #GClueModemManager structure are private and should never be accessed directly. **/ typedef struct _GClueModemManager GClueModemManager; typedef struct _GClueModemManagerClass GClueModemManagerClass; typedef struct _GClueModemManagerPrivate GClueModemManagerPrivate; struct _GClueModemManager { /* */ GObject parent_instance; GClueModemManagerPrivate *priv; }; /** * GClueModemManagerClass: * * All the fields in the #GClueModemManagerClass structure are private and should never be accessed directly. **/ struct _GClueModemManagerClass { /* */ GObjectClass parent_class; }; GClueModem* gclue_modem_manager_get_singleton (void); G_END_DECLS #endif /* GCLUE_MODEM_MANAGER_H */ geoclue-2.5.2/src/gclue-modem.c000066400000000000000000000233461341441426700163120ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include "gclue-modem.h" #include "gclue-marshal.h" /** * SECTION:gclue-modem * @short_description: Modem handler * * This interface is implemented by Modem handing modules. Currently there is * only one class, ModemManager implementing this interface. Normally it * wouldn't make sense to have it separate from the class but intention is to * make it very easy to add alternative modem sources, e.g ofono-based. **/ G_DEFINE_INTERFACE (GClueModem, gclue_modem, 0); static void gclue_modem_default_init (GClueModemInterface *iface) { GParamSpec *spec; spec = g_param_spec_boolean ("is-3g-available", "Is3GAvailable", "Is 3G Available?", FALSE, G_PARAM_READABLE); g_object_interface_install_property (iface, spec); spec = g_param_spec_boolean ("is-cdma-available", "IsCDMAAvailable", "Is CDMA Available?", FALSE, G_PARAM_READABLE); g_object_interface_install_property (iface, spec); spec = g_param_spec_boolean ("is-gps-available", "IsGPSAvailable", "Is GPS Available?", FALSE, G_PARAM_READABLE); g_object_interface_install_property (iface, spec); spec = g_param_spec_uint ("time-threshold", "TimeThreshold", "Time Threshold", 0, G_MAXUINT, 0, G_PARAM_READWRITE); g_object_interface_install_property (iface, spec); g_signal_new ("fix-3g", GCLUE_TYPE_MODEM, G_SIGNAL_RUN_LAST, 0, NULL, NULL, gclue_marshal_VOID__UINT_UINT_ULONG_ULONG, G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_ULONG, G_TYPE_ULONG); g_signal_new ("fix-cdma", GCLUE_TYPE_MODEM, G_SIGNAL_RUN_LAST, 0, NULL, NULL, gclue_marshal_VOID__DOUBLE_DOUBLE, G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE); g_signal_new ("fix-gps", GCLUE_TYPE_MODEM, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } gboolean gclue_modem_get_is_3g_available (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->get_is_3g_available (modem); } gboolean gclue_modem_get_is_cdma_available (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->get_is_cdma_available (modem); } gboolean gclue_modem_get_is_gps_available (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->get_is_gps_available (modem); } guint gclue_modem_get_time_threshold (GClueModem *modem) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), 0); return GCLUE_MODEM_GET_INTERFACE (modem)->get_time_threshold (modem); } void gclue_modem_set_time_threshold (GClueModem *modem, guint threshold) { g_return_if_fail (GCLUE_IS_MODEM (modem)); return GCLUE_MODEM_GET_INTERFACE (modem)->set_time_threshold (modem, threshold); } void gclue_modem_enable_3g (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (GCLUE_IS_MODEM (modem)); g_return_if_fail (gclue_modem_get_is_3g_available (modem)); GCLUE_MODEM_GET_INTERFACE (modem)->enable_3g (modem, cancellable, callback, user_data); } gboolean gclue_modem_enable_3g_finish (GClueModem *modem, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->enable_3g_finish (modem, result, error); } void gclue_modem_enable_cdma (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (GCLUE_IS_MODEM (modem)); g_return_if_fail (gclue_modem_get_is_cdma_available (modem)); GCLUE_MODEM_GET_INTERFACE (modem)->enable_cdma (modem, cancellable, callback, user_data); } gboolean gclue_modem_enable_cdma_finish (GClueModem *modem, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->enable_cdma_finish (modem, result, error); } void gclue_modem_enable_gps (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (GCLUE_IS_MODEM (modem)); g_return_if_fail (gclue_modem_get_is_gps_available (modem)); GCLUE_MODEM_GET_INTERFACE (modem)->enable_gps (modem, cancellable, callback, user_data); } gboolean gclue_modem_enable_gps_finish (GClueModem *modem, GAsyncResult *result, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->enable_gps_finish (modem, result, error); } gboolean gclue_modem_disable_3g (GClueModem *modem, GCancellable *cancellable, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); g_return_val_if_fail (gclue_modem_get_is_3g_available (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->disable_3g (modem, cancellable, error); } gboolean gclue_modem_disable_cdma (GClueModem *modem, GCancellable *cancellable, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); g_return_val_if_fail (gclue_modem_get_is_cdma_available (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->disable_cdma (modem, cancellable, error); } gboolean gclue_modem_disable_gps (GClueModem *modem, GCancellable *cancellable, GError **error) { g_return_val_if_fail (GCLUE_IS_MODEM (modem), FALSE); g_return_val_if_fail (gclue_modem_get_is_gps_available (modem), FALSE); return GCLUE_MODEM_GET_INTERFACE (modem)->disable_gps (modem, cancellable, error); } geoclue-2.5.2/src/gclue-modem.h000066400000000000000000000154041341441426700163130ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_MODEM_H #define GCLUE_MODEM_H #include G_BEGIN_DECLS GType gclue_modem_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_MODEM (gclue_modem_get_type ()) #define GCLUE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_MODEM, GClueModem)) #define GCLUE_IS_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_MODEM)) #define GCLUE_MODEM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GCLUE_TYPE_MODEM, GClueModemInterface)) typedef struct _GClueModem GClueModem; typedef struct _GClueModemInterface GClueModemInterface; struct _GClueModemInterface { /* */ GTypeInterface parent_iface; gboolean (*get_is_3g_available) (GClueModem *modem); gboolean (*get_is_cdma_available) (GClueModem *modem); gboolean (*get_is_gps_available) (GClueModem *modem); void (*enable_3g) (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); guint (*get_time_threshold) (GClueModem *modem); void (*set_time_threshold) (GClueModem *modem, guint threshold); gboolean (*enable_3g_finish) (GClueModem *modem, GAsyncResult *result, GError **error); void (*enable_cdma) (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (*enable_cdma_finish) (GClueModem *modem, GAsyncResult *result, GError **error); void (*enable_gps) (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (*enable_gps_finish) (GClueModem *modem, GAsyncResult *result, GError **error); gboolean (*disable_3g) (GClueModem *modem, GCancellable *cancellable, GError **error); gboolean (*disable_cdma) (GClueModem *modem, GCancellable *cancellable, GError **error); gboolean (*disable_gps) (GClueModem *modem, GCancellable *cancellable, GError **error); }; gboolean gclue_modem_get_is_3g_available (GClueModem *modem); gboolean gclue_modem_get_is_cdma_available (GClueModem *modem); gboolean gclue_modem_get_is_gps_available (GClueModem *modem); void gclue_modem_enable_3g (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); guint gclue_modem_get_time_threshold (GClueModem *modem); void gclue_modem_set_time_threshold (GClueModem *modem, guint threshold); gboolean gclue_modem_enable_3g_finish (GClueModem *modem, GAsyncResult *result, GError **error); void gclue_modem_enable_cdma (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean gclue_modem_enable_cdma_finish (GClueModem *modem, GAsyncResult *result, GError **error); void gclue_modem_enable_gps (GClueModem *modem, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean gclue_modem_enable_gps_finish (GClueModem *modem, GAsyncResult *result, GError **error); gboolean gclue_modem_disable_3g (GClueModem *modem, GCancellable *cancellable, GError **error); gboolean gclue_modem_disable_cdma (GClueModem *modem, GCancellable *cancellable, GError **error); gboolean gclue_modem_disable_gps (GClueModem *modem, GCancellable *cancellable, GError **error); G_END_DECLS #endif /* GCLUE_MODEM_H */ geoclue-2.5.2/src/gclue-mozilla.c000066400000000000000000000342741341441426700166620ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include #include #include "gclue-mozilla.h" #include "gclue-config.h" #include "gclue-error.h" /** * SECTION:gclue-mozilla * @short_description: Helpers to create queries for and parse response of, * Mozilla Location Service. * * Contains API to get the geolocation based on IP address, nearby WiFi networks * and 3GPP cell tower info. It uses * Mozilla Location * Service to achieve that. The URL is kept in our configuration file so * its easy to switch to Google's API. **/ static char * variant_to_string (GVariant *variant, guint *len) { guint n_bytes, i; char *ret; n_bytes = g_variant_n_children (variant); if (len != NULL) *len = n_bytes; if (n_bytes <= 0) return NULL; ret = g_malloc (n_bytes + 1); ret[n_bytes] = '\0'; for (i = 0; i < n_bytes; i++) g_variant_get_child (variant, i, "y", &ret[i]); return ret; } static char * get_ssid_from_bss (WPABSS *bss) { GVariant *variant = wpa_bss_get_ssid (bss); return variant_to_string (variant, NULL); } static char * get_bssid_from_bss (WPABSS *bss) { GVariant *variant; char *raw_bssid; char *bssid; guint raw_len, len, i, j; variant = wpa_bss_get_bssid (bss); raw_bssid = variant_to_string (variant, &raw_len); len = raw_len * 2 + raw_len; bssid = g_malloc (len); for (i = 0, j = 0; i < len; i = i + 3, j++) g_snprintf (bssid + i, 4, "%02x:", (unsigned char) raw_bssid[j]); bssid[len - 1] = '\0'; return bssid; } static const char * get_url (void) { GClueConfig *config; config = gclue_config_get_singleton (); return gclue_config_get_wifi_url (config); } SoupMessage * gclue_mozilla_create_query (GList *bss_list, /* As in Access Points */ GClue3GTower *tower, GError **error) { SoupMessage *ret = NULL; JsonBuilder *builder; JsonGenerator *generator; JsonNode *root_node; char *data; gsize data_len; const char *uri; builder = json_builder_new (); json_builder_begin_object (builder); /* We send pure geoip query using empty object if both bss_list and * tower are NULL. */ if (tower != NULL) { json_builder_set_member_name (builder, "radioType"); json_builder_add_string_value (builder, "gsm"); json_builder_set_member_name (builder, "cellTowers"); json_builder_begin_array (builder); json_builder_begin_object (builder); json_builder_set_member_name (builder, "cellId"); json_builder_add_int_value (builder, tower->cell_id); json_builder_set_member_name (builder, "mobileCountryCode"); json_builder_add_int_value (builder, tower->mcc); json_builder_set_member_name (builder, "mobileNetworkCode"); json_builder_add_int_value (builder, tower->mnc); json_builder_set_member_name (builder, "locationAreaCode"); json_builder_add_int_value (builder, tower->lac); json_builder_end_object (builder); json_builder_end_array (builder); } if (bss_list != NULL) { GList *iter; json_builder_set_member_name (builder, "wifiAccessPoints"); json_builder_begin_array (builder); for (iter = bss_list; iter != NULL; iter = iter->next) { WPABSS *bss = WPA_BSS (iter->data); char *mac; gint16 strength_dbm; if (gclue_mozilla_should_ignore_bss (bss)) continue; json_builder_begin_object (builder); json_builder_set_member_name (builder, "macAddress"); mac = get_bssid_from_bss (bss); json_builder_add_string_value (builder, mac); g_free (mac); json_builder_set_member_name (builder, "signalStrength"); strength_dbm = wpa_bss_get_signal (bss); json_builder_add_int_value (builder, strength_dbm); json_builder_end_object (builder); } json_builder_end_array (builder); } json_builder_end_object (builder); generator = json_generator_new (); root_node = json_builder_get_root (builder); json_generator_set_root (generator, root_node); data = json_generator_to_data (generator, &data_len); json_node_free (root_node); g_object_unref (builder); g_object_unref (generator); uri = get_url (); ret = soup_message_new ("POST", uri); soup_message_set_request (ret, "application/json", SOUP_MEMORY_TAKE, data, data_len); g_debug ("Sending following request to '%s':\n%s", uri, data); return ret; } static gboolean parse_server_error (JsonObject *object, GError **error) { JsonObject *error_obj; int code; const char *message; if (!json_object_has_member (object, "error")) return FALSE; error_obj = json_object_get_object_member (object, "error"); code = json_object_get_int_member (error_obj, "code"); message = json_object_get_string_member (error_obj, "message"); g_set_error_literal (error, G_IO_ERROR, code, message); return TRUE; } GClueLocation * gclue_mozilla_parse_response (const char *json, GError **error) { JsonParser *parser; JsonNode *node; JsonObject *object, *loc_object; GClueLocation *location; gdouble latitude, longitude, accuracy; parser = json_parser_new (); if (!json_parser_load_from_data (parser, json, -1, error)) return NULL; node = json_parser_get_root (parser); object = json_node_get_object (node); if (parse_server_error (object, error)) return NULL; loc_object = json_object_get_object_member (object, "location"); latitude = json_object_get_double_member (loc_object, "lat"); longitude = json_object_get_double_member (loc_object, "lng"); accuracy = json_object_get_double_member (object, "accuracy"); location = gclue_location_new (latitude, longitude, accuracy); g_object_unref (parser); return location; } static const char * get_submit_config (const char **nick) { GClueConfig *config; config = gclue_config_get_singleton (); if (!gclue_config_get_wifi_submit_data (config)) return NULL; *nick = gclue_config_get_wifi_submit_nick (config); return gclue_config_get_wifi_submit_url (config); } SoupMessage * gclue_mozilla_create_submit_query (GClueLocation *location, GList *bss_list, /* As in Access Points */ GClue3GTower *tower, GError **error) { SoupMessage *ret = NULL; JsonBuilder *builder; JsonGenerator *generator; JsonNode *root_node; char *data, *timestamp; const char *url, *nick; gsize data_len; GList *iter; gdouble lat, lon, accuracy, altitude; GTimeVal tv; url = get_submit_config (&nick); if (url == NULL) goto out; builder = json_builder_new (); json_builder_begin_object (builder); json_builder_set_member_name (builder, "items"); json_builder_begin_array (builder); json_builder_begin_object (builder); lat = gclue_location_get_latitude (location); json_builder_set_member_name (builder, "lat"); json_builder_add_double_value (builder, lat); lon = gclue_location_get_longitude (location); json_builder_set_member_name (builder, "lon"); json_builder_add_double_value (builder, lon); accuracy = gclue_location_get_accuracy (location); if (accuracy != GCLUE_LOCATION_ACCURACY_UNKNOWN) { json_builder_set_member_name (builder, "accuracy"); json_builder_add_double_value (builder, accuracy); } altitude = gclue_location_get_altitude (location); if (altitude != GCLUE_LOCATION_ALTITUDE_UNKNOWN) { json_builder_set_member_name (builder, "altitude"); json_builder_add_double_value (builder, altitude); } tv.tv_sec = gclue_location_get_timestamp (location); tv.tv_usec = 0; timestamp = g_time_val_to_iso8601 (&tv); json_builder_set_member_name (builder, "time"); json_builder_add_string_value (builder, timestamp); g_free (timestamp); json_builder_set_member_name (builder, "radioType"); json_builder_add_string_value (builder, "gsm"); if (bss_list != NULL) { json_builder_set_member_name (builder, "wifi"); json_builder_begin_array (builder); for (iter = bss_list; iter != NULL; iter = iter->next) { WPABSS *bss = WPA_BSS (iter->data); char *mac; gint16 strength_dbm; guint16 frequency; if (gclue_mozilla_should_ignore_bss (bss)) continue; json_builder_begin_object (builder); json_builder_set_member_name (builder, "key"); mac = get_bssid_from_bss (bss); json_builder_add_string_value (builder, mac); g_free (mac); json_builder_set_member_name (builder, "signal"); strength_dbm = wpa_bss_get_signal (bss); json_builder_add_int_value (builder, strength_dbm); json_builder_set_member_name (builder, "frequency"); frequency = wpa_bss_get_frequency (bss); json_builder_add_int_value (builder, frequency); json_builder_end_object (builder); } json_builder_end_array (builder); /* wifi */ } if (tower != NULL) { json_builder_set_member_name (builder, "cell"); json_builder_begin_array (builder); json_builder_begin_object (builder); json_builder_set_member_name (builder, "radio"); json_builder_add_string_value (builder, "gsm"); json_builder_set_member_name (builder, "cid"); json_builder_add_int_value (builder, tower->cell_id); json_builder_set_member_name (builder, "mcc"); json_builder_add_int_value (builder, tower->mcc); json_builder_set_member_name (builder, "mnc"); json_builder_add_int_value (builder, tower->mnc); json_builder_set_member_name (builder, "lac"); json_builder_add_int_value (builder, tower->lac); json_builder_end_object (builder); json_builder_end_array (builder); /* cell */ } json_builder_end_object (builder); json_builder_end_array (builder); /* items */ json_builder_end_object (builder); generator = json_generator_new (); root_node = json_builder_get_root (builder); json_generator_set_root (generator, root_node); data = json_generator_to_data (generator, &data_len); json_node_free (root_node); g_object_unref (builder); g_object_unref (generator); ret = soup_message_new ("POST", url); if (nick != NULL && nick[0] != '\0') soup_message_headers_append (ret->request_headers, "X-Nickname", nick); soup_message_set_request (ret, "application/json", SOUP_MEMORY_TAKE, data, data_len); g_debug ("Sending following request to '%s':\n%s", url, data); out: return ret; } gboolean gclue_mozilla_should_ignore_bss (WPABSS *bss) { char *ssid, *bssid; ssid = get_ssid_from_bss (bss); bssid = get_bssid_from_bss (bss); if (ssid == NULL || g_str_has_suffix (ssid, "_nomap")) { g_debug ("SSID for WiFi AP '%s' missing or has '_nomap' suffix." ", Ignoring..", bssid); return TRUE; } g_free (ssid); g_free (bssid); return FALSE; } geoclue-2.5.2/src/gclue-mozilla.h000066400000000000000000000032701341441426700166570ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_MOZILLA_H #define GCLUE_MOZILLA_H #include #include #include "wpa_supplicant-interface.h" #include "gclue-location.h" #include "gclue-3g-tower.h" G_BEGIN_DECLS SoupMessage * gclue_mozilla_create_query (GList *bss_list, /* As in Access Points */ GClue3GTower *tower, GError **error); GClueLocation * gclue_mozilla_parse_response (const char *json, GError **error); SoupMessage * gclue_mozilla_create_submit_query (GClueLocation *location, GList *bss_list, /* As in Access Points */ GClue3GTower *tower, GError **error); gboolean gclue_mozilla_should_ignore_bss (WPABSS *bss); G_END_DECLS #endif /* GCLUE_MOZILLA_H */ geoclue-2.5.2/src/gclue-nmea-source.c000066400000000000000000000550531341441426700174270ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * Copyright 2015 Ankit (Verma) * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) * Ankit (Verma) */ #include #include #include "gclue-nmea-source.h" #include "gclue-location.h" #include "config.h" #include "gclue-enum-types.h" #include #include #include #include #include typedef struct AvahiServiceInfo AvahiServiceInfo; struct _GClueNMEASourcePrivate { GSocketConnection *connection; GSocketClient *client; GCancellable *cancellable; AvahiClient *avahi_client; AvahiServiceInfo *active_service; /* List of all services but only the most accurate one is used. */ GList *all_services; }; G_DEFINE_TYPE_WITH_CODE (GClueNMEASource, gclue_nmea_source, GCLUE_TYPE_LOCATION_SOURCE, G_ADD_PRIVATE (GClueNMEASource)) static gboolean gclue_nmea_source_start (GClueLocationSource *source); static gboolean gclue_nmea_source_stop (GClueLocationSource *source); static void connect_to_service (GClueNMEASource *source); static void disconnect_from_service (GClueNMEASource *source); struct AvahiServiceInfo { char *identifier; char *host_name; guint16 port; GClueAccuracyLevel accuracy; guint64 timestamp; }; static void avahi_service_free (gpointer data) { AvahiServiceInfo *service = (AvahiServiceInfo *) data; g_free (service->identifier); g_free (service->host_name); g_slice_free(AvahiServiceInfo, service); } static AvahiServiceInfo * avahi_service_new (const char *identifier, const char *host_name, guint16 port, GClueAccuracyLevel accuracy) { GTimeVal tv; AvahiServiceInfo *service = g_slice_new0 (AvahiServiceInfo); service->identifier = g_strdup (identifier); service->host_name = g_strdup (host_name); service->port = port; service->accuracy = accuracy; g_get_current_time (&tv); service->timestamp = tv.tv_sec; return service; } static gint compare_avahi_service_by_identifier (gconstpointer a, gconstpointer b) { AvahiServiceInfo *first, *second; first = (AvahiServiceInfo *) a; second = (AvahiServiceInfo *) b; return g_strcmp0 (first->identifier, second->identifier); } static gint compare_avahi_service_by_accuracy_n_time (gconstpointer a, gconstpointer b) { AvahiServiceInfo *first, *second; gint diff; first = (AvahiServiceInfo *) a; second = (AvahiServiceInfo *) b; diff = second->accuracy - first->accuracy; if (diff == 0) return first->timestamp - second->timestamp; return diff; } static gboolean reconnection_required (GClueNMEASource *source) { GClueNMEASourcePrivate *priv = source->priv; /* Basically, reconnection is required if either * * 1. service in use went down. * 2. a more accurate service than one currently in use, is now * available. */ return (priv->active_service != NULL && (priv->all_services == NULL || priv->active_service != priv->all_services->data)); } static void reconnect_service (GClueNMEASource *source) { if (!reconnection_required (source)) return; disconnect_from_service (source); connect_to_service (source); } static void refresh_accuracy_level (GClueNMEASource *source) { GClueAccuracyLevel new, existing; existing = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (source)); if (source->priv->all_services != NULL) { AvahiServiceInfo *service; service = (AvahiServiceInfo *) source->priv->all_services->data; new = service->accuracy; } else { new = GCLUE_ACCURACY_LEVEL_NONE; } if (new != existing) { g_debug ("Available accuracy level from %s: %u", G_OBJECT_TYPE_NAME (source), new); g_object_set (G_OBJECT (source), "available-accuracy-level", new, NULL); } } static void add_new_service (GClueNMEASource *source, const char *name, const char *host_name, uint16_t port, AvahiStringList *txt) { GClueAccuracyLevel accuracy = GCLUE_ACCURACY_LEVEL_NONE; AvahiServiceInfo *service; AvahiStringList *node; guint n_services; char *key, *value; GEnumClass *enum_class; GEnumValue *enum_value; node = avahi_string_list_find (txt, "accuracy"); if (node == NULL) { g_warning ("No `accuracy` key inside TXT record"); accuracy = GCLUE_ACCURACY_LEVEL_EXACT; goto CREATE_SERVICE; } avahi_string_list_get_pair (node, &key, &value, NULL); if (value == NULL) { g_warning ("There is no value for `accuracy` inside TXT " "record"); accuracy = GCLUE_ACCURACY_LEVEL_EXACT; goto CREATE_SERVICE; } enum_class = g_type_class_ref (GCLUE_TYPE_ACCURACY_LEVEL); enum_value = g_enum_get_value_by_nick (enum_class, value); g_type_class_unref (enum_class); if (enum_value == NULL) { g_warning ("Invalid `accuracy` value `%s` inside TXT records.", value); accuracy = GCLUE_ACCURACY_LEVEL_EXACT; goto CREATE_SERVICE; } accuracy = enum_value->value; CREATE_SERVICE: service = avahi_service_new (name, host_name, port, accuracy); source->priv->all_services = g_list_insert_sorted (source->priv->all_services, service, compare_avahi_service_by_accuracy_n_time); refresh_accuracy_level (source); reconnect_service (source); n_services = g_list_length (source->priv->all_services); g_debug ("No. of _nmea-0183._tcp services %u", n_services); } static void remove_service (GClueNMEASource *source, AvahiServiceInfo *service) { guint n_services = 0; avahi_service_free (service); source->priv->all_services = g_list_remove (source->priv->all_services, service); n_services = g_list_length (source->priv->all_services); g_debug ("No. of _nmea-0183._tcp services %u", n_services); refresh_accuracy_level (source); reconnect_service (source); } static void remove_service_by_name (GClueNMEASource *source, const char *name) { AvahiServiceInfo *service; GList *item; /* only `name` is required here */ service = avahi_service_new (name, NULL, 0, GCLUE_ACCURACY_LEVEL_NONE); item = g_list_find_custom (source->priv->all_services, service, compare_avahi_service_by_identifier); avahi_service_free (service); if (item == NULL) return; remove_service (source, item->data); } static void resolve_callback (AvahiServiceResolver *service_resolver, AvahiIfIndex interface G_GNUC_UNUSED, AvahiProtocol protocol G_GNUC_UNUSED, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *user_data) { const char *errorstr; /* FIXME: check with Avahi devs whether this is really needed. */ g_return_if_fail (service_resolver != NULL); switch (event) { case AVAHI_RESOLVER_FAILURE: { AvahiClient *avahi_client = avahi_service_resolver_get_client (service_resolver); errorstr = avahi_strerror (avahi_client_errno (avahi_client)); g_warning ("(Resolver) Failed to resolve service '%s' " "of type '%s' in domain '%s': %s", name, type, domain, errorstr); break; } case AVAHI_RESOLVER_FOUND: g_debug ("Service %s:%u resolved", host_name, port); add_new_service (GCLUE_NMEA_SOURCE (user_data), name, host_name, port, txt); break; } avahi_service_resolver_free (service_resolver); } static void client_callback (AvahiClient *avahi_client, AvahiClientState state, void *user_data) { GClueNMEASourcePrivate *priv = GCLUE_NMEA_SOURCE (user_data)->priv; g_return_if_fail (avahi_client != NULL); priv->avahi_client = avahi_client; if (state == AVAHI_CLIENT_FAILURE) { const char *errorstr = avahi_strerror (avahi_client_errno (avahi_client)); g_warning ("Avahi client failure: %s", errorstr); } } static void browse_callback (AvahiServiceBrowser *service_browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags G_GNUC_UNUSED, void *user_data) { GClueNMEASourcePrivate *priv = GCLUE_NMEA_SOURCE (user_data)->priv; const char *errorstr; /* FIXME: check with Avahi devs whether this is really needed. */ g_return_if_fail (service_browser != NULL); switch (event) { case AVAHI_BROWSER_FAILURE: errorstr = avahi_strerror (avahi_client_errno (avahi_service_browser_get_client (service_browser))); g_warning ("Avahi service browser Error %s", errorstr); return; case AVAHI_BROWSER_NEW: { AvahiServiceResolver *service_resolver; g_debug ("Service '%s' of type '%s' found in domain '%s'", name, type, domain); service_resolver = avahi_service_resolver_new (priv->avahi_client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, user_data); if (service_resolver == NULL) { errorstr = avahi_strerror (avahi_client_errno (priv->avahi_client)); g_warning ("Failed to resolve service '%s': %s", name, errorstr); } break; } case AVAHI_BROWSER_REMOVE: g_debug ("Service '%s' of type '%s' in domain '%s' removed " "from the list of available NMEA services", name, type, domain); remove_service_by_name (GCLUE_NMEA_SOURCE (user_data), name); break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: g_debug ("Avahi Service Browser's %s event occurred", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; } } static void on_read_gga_sentence (GObject *object, GAsyncResult *result, gpointer user_data) { GClueNMEASource *source = GCLUE_NMEA_SOURCE (user_data); GDataInputStream *data_input_stream = G_DATA_INPUT_STREAM (object); GError *error = NULL; GClueLocation *location; gsize data_size = 0 ; char *message; message = g_data_input_stream_read_line_finish (data_input_stream, result, &data_size, &error); if (message == NULL) { if (error != NULL) { if (error->code == G_IO_ERROR_CLOSED) g_debug ("Socket closed."); else if (error->code != G_IO_ERROR_CANCELLED) g_warning ("Error when receiving message: %s", error->message); g_error_free (error); } else { g_debug ("Nothing to read"); } g_object_unref (data_input_stream); if (source->priv->active_service != NULL) /* In case service did not advertise it exiting * or we failed to receive it's notification. */ remove_service (source, source->priv->active_service); return; } g_debug ("Network source sent: \"%s\"", message); if (!g_str_has_prefix (message, "$GPGGA")) { /* FIXME: Handle other useful NMEA sentences too */ g_debug ("Ignoring non-GGA sentence from NMEA source"); goto READ_NEXT_LINE; } location = gclue_location_create_from_gga (message, &error); if (error != NULL) { g_warning ("Error: %s", error->message); g_clear_error (&error); } else { gclue_location_source_set_location (GCLUE_LOCATION_SOURCE (source), location); } READ_NEXT_LINE: g_data_input_stream_read_line_async (data_input_stream, G_PRIORITY_DEFAULT, source->priv->cancellable, on_read_gga_sentence, source); } static void on_connection_to_location_server (GObject *object, GAsyncResult *result, gpointer user_data) { GClueNMEASource *source = GCLUE_NMEA_SOURCE (user_data); GSocketClient *client = G_SOCKET_CLIENT (object); GError *error = NULL; GDataInputStream *data_input_stream; GInputStream *input_stream; source->priv->connection = g_socket_client_connect_to_host_finish (client, result, &error); if (error != NULL) { if (error->code != G_IO_ERROR_CANCELLED) g_warning ("Failed to connect to NMEA service: %s", error->message); g_clear_error (&error); return; } input_stream = g_io_stream_get_input_stream (G_IO_STREAM (source->priv->connection)); data_input_stream = g_data_input_stream_new (input_stream); g_data_input_stream_read_line_async (data_input_stream, G_PRIORITY_DEFAULT, source->priv->cancellable, on_read_gga_sentence, source); } static void connect_to_service (GClueNMEASource *source) { GClueNMEASourcePrivate *priv = source->priv; if (priv->all_services == NULL) return; priv->client = g_socket_client_new (); g_cancellable_reset (priv->cancellable); /* The service with the highest accuracy will be stored in the beginning * of the list. */ priv->active_service = (AvahiServiceInfo *) priv->all_services->data; g_socket_client_connect_to_host_async (priv->client, priv->active_service->host_name, priv->active_service->port, priv->cancellable, on_connection_to_location_server, source); } static void disconnect_from_service (GClueNMEASource *source) { GClueNMEASourcePrivate *priv = source->priv; g_cancellable_cancel (priv->cancellable); if (priv->connection != NULL) { GError *error = NULL; g_io_stream_close (G_IO_STREAM (priv->connection), NULL, &error); if (error != NULL) g_warning ("Error in closing socket connection: %s", error->message); } g_clear_object (&priv->connection); g_clear_object (&priv->client); priv->active_service = NULL; } static void gclue_nmea_source_finalize (GObject *gnmea) { GClueNMEASourcePrivate *priv = GCLUE_NMEA_SOURCE (gnmea)->priv; G_OBJECT_CLASS (gclue_nmea_source_parent_class)->finalize (gnmea); g_clear_object (&priv->connection); g_clear_object (&priv->client); g_clear_object (&priv->cancellable); if (priv->avahi_client) avahi_client_free (priv->avahi_client); g_list_free_full (priv->all_services, avahi_service_free); } static void gclue_nmea_source_class_init (GClueNMEASourceClass *klass) { GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *gnmea_class = G_OBJECT_CLASS (klass); gnmea_class->finalize = gclue_nmea_source_finalize; source_class->start = gclue_nmea_source_start; source_class->stop = gclue_nmea_source_stop; } static void gclue_nmea_source_init (GClueNMEASource *source) { GClueNMEASourcePrivate *priv; AvahiServiceBrowser *service_browser; const AvahiPoll *poll_api; AvahiGLibPoll *glib_poll; int error; source->priv = G_TYPE_INSTANCE_GET_PRIVATE ((source), GCLUE_TYPE_NMEA_SOURCE, GClueNMEASourcePrivate); priv = source->priv; glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT); poll_api = avahi_glib_poll_get (glib_poll); priv->cancellable = g_cancellable_new (); avahi_client_new (poll_api, 0, client_callback, source, &error); if (priv->avahi_client == NULL) { g_warning ("Failed to connect to avahi service: %s", avahi_strerror (error)); return; } service_browser = avahi_service_browser_new (priv->avahi_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_nmea-0183._tcp", NULL, 0, browse_callback, source); if (service_browser == NULL) { const char *errorstr; error = avahi_client_errno (priv->avahi_client); errorstr = avahi_strerror (error); g_warning ("Failed to browse avahi services: %s", errorstr); } } /** * gclue_nmea_source_get_singleton: * * Get the #GClueNMEASource singleton. * * Returns: (transfer full): a new ref to #GClueNMEASource. Use g_object_unref() * when done. **/ GClueNMEASource * gclue_nmea_source_get_singleton (void) { static GClueNMEASource *source = NULL; if (source == NULL) { source = g_object_new (GCLUE_TYPE_NMEA_SOURCE, NULL); g_object_add_weak_pointer (G_OBJECT (source), (gpointer) &source); } else g_object_ref (source); return source; } static gboolean gclue_nmea_source_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; g_return_val_if_fail (GCLUE_IS_NMEA_SOURCE (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_nmea_source_parent_class); if (!base_class->start (source)) return FALSE; connect_to_service (GCLUE_NMEA_SOURCE (source)); return TRUE; } static gboolean gclue_nmea_source_stop (GClueLocationSource *source) { GClueLocationSourceClass *base_class; g_return_val_if_fail (GCLUE_IS_NMEA_SOURCE (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_nmea_source_parent_class); if (!base_class->stop (source)) return FALSE; disconnect_from_service (GCLUE_NMEA_SOURCE (source)); return TRUE; } geoclue-2.5.2/src/gclue-nmea-source.h000066400000000000000000000050121341441426700174220ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * Copyright 2015 Ankit (Verma) * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) * Ankit (Verma) */ #ifndef GCLUE_NMEA_SOURCE_H #define GCLUE_NMEA_SOURCE_H #include #include #include "gclue-location-source.h" G_BEGIN_DECLS GType gclue_nmea_source_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_NMEA_SOURCE (gclue_nmea_source_get_type ()) #define GCLUE_NMEA_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_NMEA_SOURCE, GClueNMEASource)) #define GCLUE_IS_NMEA_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_NMEA_SOURCE)) #define GCLUE_NMEA_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_NMEA_SOURCE, GClueNMEASourceClass)) #define GCLUE_IS_NMEA_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_NMEA_SOURCE)) #define GCLUE_NMEA_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_NMEA_SOURCE, GClueNMEASourceClass)) /** * GClueNMEASource: * * All the fields in the #GClueNMEASource structure are private and should never be accessed directly. **/ typedef struct _GClueNMEASource GClueNMEASource; typedef struct _GClueNMEASourceClass GClueNMEASourceClass; typedef struct _GClueNMEASourcePrivate GClueNMEASourcePrivate; struct _GClueNMEASource { /* */ GClueLocationSource parent_instance; GClueNMEASourcePrivate *priv; }; /** * GClueNMEASourceClass: * * All the fields in the #GClueNMEASourceClass structure are private and should never be accessed directly. **/ struct _GClueNMEASourceClass { /* */ GClueLocationSourceClass parent_class; }; GClueNMEASource * gclue_nmea_source_get_singleton (void); G_END_DECLS #endif /* GCLUE_NMEA_SOURCE_H */ geoclue-2.5.2/src/gclue-service-client.c000066400000000000000000001127251341441426700201250ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-client.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include "gclue-service-client.h" #include "gclue-service-location.h" #include "gclue-locator.h" #include "gclue-enum-types.h" #include "gclue-config.h" #define DEFAULT_ACCURACY_LEVEL GCLUE_ACCURACY_LEVEL_CITY #define DEFAULT_AGENT_STARTUP_WAIT_SECS 5 static void gclue_service_client_client_iface_init (GClueDBusClientIface *iface); static void gclue_service_client_initable_iface_init (GInitableIface *iface); typedef struct _StartData StartData; struct _GClueServiceClientPrivate { GClueClientInfo *client_info; char *path; GDBusConnection *connection; GClueAgent *agent_proxy; StartData *pending_auth_start_data; guint pending_auth_timeout_id; GClueServiceLocation *location; GClueServiceLocation *prev_location; guint distance_threshold; guint time_threshold; GClueLocator *locator; /* Number of times location has been updated */ guint locations_updated; gboolean agent_stopped; /* Agent stopped client, not the app */ }; G_DEFINE_TYPE_WITH_CODE (GClueServiceClient, gclue_service_client, GCLUE_DBUS_TYPE_CLIENT_SKELETON, G_IMPLEMENT_INTERFACE (GCLUE_DBUS_TYPE_CLIENT, gclue_service_client_client_iface_init) G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gclue_service_client_initable_iface_init) G_ADD_PRIVATE (GClueServiceClient)); enum { PROP_0, PROP_CLIENT_INFO, PROP_PATH, PROP_CONNECTION, PROP_AGENT_PROXY, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static char * next_location_path (GClueServiceClient *client) { GClueServiceClientPrivate *priv = client->priv; char *path, *index_str; index_str = g_strdup_printf ("%u", (priv->locations_updated)++), path = g_strjoin ("/", priv->path, "Location", index_str, NULL); g_free (index_str); return path; } /* We don't use the gdbus-codegen provided gclue_client_emit_location_updated() * as that sends the signal to all listeners on the bus */ static gboolean emit_location_updated (GClueServiceClient *client, const char *old, const char *new, GError **error) { GClueServiceClientPrivate *priv = client->priv; GVariant *variant; const char *peer; variant = g_variant_new ("(oo)", old, new); peer = gclue_client_info_get_bus_name (priv->client_info); return g_dbus_connection_emit_signal (priv->connection, peer, priv->path, "org.freedesktop.GeoClue2.Client", "LocationUpdated", variant, error); } static gboolean distance_below_threshold (GClueServiceClient *client, GClueLocation *location) { GClueServiceClientPrivate *priv = client->priv; GClueLocation *cur_location; gdouble distance; gdouble threshold_km; if (priv->distance_threshold == 0) return FALSE; g_object_get (priv->location, "location", &cur_location, NULL); distance = gclue_location_get_distance_from (cur_location, location); g_object_unref (cur_location); threshold_km = priv->distance_threshold / 1000.0; if (distance < threshold_km) { g_debug ("Distance from previous location is %f km and " "below threshold of %f km.", distance, threshold_km); return TRUE; } return FALSE; } static gboolean time_below_threshold (GClueServiceClient *client, GClueLocation *location) { GClueServiceClientPrivate *priv = client->priv; GClueLocation *cur_location; gint64 cur_ts, ts; guint64 diff_ts; if (priv->time_threshold == 0) return FALSE; g_object_get (priv->location, "location", &cur_location, NULL); cur_ts = gclue_location_get_timestamp (cur_location); ts = gclue_location_get_timestamp (location); diff_ts = ABS (ts - cur_ts); g_object_unref (cur_location); if (diff_ts < priv->time_threshold) { g_debug ("Time difference between previous and new location" " is %" G_GUINT64_FORMAT " seconds and" " below threshold of %" G_GUINT32_FORMAT " seconds.", diff_ts, priv->time_threshold); return TRUE; } return FALSE; } static gboolean below_threshold (GClueServiceClient *client, GClueLocation *location) { return (distance_below_threshold (client, location) || time_below_threshold (client, location)); } static gboolean on_prev_location_timeout (gpointer user_data) { g_object_unref (user_data); return FALSE; } static void on_locator_location_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueServiceClient *client = GCLUE_SERVICE_CLIENT (user_data); GClueServiceClientPrivate *priv = client->priv; GClueLocationSource *locator = GCLUE_LOCATION_SOURCE (gobject); GClueLocation *location_info; char *path = NULL; const char *prev_path; GError *error = NULL; location_info = gclue_location_source_get_location (locator); if (location_info == NULL) return; /* No location found yet */ if (priv->location != NULL && below_threshold (client, location_info)) { g_debug ("Updating location, below threshold"); g_object_set (priv->location, "location", location_info, NULL); return; } if (priv->prev_location != NULL) // Lets try to ensure that apps are not still accessing the // last location before unrefing (and therefore destroying) it. g_timeout_add_seconds (5, on_prev_location_timeout, priv->prev_location); priv->prev_location = priv->location; path = next_location_path (client); priv->location = gclue_service_location_new (priv->client_info, path, priv->connection, location_info, &error); if (priv->location == NULL) goto error_out; if (priv->prev_location != NULL) prev_path = gclue_service_location_get_path (priv->prev_location); else prev_path = "/"; gclue_dbus_client_set_location (GCLUE_DBUS_CLIENT (client), path); if (!emit_location_updated (client, prev_path, path, &error)) goto error_out; goto out; error_out: g_warning ("Failed to update location info: %s", error->message); g_error_free (error); out: g_free (path); } static void start_client (GClueServiceClient *client, GClueAccuracyLevel accuracy_level) { GClueServiceClientPrivate *priv = client->priv; gclue_dbus_client_set_active (GCLUE_DBUS_CLIENT (client), TRUE); priv->locator = gclue_locator_new (accuracy_level); gclue_locator_set_time_threshold (priv->locator, 0); g_signal_connect (priv->locator, "notify::location", G_CALLBACK (on_locator_location_changed), client); gclue_location_source_start (GCLUE_LOCATION_SOURCE (priv->locator)); } static void stop_client (GClueServiceClient *client) { g_clear_object (&client->priv->locator); gclue_dbus_client_set_active (GCLUE_DBUS_CLIENT (client), FALSE); } static GClueAccuracyLevel ensure_valid_accuracy_level (GClueAccuracyLevel accuracy_level, GClueAccuracyLevel max_accuracy) { GClueAccuracyLevel accuracy; GEnumClass *enum_class; GEnumValue *enum_value; accuracy = CLAMP (accuracy_level, GCLUE_ACCURACY_LEVEL_COUNTRY, max_accuracy); enum_class = g_type_class_ref (GCLUE_TYPE_ACCURACY_LEVEL); enum_value = g_enum_get_value (enum_class, accuracy); if (enum_value == NULL) { GClueAccuracyLevel i; g_debug ("Invalid accuracy level %u requested", accuracy_level); for (i = accuracy; i >= GCLUE_ACCURACY_LEVEL_COUNTRY; i--) { enum_value = g_enum_get_value (enum_class, i); if (enum_value != NULL) { accuracy = i; break; } } } return accuracy; } static void on_agent_props_changed (GDBusProxy *agent_proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer user_data) { GClueServiceClient *client = GCLUE_SERVICE_CLIENT (user_data); GClueDBusClient *gdbus_client; GVariantIter *iter; GVariant *value; gchar *key; if (g_variant_n_children (changed_properties) <= 0) return; g_variant_get (changed_properties, "a{sv}", &iter); while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) { GClueAccuracyLevel max_accuracy; const char *id; gboolean system_app; if (strcmp (key, "MaxAccuracyLevel") != 0) continue; gdbus_client = GCLUE_DBUS_CLIENT (client); id = gclue_dbus_client_get_desktop_id (gdbus_client); max_accuracy = g_variant_get_uint32 (value); system_app = (gclue_client_info_get_xdg_id (client->priv->client_info) == NULL); /* FIXME: We should be handling all values of max accuracy * level here, not just 0 and non-0. */ if (max_accuracy != 0 && client->priv->agent_stopped) { GClueAccuracyLevel accuracy; client->priv->agent_stopped = FALSE; accuracy = gclue_dbus_client_get_requested_accuracy_level (gdbus_client); accuracy = ensure_valid_accuracy_level (accuracy, max_accuracy); start_client (client, accuracy); g_debug ("Re-started '%s'.", id); } else if (max_accuracy == 0 && gclue_dbus_client_get_active (gdbus_client) && !system_app) { stop_client (client); client->priv->agent_stopped = TRUE; g_debug ("Stopped '%s'.", id); } break; } g_variant_iter_free (iter); } struct _StartData { GClueServiceClient *client; GDBusMethodInvocation *invocation; char *desktop_id; GClueAccuracyLevel accuracy_level; }; static void start_data_free (StartData *data) { g_object_unref (data->client); g_object_unref (data->invocation); g_free(data->desktop_id); g_slice_free (StartData, data); } static void complete_start (StartData *data) { GClueDBusClient *gdbus_client = GCLUE_DBUS_CLIENT (data->client); start_client (data->client, data->accuracy_level); gclue_dbus_client_complete_start (gdbus_client, data->invocation); g_debug ("'%s' started.", gclue_dbus_client_get_desktop_id (gdbus_client)); start_data_free (data); } static void on_authorize_app_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { StartData *data = (StartData *) user_data; GClueServiceClientPrivate *priv = data->client->priv; GError *error = NULL; gboolean authorized = FALSE; if (!gclue_agent_call_authorize_app_finish (GCLUE_AGENT (source_object), &authorized, &data->accuracy_level, res, &error)) goto error_out; if (!authorized) { guint32 uid; uid = gclue_client_info_get_user_id (priv->client_info); g_set_error (&error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Agent rejected '%s' for user '%u'. Please ensure " "that '%s' has installed a valid %s.desktop file.", data->desktop_id, uid, data->desktop_id, data->desktop_id); goto error_out; } complete_start (data); return; error_out: g_dbus_method_invocation_take_error (data->invocation, error); start_data_free (data); } static void handle_post_agent_check_auth (StartData *data) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (data->client)->priv; GClueAccuracyLevel max_accuracy; GClueConfig *config; GClueAppPerm app_perm; guint32 uid; uid = gclue_client_info_get_user_id (priv->client_info); max_accuracy = gclue_agent_get_max_accuracy_level (priv->agent_proxy); if (max_accuracy == 0) { // Agent disabled geolocation for the user g_dbus_method_invocation_return_error (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Geolocation disabled for" " UID %u", uid); start_data_free (data); return; } g_debug ("requested accuracy level: %u. " "Max accuracy level allowed by agent: %u", data->accuracy_level, max_accuracy); data->accuracy_level = ensure_valid_accuracy_level (data->accuracy_level, max_accuracy); config = gclue_config_get_singleton (); app_perm = gclue_config_get_app_perm (config, data->desktop_id, priv->client_info); if (app_perm == GCLUE_APP_PERM_ALLOWED) { complete_start (data); return; } gclue_agent_call_authorize_app (priv->agent_proxy, data->desktop_id, data->accuracy_level, NULL, on_authorize_app_ready, data); } static gboolean handle_pending_auth (gpointer user_data) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (user_data)->priv; StartData *data = priv->pending_auth_start_data; guint32 uid; g_return_val_if_fail (data != NULL, G_SOURCE_REMOVE); uid = gclue_client_info_get_user_id (priv->client_info); if (priv->agent_proxy == NULL) { GClueConfig *config = gclue_config_get_singleton (); if (gclue_config_get_num_allowed_agents (config) == 0) { /* If there are no white-listed agents, there is no * point in requiring an agent */ complete_start (data); } else { g_dbus_method_invocation_return_error (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "'%s' disallowed, no agent " "for UID %u", data->desktop_id, uid); start_data_free (data); } } else { handle_post_agent_check_auth (data); } priv->pending_auth_timeout_id = 0; priv->pending_auth_start_data = NULL; return G_SOURCE_REMOVE; } static void set_pending_auth_timeout_enable (GClueDBusClient *client) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (client)->priv; if (priv->pending_auth_timeout_id > 0) return; priv->pending_auth_timeout_id = g_timeout_add_seconds (DEFAULT_AGENT_STARTUP_WAIT_SECS, handle_pending_auth, client); } static void set_pending_auth_timeout_disable (GClueDBusClient *client) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (client)->priv; if (priv->pending_auth_timeout_id == 0) return; g_source_remove (priv->pending_auth_timeout_id); priv->pending_auth_timeout_id = 0; } static gboolean gclue_service_client_handle_start (GClueDBusClient *client, GDBusMethodInvocation *invocation) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (client)->priv; GClueConfig *config; StartData *data; const char *desktop_id; GClueAppPerm app_perm; guint32 uid; gboolean system_app = FALSE; if (priv->locator != NULL) { /* Already started */ gclue_dbus_client_complete_start (client, invocation); return TRUE; } desktop_id = gclue_client_info_get_xdg_id (priv->client_info); if (desktop_id == NULL) { /* Non-xdg app */ desktop_id = gclue_dbus_client_get_desktop_id (client); system_app = TRUE; } if (desktop_id == NULL) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "'DesktopId' property must be set"); return TRUE; } config = gclue_config_get_singleton (); uid = gclue_client_info_get_user_id (priv->client_info); app_perm = gclue_config_get_app_perm (config, desktop_id, priv->client_info); if (app_perm == GCLUE_APP_PERM_DISALLOWED) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "'%s' disallowed by " "configuration for UID %u", desktop_id, uid); return TRUE; } data = g_slice_new (StartData); data->client = g_object_ref (GCLUE_SERVICE_CLIENT (client)); data->invocation = g_object_ref (invocation); data->desktop_id = g_strdup (desktop_id); data->accuracy_level = gclue_dbus_client_get_requested_accuracy_level (client); data->accuracy_level = ensure_valid_accuracy_level (data->accuracy_level, GCLUE_ACCURACY_LEVEL_EXACT); if (system_app) { /* Since we have no reliable way to identify system apps, no * need for auth for them. */ complete_start (data); return TRUE; } /* No agent == No authorization */ if (priv->agent_proxy == NULL) { /* Already a pending Start()? Denied! */ if (priv->pending_auth_start_data) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "An authorization request is already pending"); } else { priv->pending_auth_start_data = data; set_pending_auth_timeout_enable (client); } return TRUE; } handle_post_agent_check_auth (data); return TRUE; } static gboolean gclue_service_client_handle_stop (GClueDBusClient *client, GDBusMethodInvocation *invocation) { stop_client (GCLUE_SERVICE_CLIENT (client)); gclue_dbus_client_complete_stop (client, invocation); g_debug ("'%s' stopped.", gclue_dbus_client_get_desktop_id (client)); return TRUE; } static void gclue_service_client_finalize (GObject *object) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (object)->priv; g_clear_pointer (&priv->path, g_free); g_clear_object (&priv->connection); set_pending_auth_timeout_disable (GCLUE_DBUS_CLIENT (object)); g_clear_pointer (&priv->pending_auth_start_data, start_data_free); if (priv->agent_proxy != NULL) g_signal_handlers_disconnect_by_func (priv->agent_proxy, G_CALLBACK (on_agent_props_changed), object); g_clear_object (&priv->agent_proxy); g_clear_object (&priv->locator); g_clear_object (&priv->location); g_clear_object (&priv->prev_location); g_clear_object (&priv->client_info); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_service_client_parent_class)->finalize (object); } static void gclue_service_client_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueServiceClient *client = GCLUE_SERVICE_CLIENT (object); switch (prop_id) { case PROP_CLIENT_INFO: g_value_set_object (value, client->priv->client_info); break; case PROP_PATH: g_value_set_string (value, client->priv->path); break; case PROP_CONNECTION: g_value_set_object (value, client->priv->connection); break; case PROP_AGENT_PROXY: g_value_set_object (value, client->priv->agent_proxy); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_client_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueServiceClient *client = GCLUE_SERVICE_CLIENT (object); switch (prop_id) { case PROP_CLIENT_INFO: client->priv->client_info = g_value_dup_object (value); break; case PROP_PATH: client->priv->path = g_value_dup_string (value); break; case PROP_CONNECTION: client->priv->connection = g_value_dup_object (value); break; case PROP_AGENT_PROXY: client->priv->agent_proxy = g_value_dup_object (value); if (client->priv->agent_proxy != NULL) g_signal_connect (client->priv->agent_proxy, "g-properties-changed", G_CALLBACK (on_agent_props_changed), object); if (client->priv->pending_auth_start_data != NULL) handle_pending_auth (client); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_client_handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (user_data)->priv; GDBusInterfaceSkeletonClass *skeleton_class; GDBusInterfaceVTable *skeleton_vtable; if (!gclue_client_info_check_bus_name (priv->client_info, sender)) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Access denied"); return; } skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (gclue_service_client_parent_class); skeleton_vtable = skeleton_class->get_vtable (G_DBUS_INTERFACE_SKELETON (user_data)); skeleton_vtable->method_call (connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data); } static GVariant * gclue_service_client_handle_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (user_data)->priv; GDBusInterfaceSkeletonClass *skeleton_class; GDBusInterfaceVTable *skeleton_vtable; if (!gclue_client_info_check_bus_name (priv->client_info, sender)) { g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Access denied"); return NULL; } skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (gclue_service_client_parent_class); skeleton_vtable = skeleton_class->get_vtable (G_DBUS_INTERFACE_SKELETON (user_data)); return skeleton_vtable->get_property (connection, sender, object_path, interface_name, property_name, error, user_data); } static gboolean gclue_service_client_handle_set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *variant, GError **error, gpointer user_data) { GClueDBusClient *client = GCLUE_DBUS_CLIENT (user_data); GClueServiceClientPrivate *priv = GCLUE_SERVICE_CLIENT (client)->priv; GDBusInterfaceSkeletonClass *skeleton_class; GDBusInterfaceVTable *skeleton_vtable; gboolean ret; if (!gclue_client_info_check_bus_name (priv->client_info, sender)) { g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Access denied"); return FALSE; } skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (gclue_service_client_parent_class); skeleton_vtable = skeleton_class->get_vtable (G_DBUS_INTERFACE_SKELETON (user_data)); ret = skeleton_vtable->set_property (connection, sender, object_path, interface_name, property_name, variant, error, user_data); if (ret && strcmp (property_name, "DistanceThreshold") == 0) { priv->distance_threshold = gclue_dbus_client_get_distance_threshold (client); g_debug ("New distance threshold: %u", priv->distance_threshold); } else if (ret && strcmp (property_name, "TimeThreshold") == 0) { priv->time_threshold = gclue_dbus_client_get_time_threshold (client); gclue_locator_set_time_threshold (priv->locator, priv->time_threshold); g_debug ("%s: New time-threshold: %u", G_OBJECT_TYPE_NAME (client), priv->time_threshold); } return ret; } static const GDBusInterfaceVTable gclue_service_client_vtable = { gclue_service_client_handle_method_call, gclue_service_client_handle_get_property, gclue_service_client_handle_set_property, {NULL} }; static GDBusInterfaceVTable * gclue_service_client_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) { return (GDBusInterfaceVTable *) &gclue_service_client_vtable; } static void gclue_service_client_class_init (GClueServiceClientClass *klass) { GObjectClass *object_class; GDBusInterfaceSkeletonClass *skeleton_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_service_client_finalize; object_class->get_property = gclue_service_client_get_property; object_class->set_property = gclue_service_client_set_property; skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); skeleton_class->get_vtable = gclue_service_client_get_vtable; gParamSpecs[PROP_CLIENT_INFO] = g_param_spec_object ("client-info", "ClientInfo", "Information on client", GCLUE_TYPE_CLIENT_INFO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CLIENT_INFO, gParamSpecs[PROP_CLIENT_INFO]); gParamSpecs[PROP_PATH] = g_param_spec_string ("path", "Path", "Path", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_PATH, gParamSpecs[PROP_PATH]); gParamSpecs[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", "DBus Connection", G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, gParamSpecs[PROP_CONNECTION]); gParamSpecs[PROP_AGENT_PROXY] = g_param_spec_object ("agent-proxy", "AgentProxy", "Proxy to app authorization agent", GCLUE_TYPE_AGENT_PROXY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_AGENT_PROXY, gParamSpecs[PROP_AGENT_PROXY]); } static void gclue_service_client_client_iface_init (GClueDBusClientIface *iface) { iface->handle_start = gclue_service_client_handle_start; iface->handle_stop = gclue_service_client_handle_stop; } static gboolean gclue_service_client_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (initable), GCLUE_SERVICE_CLIENT (initable)->priv->connection, GCLUE_SERVICE_CLIENT (initable)->priv->path, error)) return FALSE; return TRUE; } static void gclue_service_client_initable_iface_init (GInitableIface *iface) { iface->init = gclue_service_client_initable_init; } static void gclue_service_client_init (GClueServiceClient *client) { client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, GCLUE_TYPE_SERVICE_CLIENT, GClueServiceClientPrivate); gclue_dbus_client_set_requested_accuracy_level (GCLUE_DBUS_CLIENT (client), DEFAULT_ACCURACY_LEVEL); } GClueServiceClient * gclue_service_client_new (GClueClientInfo *info, const char *path, GDBusConnection *connection, GClueAgent *agent_proxy, GError **error) { return g_initable_new (GCLUE_TYPE_SERVICE_CLIENT, NULL, error, "client-info", info, "path", path, "connection", connection, "agent-proxy", agent_proxy, NULL); } const gchar * gclue_service_client_get_path (GClueServiceClient *client) { g_return_val_if_fail (GCLUE_IS_SERVICE_CLIENT(client), NULL); return client->priv->path; } GClueClientInfo * gclue_service_client_get_client_info (GClueServiceClient *client) { g_return_val_if_fail (GCLUE_IS_SERVICE_CLIENT(client), NULL); return client->priv->client_info; } geoclue-2.5.2/src/gclue-service-client.h000066400000000000000000000057251341441426700201330ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-client.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_SERVICE_CLIENT_H #define GCLUE_SERVICE_CLIENT_H #include #include "gclue-client-interface.h" #include "geoclue-agent-interface.h" #include "gclue-client-info.h" G_BEGIN_DECLS #define GCLUE_TYPE_SERVICE_CLIENT (gclue_service_client_get_type()) #define GCLUE_SERVICE_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_CLIENT, GClueServiceClient)) #define GCLUE_SERVICE_CLIENT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_CLIENT, GClueServiceClient const)) #define GCLUE_SERVICE_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_SERVICE_CLIENT, GClueServiceClientClass)) #define GCLUE_IS_SERVICE_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_SERVICE_CLIENT)) #define GCLUE_IS_SERVICE_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_SERVICE_CLIENT)) #define GCLUE_SERVICE_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_SERVICE_CLIENT, GClueServiceClientClass)) typedef struct _GClueServiceClient GClueServiceClient; typedef struct _GClueServiceClientClass GClueServiceClientClass; typedef struct _GClueServiceClientPrivate GClueServiceClientPrivate; struct _GClueServiceClient { GClueDBusClientSkeleton parent; /*< private >*/ GClueServiceClientPrivate *priv; }; struct _GClueServiceClientClass { GClueDBusClientSkeletonClass parent_class; }; GType gclue_service_client_get_type (void) G_GNUC_CONST; GClueServiceClient * gclue_service_client_new (GClueClientInfo *info, const char *path, GDBusConnection *connection, GClueAgent *agent_proxy, GError **error); const char * gclue_service_client_get_path (GClueServiceClient *client); GClueClientInfo * gclue_service_client_get_client_info (GClueServiceClient *client); G_END_DECLS #endif /* GCLUE_SERVICE_CLIENT_H */ geoclue-2.5.2/src/gclue-service-location.c000066400000000000000000000410301341441426700204450ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-location.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include "gclue-service-location.h" static void gclue_service_location_initable_iface_init (GInitableIface *iface); struct _GClueServiceLocationPrivate { GClueClientInfo *client_info; char *path; GDBusConnection *connection; }; G_DEFINE_TYPE_WITH_CODE (GClueServiceLocation, gclue_service_location, GCLUE_DBUS_TYPE_LOCATION_SKELETON, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gclue_service_location_initable_iface_init) G_ADD_PRIVATE (GClueServiceLocation)); enum { PROP_0, PROP_CLIENT_INFO, PROP_PATH, PROP_CONNECTION, PROP_LOCATION, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static void gclue_service_location_finalize (GObject *object) { GClueServiceLocationPrivate *priv = GCLUE_SERVICE_LOCATION (object)->priv; g_clear_pointer (&priv->path, g_free); g_clear_object (&priv->connection); g_clear_object (&priv->client_info); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_service_location_parent_class)->finalize (object); } static void gclue_service_location_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueServiceLocation *self = GCLUE_SERVICE_LOCATION (object); switch (prop_id) { case PROP_CLIENT_INFO: g_value_set_object (value, self->priv->client_info); break; case PROP_PATH: g_value_set_string (value, self->priv->path); break; case PROP_CONNECTION: g_value_set_object (value, self->priv->connection); break; case PROP_LOCATION: { GClueDBusLocation *location; GClueLocation *loc; GVariant *timestamp; guint64 sec, usec; location = GCLUE_DBUS_LOCATION (object); timestamp = gclue_dbus_location_get_timestamp (location); g_variant_get (timestamp, "(tt)", &sec, &usec); loc = gclue_location_new_full (gclue_dbus_location_get_latitude (location), gclue_dbus_location_get_longitude (location), gclue_dbus_location_get_accuracy (location), gclue_dbus_location_get_speed (location), gclue_dbus_location_get_heading (location), gclue_dbus_location_get_altitude (location), sec, gclue_dbus_location_get_description (location)); g_value_take_object (value, loc); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_location_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueServiceLocation *self = GCLUE_SERVICE_LOCATION (object); switch (prop_id) { case PROP_CLIENT_INFO: self->priv->client_info = g_value_dup_object (value); break; case PROP_PATH: self->priv->path = g_value_dup_string (value); break; case PROP_CONNECTION: self->priv->connection = g_value_dup_object (value); break; case PROP_LOCATION: { GClueDBusLocation *location; GClueLocation *loc; gdouble altitude; GVariant *timestamp; location = GCLUE_DBUS_LOCATION (object); loc = g_value_get_object (value); gclue_dbus_location_set_latitude (location, gclue_location_get_latitude (loc)); gclue_dbus_location_set_longitude (location, gclue_location_get_longitude (loc)); gclue_dbus_location_set_accuracy (location, gclue_location_get_accuracy (loc)); gclue_dbus_location_set_description (location, gclue_location_get_description (loc)); gclue_dbus_location_set_speed (location, gclue_location_get_speed (loc)); gclue_dbus_location_set_heading (location, gclue_location_get_heading (loc)); timestamp = g_variant_new ("(tt)", (guint64) gclue_location_get_timestamp (loc), (guint64) 0); gclue_dbus_location_set_timestamp (location, timestamp); altitude = gclue_location_get_altitude (loc); if (altitude != GCLUE_LOCATION_ALTITUDE_UNKNOWN) gclue_dbus_location_set_altitude (location, altitude); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_location_handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { GClueServiceLocationPrivate *priv = GCLUE_SERVICE_LOCATION (user_data)->priv; GDBusInterfaceSkeletonClass *skeleton_class; GDBusInterfaceVTable *skeleton_vtable; if (!gclue_client_info_check_bus_name (priv->client_info, sender)) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Access denied"); return; } skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (gclue_service_location_parent_class); skeleton_vtable = skeleton_class->get_vtable (G_DBUS_INTERFACE_SKELETON (user_data)); skeleton_vtable->method_call (connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data); } static GVariant * gclue_service_location_handle_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { GClueServiceLocationPrivate *priv = GCLUE_SERVICE_LOCATION (user_data)->priv; GDBusInterfaceSkeletonClass *skeleton_class; GDBusInterfaceVTable *skeleton_vtable; if (!gclue_client_info_check_bus_name (priv->client_info, sender)) { g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Access denied"); return NULL; } skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (gclue_service_location_parent_class); skeleton_vtable = skeleton_class->get_vtable (G_DBUS_INTERFACE_SKELETON (user_data)); return skeleton_vtable->get_property (connection, sender, object_path, interface_name, property_name, error, user_data); } static gboolean gclue_service_location_handle_set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *variant, GError **error, gpointer user_data) { GClueServiceLocationPrivate *priv = GCLUE_SERVICE_LOCATION (user_data)->priv; GDBusInterfaceSkeletonClass *skeleton_class; GDBusInterfaceVTable *skeleton_vtable; if (!gclue_client_info_check_bus_name (priv->client_info, sender)) { g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Access denied"); return FALSE; } skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (gclue_service_location_parent_class); skeleton_vtable = skeleton_class->get_vtable (G_DBUS_INTERFACE_SKELETON (user_data)); return skeleton_vtable->set_property (connection, sender, object_path, interface_name, property_name, variant, error, user_data); } static const GDBusInterfaceVTable gclue_service_location_vtable = { gclue_service_location_handle_method_call, gclue_service_location_handle_get_property, gclue_service_location_handle_set_property, {NULL} }; static GDBusInterfaceVTable * gclue_service_location_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) { return (GDBusInterfaceVTable *) &gclue_service_location_vtable; } static void gclue_service_location_class_init (GClueServiceLocationClass *klass) { GObjectClass *object_class; GDBusInterfaceSkeletonClass *skeleton_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_service_location_finalize; object_class->get_property = gclue_service_location_get_property; object_class->set_property = gclue_service_location_set_property; skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); skeleton_class->get_vtable = gclue_service_location_get_vtable; gParamSpecs[PROP_CLIENT_INFO] = g_param_spec_object ("client-info", "ClientInfo", "Information on client", GCLUE_TYPE_CLIENT_INFO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CLIENT_INFO, gParamSpecs[PROP_CLIENT_INFO]); gParamSpecs[PROP_PATH] = g_param_spec_string ("path", "Path", "Path", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_PATH, gParamSpecs[PROP_PATH]); gParamSpecs[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", "DBus Connection", G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, gParamSpecs[PROP_CONNECTION]); gParamSpecs[PROP_LOCATION] = g_param_spec_object ("location", "Location", "Location", GCLUE_TYPE_LOCATION, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_LOCATION, gParamSpecs[PROP_LOCATION]); } static void gclue_service_location_init (GClueServiceLocation *location) { location->priv = G_TYPE_INSTANCE_GET_PRIVATE (location, GCLUE_TYPE_SERVICE_LOCATION, GClueServiceLocationPrivate); gclue_dbus_location_set_altitude (GCLUE_DBUS_LOCATION (location), GCLUE_LOCATION_ALTITUDE_UNKNOWN); } static gboolean gclue_service_location_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (initable), GCLUE_SERVICE_LOCATION (initable)->priv->connection, GCLUE_SERVICE_LOCATION (initable)->priv->path, error); } static void gclue_service_location_initable_iface_init (GInitableIface *iface) { iface->init = gclue_service_location_initable_init; } GClueServiceLocation * gclue_service_location_new (GClueClientInfo *info, const char *path, GDBusConnection *connection, GClueLocation *location, GError **error) { return g_initable_new (GCLUE_TYPE_SERVICE_LOCATION, NULL, error, "client-info", info, "path", path, "connection", connection, "location", location, NULL); } const gchar * gclue_service_location_get_path (GClueServiceLocation *location) { g_return_val_if_fail (GCLUE_IS_SERVICE_LOCATION(location), NULL); return location->priv->path; } geoclue-2.5.2/src/gclue-service-location.h000066400000000000000000000057021341441426700204600ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-location.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_SERVICE_LOCATION_H #define GCLUE_SERVICE_LOCATION_H #include #include "gclue-location.h" #include "gclue-client-info.h" #include "gclue-location-interface.h" G_BEGIN_DECLS #define GCLUE_TYPE_SERVICE_LOCATION (gclue_service_location_get_type()) #define GCLUE_SERVICE_LOCATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_LOCATION, GClueServiceLocation)) #define GCLUE_SERVICE_LOCATION_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_LOCATION, GClueServiceLocation const)) #define GCLUE_SERVICE_LOCATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_SERVICE_LOCATION, GClueServiceLocationClass)) #define GCLUE_IS_SERVICE_LOCATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_SERVICE_LOCATION)) #define GCLUE_IS_SERVICE_LOCATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_SERVICE_LOCATION)) #define GCLUE_SERVICE_LOCATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_SERVICE_LOCATION, GClueServiceLocationClass)) typedef struct _GClueServiceLocation GClueServiceLocation; typedef struct _GClueServiceLocationClass GClueServiceLocationClass; typedef struct _GClueServiceLocationPrivate GClueServiceLocationPrivate; struct _GClueServiceLocation { GClueDBusLocationSkeleton parent; /*< private >*/ GClueServiceLocationPrivate *priv; }; struct _GClueServiceLocationClass { GClueDBusLocationSkeletonClass parent_class; }; GType gclue_service_location_get_type (void) G_GNUC_CONST; GClueServiceLocation * gclue_service_location_new (GClueClientInfo *info, const char *path, GDBusConnection *connection, GClueLocation *location, GError **error); const char * gclue_service_location_get_path (GClueServiceLocation *location); G_END_DECLS #endif /* GCLUE_SERVICE_LOCATION_H */ geoclue-2.5.2/src/gclue-service-manager.c000066400000000000000000000607601341441426700202620ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-manager.c * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #include #include #include "gclue-service-manager.h" #include "gclue-service-client.h" #include "gclue-client-info.h" #include "geoclue-agent-interface.h" #include "gclue-enums.h" #include "gclue-locator.h" #include "gclue-config.h" /* 20 seconds as milliseconds */ #define AGENT_WAIT_TIMEOUT 20000 /* 20 seconds as microseconds */ #define AGENT_WAIT_TIMEOUT_USEC (20 * G_USEC_PER_SEC) static void gclue_service_manager_manager_iface_init (GClueDBusManagerIface *iface); static void gclue_service_manager_initable_iface_init (GInitableIface *iface); struct _GClueServiceManagerPrivate { GDBusConnection *connection; GList *clients; GHashTable *agents; guint last_client_id; guint num_clients; gint64 init_time; GClueLocator *locator; }; G_DEFINE_TYPE_WITH_CODE (GClueServiceManager, gclue_service_manager, GCLUE_DBUS_TYPE_MANAGER_SKELETON, G_IMPLEMENT_INTERFACE (GCLUE_DBUS_TYPE_MANAGER, gclue_service_manager_manager_iface_init) G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gclue_service_manager_initable_iface_init) G_ADD_PRIVATE (GClueServiceManager)) enum { PROP_0, PROP_CONNECTION, PROP_ACTIVE, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static void sync_in_use_property (GClueServiceManager *manager) { gboolean in_use = FALSE; GList *l; GClueDBusManager *gdbus_manager; for (l = manager->priv->clients; l != NULL; l = l->next) { GClueDBusClient *client = GCLUE_DBUS_CLIENT (l->data); GClueConfig *config; const char *id; id = gclue_dbus_client_get_desktop_id (client); config = gclue_config_get_singleton (); if (gclue_dbus_client_get_active (client) && !gclue_config_is_system_component (config, id)) { in_use = TRUE; break; } } gdbus_manager = GCLUE_DBUS_MANAGER (manager); if (in_use != gclue_dbus_manager_get_in_use (gdbus_manager)) gclue_dbus_manager_set_in_use (gdbus_manager, in_use); } static int compare_client_bus_name (gconstpointer a, gconstpointer b) { GClueClientInfo *info; const char *bus_name = (const char *) b; info = gclue_service_client_get_client_info (GCLUE_SERVICE_CLIENT (a)); return g_strcmp0 (bus_name, gclue_client_info_get_bus_name (info)); } static void delete_client (GClueServiceManager *manager, GCompareFunc compare_func, gpointer compare_func_data) { GClueServiceManagerPrivate *priv = manager->priv; GList *l; l = priv->clients; while (l != NULL) { GList *next = l->next; if (compare_func (l->data, compare_func_data) == 0) { g_object_unref (G_OBJECT (l->data)); priv->clients = g_list_remove_link (priv->clients, l); priv->num_clients--; if (priv->num_clients == 0) { g_object_notify (G_OBJECT (manager), "active"); } } l = next; } g_debug ("Number of connected clients: %u", priv->num_clients); sync_in_use_property (manager); } static void on_peer_vanished (GClueClientInfo *info, gpointer user_data) { const char *bus_name; bus_name = gclue_client_info_get_bus_name (info); g_debug ("Client `%s` vanished. Dropping associated client objects", bus_name); delete_client (GCLUE_SERVICE_MANAGER (user_data), compare_client_bus_name, (char *) bus_name); } typedef struct { GClueDBusManager *manager; GDBusMethodInvocation *invocation; GClueClientInfo *client_info; gboolean reuse_client; } OnClientInfoNewReadyData; static gboolean complete_get_client (OnClientInfoNewReadyData *data) { GClueServiceManagerPrivate *priv = GCLUE_SERVICE_MANAGER (data->manager)->priv; GClueServiceClient *client; GClueClientInfo *info = data->client_info; GClueAgent *agent_proxy = NULL; GError *error = NULL; char *path; guint32 user_id; user_id = gclue_client_info_get_user_id (info); agent_proxy = g_hash_table_lookup (priv->agents, GINT_TO_POINTER (user_id)); if (data->reuse_client) { GList *node; const char *peer; peer = g_dbus_method_invocation_get_sender (data->invocation); node = g_list_find_custom (priv->clients, peer, compare_client_bus_name); if (node != NULL) { GClueServiceClient *client; client = GCLUE_SERVICE_CLIENT (node->data); path = g_strdup (gclue_service_client_get_path (client)); goto client_created; } } path = g_strdup_printf ("/org/freedesktop/GeoClue2/Client/%u", ++priv->last_client_id); client = gclue_service_client_new (info, path, priv->connection, agent_proxy, &error); if (client == NULL) goto error_out; priv->clients = g_list_prepend (priv->clients, client); priv->num_clients++; if (priv->num_clients == 1) { g_object_notify (G_OBJECT (data->manager), "active"); } g_debug ("Number of connected clients: %u", priv->num_clients); g_signal_connect (info, "peer-vanished", G_CALLBACK (on_peer_vanished), data->manager); client_created: if (data->reuse_client) gclue_dbus_manager_complete_get_client (data->manager, data->invocation, path); else gclue_dbus_manager_complete_create_client (data->manager, data->invocation, path); goto out; error_out: g_dbus_method_invocation_return_error_literal (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, error->message); out: g_clear_error (&error); g_clear_object (&info); g_slice_free (OnClientInfoNewReadyData, data); g_free (path); return FALSE; } static void on_client_info_new_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { OnClientInfoNewReadyData *data = (OnClientInfoNewReadyData *) user_data; GClueServiceManagerPrivate *priv = GCLUE_SERVICE_MANAGER (data->manager)->priv; GClueClientInfo *info = NULL; GClueAgent *agent_proxy; GError *error = NULL; guint32 user_id; gint64 now; info = gclue_client_info_new_finish (res, &error); if (info == NULL) { g_dbus_method_invocation_return_error_literal (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, error->message); g_error_free (error); g_slice_free (OnClientInfoNewReadyData, data); return; } data->client_info = info; user_id = gclue_client_info_get_user_id (info); agent_proxy = g_hash_table_lookup (priv->agents, GINT_TO_POINTER (user_id)); now = g_get_monotonic_time (); if (agent_proxy == NULL && now < (priv->init_time + AGENT_WAIT_TIMEOUT_USEC)) { /* Its possible that geoclue was just launched on GetClient * call, in which case agents need some time to register * themselves to us. */ g_timeout_add (AGENT_WAIT_TIMEOUT, (GSourceFunc) complete_get_client, user_data); return; } complete_get_client (data); } static void handle_get_client (GClueDBusManager *manager, GDBusMethodInvocation *invocation, gboolean reuse_client) { GClueServiceManager *self = GCLUE_SERVICE_MANAGER (manager); GClueServiceManagerPrivate *priv = self->priv; const char *peer; OnClientInfoNewReadyData *data; peer = g_dbus_method_invocation_get_sender (invocation); data = g_slice_new (OnClientInfoNewReadyData); data->manager = manager; data->invocation = invocation; data->reuse_client = reuse_client; gclue_client_info_new_async (peer, priv->connection, NULL, on_client_info_new_ready, data); } static gboolean gclue_service_manager_handle_get_client (GClueDBusManager *manager, GDBusMethodInvocation *invocation) { handle_get_client (manager, invocation, TRUE); return TRUE; } static gboolean gclue_service_manager_handle_create_client (GClueDBusManager *manager, GDBusMethodInvocation *invocation) { handle_get_client (manager, invocation, FALSE); return TRUE; } typedef struct { const char *path; const char *bus_name; } CompareClientPathNBusNameData; static int compare_client_path_n_bus_name (gconstpointer a, gconstpointer b) { GClueServiceClient *client = GCLUE_SERVICE_CLIENT (a); CompareClientPathNBusNameData *data = (CompareClientPathNBusNameData *) b; GClueClientInfo *info; info = gclue_service_client_get_client_info (client); if (g_strcmp0 (data->bus_name, gclue_client_info_get_bus_name (info)) == 0 && g_strcmp0 (data->path, gclue_service_client_get_path (client)) == 0) return 0; else return 1; } static gboolean gclue_service_manager_handle_delete_client (GClueDBusManager *manager, GDBusMethodInvocation *invocation, const char *path) { CompareClientPathNBusNameData data; data.path = path; data.bus_name = g_dbus_method_invocation_get_sender (invocation); delete_client (GCLUE_SERVICE_MANAGER (manager), compare_client_path_n_bus_name, &data); gclue_dbus_manager_complete_delete_client (manager, invocation); return TRUE; } typedef struct { GClueDBusManager *manager; GDBusMethodInvocation *invocation; GClueClientInfo *info; char *desktop_id; } AddAgentData; static void add_agent_data_free (AddAgentData *data) { g_clear_pointer (&data->desktop_id, g_free); g_slice_free (AddAgentData, data); } static void on_agent_vanished (GClueClientInfo *info, gpointer user_data) { GClueServiceManager *manager = GCLUE_SERVICE_MANAGER (user_data); guint32 user_id; user_id = gclue_client_info_get_user_id (info); g_debug ("Agent for user '%u' vanished", user_id); g_hash_table_remove (manager->priv->agents, GINT_TO_POINTER (user_id)); g_object_unref (info); } static void on_agent_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { AddAgentData *data = (AddAgentData *) user_data; GClueServiceManagerPrivate *priv = GCLUE_SERVICE_MANAGER (data->manager)->priv; guint32 user_id; GClueAgent *agent; GError *error = NULL; agent = gclue_agent_proxy_new_for_bus_finish (res, &error); if (agent == NULL) goto error_out; user_id = gclue_client_info_get_user_id (data->info); g_debug ("New agent for user ID '%u'", user_id); g_hash_table_replace (priv->agents, GINT_TO_POINTER (user_id), agent); g_signal_connect (data->info, "peer-vanished", G_CALLBACK (on_agent_vanished), data->manager); gclue_dbus_manager_complete_add_agent (data->manager, data->invocation); goto out; error_out: g_dbus_method_invocation_return_error_literal (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, error->message); out: g_clear_error (&error); add_agent_data_free (data); } #define AGENT_PATH "/org/freedesktop/GeoClue2/Agent" static void on_agent_info_new_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { AddAgentData *data = (AddAgentData *) user_data; GError *error = NULL; GClueConfig *config; const char *xdg_id; data->info = gclue_client_info_new_finish (res, &error); if (data->info == NULL) { g_dbus_method_invocation_return_error_literal (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, error->message); g_error_free (error); add_agent_data_free (data); return; } xdg_id = gclue_client_info_get_xdg_id (data->info); config = gclue_config_get_singleton (); if (xdg_id != NULL || !gclue_config_is_agent_allowed (config, data->desktop_id, data->info)) { g_dbus_method_invocation_return_error (data->invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "%s not allowed to act as agent", data->desktop_id); add_agent_data_free (data); return; } gclue_agent_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, gclue_client_info_get_bus_name (data->info), AGENT_PATH, NULL, on_agent_proxy_ready, user_data); } static gboolean gclue_service_manager_handle_add_agent (GClueDBusManager *manager, GDBusMethodInvocation *invocation, const char *id) { GClueServiceManager *self = GCLUE_SERVICE_MANAGER (manager); GClueServiceManagerPrivate *priv = self->priv; const char *peer; AddAgentData *data; peer = g_dbus_method_invocation_get_sender (invocation); data = g_slice_new0 (AddAgentData); data->manager = manager; data->invocation = invocation; data->desktop_id = g_strdup (id); gclue_client_info_new_async (peer, priv->connection, NULL, on_agent_info_new_ready, data); return TRUE; } static void gclue_service_manager_finalize (GObject *object) { GClueServiceManagerPrivate *priv = GCLUE_SERVICE_MANAGER (object)->priv; g_clear_object (&priv->locator); g_clear_object (&priv->connection); if (priv->clients != NULL) { g_list_free_full (priv->clients, g_object_unref); priv->clients = NULL; } g_clear_pointer (&priv->agents, g_hash_table_unref); /* Chain up to the parent class */ G_OBJECT_CLASS (gclue_service_manager_parent_class)->finalize (object); } static void gclue_service_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueServiceManager *manager = GCLUE_SERVICE_MANAGER (object); switch (prop_id) { case PROP_CONNECTION: g_value_set_object (value, manager->priv->connection); break; case PROP_ACTIVE: g_value_set_boolean (value, (manager->priv->num_clients != 0)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_service_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueServiceManager *manager = GCLUE_SERVICE_MANAGER (object); switch (prop_id) { case PROP_CONNECTION: manager->priv->connection = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void on_avail_accuracy_level_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { GClueServiceManagerPrivate *priv = GCLUE_SERVICE_MANAGER (user_data)->priv; GClueAccuracyLevel level; level = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (priv->locator)); gclue_dbus_manager_set_available_accuracy_level (GCLUE_DBUS_MANAGER (user_data), level); } static void gclue_service_manager_constructed (GObject *object) { GClueServiceManagerPrivate *priv = GCLUE_SERVICE_MANAGER (object)->priv; G_OBJECT_CLASS (gclue_service_manager_parent_class)->constructed (object); priv->locator = gclue_locator_new (GCLUE_ACCURACY_LEVEL_EXACT); g_signal_connect (G_OBJECT (priv->locator), "notify::available-accuracy-level", G_CALLBACK (on_avail_accuracy_level_changed), object); on_avail_accuracy_level_changed (G_OBJECT (priv->locator), NULL, object); } static void gclue_service_manager_class_init (GClueServiceManagerClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gclue_service_manager_finalize; object_class->get_property = gclue_service_manager_get_property; object_class->set_property = gclue_service_manager_set_property; object_class->constructed = gclue_service_manager_constructed; gParamSpecs[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", "DBus Connection", G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, gParamSpecs[PROP_CONNECTION]); /** * GClueServiceManager:active: * * Unlike the D-Bus 'InUse' property, this indicates wether or not * currently we have connected clients. */ gParamSpecs[PROP_ACTIVE] = g_param_spec_boolean ("active", "Active", "If manager is active", FALSE, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_ACTIVE, gParamSpecs[PROP_ACTIVE]); } static void gclue_service_manager_init (GClueServiceManager *manager) { manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, GCLUE_TYPE_SERVICE_MANAGER, GClueServiceManagerPrivate); manager->priv->agents = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); manager->priv->init_time = g_get_monotonic_time (); } static gboolean gclue_service_manager_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (initable), GCLUE_SERVICE_MANAGER (initable)->priv->connection, "/org/freedesktop/GeoClue2/Manager", error); } static void gclue_service_manager_manager_iface_init (GClueDBusManagerIface *iface) { iface->handle_get_client = gclue_service_manager_handle_get_client; iface->handle_create_client = gclue_service_manager_handle_create_client; iface->handle_delete_client = gclue_service_manager_handle_delete_client; iface->handle_add_agent = gclue_service_manager_handle_add_agent; } static void gclue_service_manager_initable_iface_init (GInitableIface *iface) { iface->init = gclue_service_manager_initable_init; } GClueServiceManager * gclue_service_manager_new (GDBusConnection *connection, GError **error) { return g_initable_new (GCLUE_TYPE_SERVICE_MANAGER, NULL, error, "connection", connection, NULL); } gboolean gclue_service_manager_get_active (GClueServiceManager *manager) { return (manager->priv->num_clients != 0); } geoclue-2.5.2/src/gclue-service-manager.h000066400000000000000000000051301341441426700202550ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* gclue-service-manager.h * * Copyright 2013 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Zeeshan Ali (Khattak) */ #ifndef GCLUE_SERVICE_MANAGER_H #define GCLUE_SERVICE_MANAGER_H #include #include "gclue-manager-interface.h" G_BEGIN_DECLS #define GCLUE_TYPE_SERVICE_MANAGER (gclue_service_manager_get_type()) #define GCLUE_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_MANAGER, GClueServiceManager)) #define GCLUE_SERVICE_MANAGER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_SERVICE_MANAGER, GClueServiceManager const)) #define GCLUE_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_SERVICE_MANAGER, GClueServiceManagerClass)) #define GCLUE_IS_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_SERVICE_MANAGER)) #define GCLUE_IS_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_SERVICE_MANAGER)) #define GCLUE_SERVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_SERVICE_MANAGER, GClueServiceManagerClass)) typedef struct _GClueServiceManager GClueServiceManager; typedef struct _GClueServiceManagerClass GClueServiceManagerClass; typedef struct _GClueServiceManagerPrivate GClueServiceManagerPrivate; struct _GClueServiceManager { GClueDBusManagerSkeleton parent; /*< private >*/ GClueServiceManagerPrivate *priv; }; struct _GClueServiceManagerClass { GClueDBusManagerSkeletonClass parent_class; }; GType gclue_service_manager_get_type (void) G_GNUC_CONST; GClueServiceManager * gclue_service_manager_new (GDBusConnection *connection, GError **error); gboolean gclue_service_manager_get_active (GClueServiceManager *manager); G_END_DECLS #endif /* GCLUE_SERVICE_MANAGER_H */ geoclue-2.5.2/src/gclue-web-source.c000066400000000000000000000313671341441426700172660ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include #include #include "gclue-web-source.h" #include "gclue-error.h" #include "gclue-location.h" /** * SECTION:gclue-web-source * @short_description: Web-based geolocation * @include: gclue-glib/gclue-web-source.h * * Baseclass for all sources that solely use a web resource for geolocation. **/ static gboolean gclue_web_source_start (GClueLocationSource *source); struct _GClueWebSourcePrivate { SoupSession *soup_session; SoupMessage *query; gulong network_changed_id; gulong connectivity_changed_id; guint64 last_submitted; gboolean internet_available; }; G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GClueWebSource, gclue_web_source, GCLUE_TYPE_LOCATION_SOURCE, G_ADD_PRIVATE (GClueWebSource)) static void query_callback (SoupSession *session, SoupMessage *query, gpointer user_data) { GClueWebSource *web; GError *error = NULL; char *contents; char *str; GClueLocation *location; SoupURI *uri; if (query->status_code == SOUP_STATUS_CANCELLED) return; web = GCLUE_WEB_SOURCE (user_data); web->priv->query = NULL; if (query->status_code != SOUP_STATUS_OK) { g_warning ("Failed to query location: %s", query->reason_phrase); return; } contents = g_strndup (query->response_body->data, query->response_body->length); uri = soup_message_get_uri (query); str = soup_uri_to_string (uri, FALSE); g_debug ("Got following response from '%s':\n%s", str, contents); g_free (str); location = GCLUE_WEB_SOURCE_GET_CLASS (web)->parse_response (web, contents, &error); g_free (contents); if (error != NULL) { g_warning ("Failed to parse following response: %s\n%s", error->message, contents); return; } gclue_location_source_set_location (GCLUE_LOCATION_SOURCE (web), location); g_object_unref (location); } static gboolean get_internet_available (void) { GNetworkMonitor *monitor = g_network_monitor_get_default (); gboolean available; available = (g_network_monitor_get_connectivity (monitor) == G_NETWORK_CONNECTIVITY_FULL); return available; } static void refresh_accuracy_level (GClueWebSource *web) { GClueAccuracyLevel new, existing; existing = gclue_location_source_get_available_accuracy_level (GCLUE_LOCATION_SOURCE (web)); new = GCLUE_WEB_SOURCE_GET_CLASS (web)->get_available_accuracy_level (web, web->priv->internet_available); if (new != existing) { g_debug ("Available accuracy level from %s: %u", G_OBJECT_TYPE_NAME (web), new); g_object_set (G_OBJECT (web), "available-accuracy-level", new, NULL); } } static void on_network_changed (GNetworkMonitor *monitor G_GNUC_UNUSED, gboolean available G_GNUC_UNUSED, gpointer user_data) { GClueWebSource *web = GCLUE_WEB_SOURCE (user_data); GError *error = NULL; gboolean last_available = web->priv->internet_available; web->priv->internet_available = get_internet_available (); if (last_available == web->priv->internet_available) return; /* We already reacted to network change */ refresh_accuracy_level (web); if (!gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (user_data))) return; if (!web->priv->internet_available) { g_debug ("Network unavailable"); return; } g_debug ("Network available"); if (web->priv->query != NULL) return; web->priv->query = GCLUE_WEB_SOURCE_GET_CLASS (web)->create_query (web, &error); if (web->priv->query == NULL) { g_warning ("Failed to create query: %s", error->message); g_error_free (error); return; } soup_session_queue_message (web->priv->soup_session, web->priv->query, query_callback, web); } static void on_connectivity_changed (GObject *gobject, GParamSpec *pspec, gpointer user_data) { on_network_changed (NULL, FALSE, user_data); } static void gclue_web_source_finalize (GObject *gsource) { GClueWebSourcePrivate *priv = GCLUE_WEB_SOURCE (gsource)->priv; if (priv->network_changed_id) { g_signal_handler_disconnect (g_network_monitor_get_default (), priv->network_changed_id); priv->network_changed_id = 0; } if (priv->connectivity_changed_id) { g_signal_handler_disconnect (g_network_monitor_get_default (), priv->connectivity_changed_id); priv->connectivity_changed_id = 0; } if (priv->query != NULL) { g_debug ("Cancelling query"); soup_session_cancel_message (priv->soup_session, priv->query, SOUP_STATUS_CANCELLED); priv->query = NULL; } g_clear_object (&priv->soup_session); G_OBJECT_CLASS (gclue_web_source_parent_class)->finalize (gsource); } static void gclue_web_source_constructed (GObject *object) { GNetworkMonitor *monitor; GClueWebSourcePrivate *priv = GCLUE_WEB_SOURCE (object)->priv; G_OBJECT_CLASS (gclue_web_source_parent_class)->constructed (object); priv->soup_session = soup_session_new_with_options (SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT, NULL); monitor = g_network_monitor_get_default (); priv->network_changed_id = g_signal_connect (monitor, "network-changed", G_CALLBACK (on_network_changed), object); priv->connectivity_changed_id = g_signal_connect (monitor, "notify::connectivity", G_CALLBACK (on_connectivity_changed), object); on_network_changed (NULL, TRUE, object); } static void gclue_web_source_class_init (GClueWebSourceClass *klass) { GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *gsource_class = G_OBJECT_CLASS (klass); source_class->start = gclue_web_source_start; gsource_class->finalize = gclue_web_source_finalize; gsource_class->constructed = gclue_web_source_constructed; } static void gclue_web_source_init (GClueWebSource *web) { web->priv = G_TYPE_INSTANCE_GET_PRIVATE ((web), GCLUE_TYPE_WEB_SOURCE, GClueWebSourcePrivate); } /** * gclue_web_source_refresh: * @source: a #GClueWebSource * * Causes @source to refresh location and available accuracy level. Its meant * to be used by subclasses if they have reason to suspect location and/or * available accuracy level might have changed. **/ void gclue_web_source_refresh (GClueWebSource *source) { g_return_if_fail (GCLUE_IS_WEB_SOURCE (source)); /* Make sure ->internet_available is different from * the real availability of internet access */ source->priv->internet_available = FALSE; on_network_changed (NULL, TRUE, source); } static gboolean gclue_web_source_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_web_source_parent_class); if (!base_class->start (source)) return FALSE; return TRUE; } static void submit_query_callback (SoupSession *session, SoupMessage *query, gpointer user_data) { SoupURI *uri; uri = soup_message_get_uri (query); if (query->status_code != SOUP_STATUS_OK && query->status_code != SOUP_STATUS_NO_CONTENT) { g_warning ("Failed to submit location data to '%s': %s", soup_uri_to_string (uri, FALSE), query->reason_phrase); return; } g_debug ("Successfully submitted location data to '%s'", soup_uri_to_string (uri, FALSE)); } #define SUBMISSION_ACCURACY_THRESHOLD 100 #define SUBMISSION_TIME_THRESHOLD 60 /* seconds */ static void on_submit_source_location_notify (GObject *source_object, GParamSpec *pspec, gpointer user_data) { GClueLocationSource *source = GCLUE_LOCATION_SOURCE (source_object); GClueWebSource *web = GCLUE_WEB_SOURCE (user_data); GClueLocation *location; SoupMessage *query; GError *error = NULL; location = gclue_location_source_get_location (source); if (location == NULL || gclue_location_get_accuracy (location) > SUBMISSION_ACCURACY_THRESHOLD || gclue_location_get_timestamp (location) < web->priv->last_submitted + SUBMISSION_TIME_THRESHOLD) return; web->priv->last_submitted = gclue_location_get_timestamp (location); if (!get_internet_available ()) return; query = GCLUE_WEB_SOURCE_GET_CLASS (web)->create_submit_query (web, location, &error); if (query == NULL) { if (error != NULL) { g_warning ("Failed to create submission query: %s", error->message); g_error_free (error); } return; } soup_session_queue_message (web->priv->soup_session, query, submit_query_callback, web); } /** * gclue_web_source_set_submit_source: * @source: a #GClueWebSource * * Use this function to provide a location source to @source that is used * for submitting location data to resource being used by @source. This will be * a #GClueModemGPS but we don't assume that here, in case we later add a * non-modem GPS source and would like to pass that instead. **/ void gclue_web_source_set_submit_source (GClueWebSource *web, GClueLocationSource *submit_source) { /* Not implemented by subclass */ if (GCLUE_WEB_SOURCE_GET_CLASS (web)->create_submit_query == NULL) return; g_signal_connect_object (G_OBJECT (submit_source), "notify::location", G_CALLBACK (on_submit_source_location_notify), G_OBJECT (web), 0); on_submit_source_location_notify (G_OBJECT (submit_source), NULL, web); } geoclue-2.5.2/src/gclue-web-source.h000066400000000000000000000066511341441426700172710ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_WEB_SOURCE_H #define GCLUE_WEB_SOURCE_H #include #include #include "gclue-location-source.h" #include G_BEGIN_DECLS GType gclue_web_source_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_WEB_SOURCE (gclue_web_source_get_type ()) #define GCLUE_WEB_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_WEB_SOURCE, GClueWebSource)) #define GCLUE_IS_WEB_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_WEB_SOURCE)) #define GCLUE_WEB_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_WEB_SOURCE, GClueWebSourceClass)) #define GCLUE_IS_WEB_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_WEB_SOURCE)) #define GCLUE_WEB_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_WEB_SOURCE, GClueWebSourceClass)) /** * GClueWebSource: * * All the fields in the #GClueWebSource structure are private and should never be accessed directly. **/ typedef struct _GClueWebSource GClueWebSource; typedef struct _GClueWebSourceClass GClueWebSourceClass; typedef struct _GClueWebSourcePrivate GClueWebSourcePrivate; struct _GClueWebSource { /* */ GClueLocationSource parent_instance; GClueWebSourcePrivate *priv; }; /** * GClueWebSourceClass: * * All the fields in the #GClueWebSourceClass structure are private and should never be accessed directly. **/ struct _GClueWebSourceClass { /* */ GClueLocationSourceClass parent_class; SoupMessage * (*create_query) (GClueWebSource *source, GError **error); SoupMessage * (*create_submit_query) (GClueWebSource *source, GClueLocation *location, GError **error); GClueLocation * (*parse_response) (GClueWebSource *source, const char *response, GError **error); GClueAccuracyLevel (*get_available_accuracy_level) (GClueWebSource *source, gboolean network_available); }; void gclue_web_source_refresh (GClueWebSource *source); void gclue_web_source_set_submit_source (GClueWebSource *source, GClueLocationSource *submit_source); G_END_DECLS #endif /* GCLUE_WEB_SOURCE_H */ geoclue-2.5.2/src/gclue-wifi.c000066400000000000000000000662121341441426700161460ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #include #include #include #include #include "gclue-wifi.h" #include "gclue-config.h" #include "gclue-error.h" #include "gclue-mozilla.h" #define WIFI_SCAN_TIMEOUT_HIGH_ACCURACY 10 /* Since this is only used for city-level accuracy, 5 minutes betweeen each * scan is more than enough. */ #define WIFI_SCAN_TIMEOUT_LOW_ACCURACY 300 /** * SECTION:gclue-wifi * @short_description: WiFi-based geolocation * @include: gclue-glib/gclue-wifi.h * * Contains functions to get the geolocation based on nearby WiFi networks. **/ static gboolean gclue_wifi_start (GClueLocationSource *source); static gboolean gclue_wifi_stop (GClueLocationSource *source); struct _GClueWifiPrivate { WPASupplicant *supplicant; WPAInterface *interface; GHashTable *bss_proxies; GHashTable *ignored_bss_proxies; gboolean bss_list_changed; gulong bss_added_id; gulong bss_removed_id; gulong scan_done_id; guint scan_timeout; GClueAccuracyLevel accuracy_level; }; enum { PROP_0, PROP_ACCURACY_LEVEL, LAST_PROP }; static GParamSpec *gParamSpecs[LAST_PROP]; static SoupMessage * gclue_wifi_create_query (GClueWebSource *source, GError **error); static SoupMessage * gclue_wifi_create_submit_query (GClueWebSource *source, GClueLocation *location, GError **error); static GClueLocation * gclue_wifi_parse_response (GClueWebSource *source, const char *json, GError **error); static GClueAccuracyLevel gclue_wifi_get_available_accuracy_level (GClueWebSource *source, gboolean net_available); G_DEFINE_TYPE_WITH_CODE (GClueWifi, gclue_wifi, GCLUE_TYPE_WEB_SOURCE, G_ADD_PRIVATE (GClueWifi)) static void disconnect_bss_signals (GClueWifi *wifi); static void on_scan_call_done (GObject *source_object, GAsyncResult *res, gpointer user_data); static void on_scan_done (WPAInterface *object, gboolean success, gpointer user_data); static void gclue_wifi_finalize (GObject *gwifi) { GClueWifi *wifi = (GClueWifi *) gwifi; G_OBJECT_CLASS (gclue_wifi_parent_class)->finalize (gwifi); disconnect_bss_signals (wifi); g_clear_object (&wifi->priv->supplicant); g_clear_object (&wifi->priv->interface); g_clear_pointer (&wifi->priv->bss_proxies, g_hash_table_unref); g_clear_pointer (&wifi->priv->ignored_bss_proxies, g_hash_table_unref); } static void gclue_wifi_constructed (GObject *object); static void gclue_wifi_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GClueWifi *wifi = GCLUE_WIFI (object); switch (prop_id) { case PROP_ACCURACY_LEVEL: g_value_set_enum (value, wifi->priv->accuracy_level); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_wifi_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GClueWifi *wifi = GCLUE_WIFI (object); switch (prop_id) { case PROP_ACCURACY_LEVEL: wifi->priv->accuracy_level = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gclue_wifi_class_init (GClueWifiClass *klass) { GClueWebSourceClass *web_class = GCLUE_WEB_SOURCE_CLASS (klass); GClueLocationSourceClass *source_class = GCLUE_LOCATION_SOURCE_CLASS (klass); GObjectClass *gwifi_class = G_OBJECT_CLASS (klass); source_class->start = gclue_wifi_start; source_class->stop = gclue_wifi_stop; web_class->create_submit_query = gclue_wifi_create_submit_query; web_class->create_query = gclue_wifi_create_query; web_class->parse_response = gclue_wifi_parse_response; web_class->get_available_accuracy_level = gclue_wifi_get_available_accuracy_level; gwifi_class->get_property = gclue_wifi_get_property; gwifi_class->set_property = gclue_wifi_set_property; gwifi_class->finalize = gclue_wifi_finalize; gwifi_class->constructed = gclue_wifi_constructed; gParamSpecs[PROP_ACCURACY_LEVEL] = g_param_spec_enum ("accuracy-level", "AccuracyLevel", "Max accuracy level", GCLUE_TYPE_ACCURACY_LEVEL, GCLUE_ACCURACY_LEVEL_CITY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (gwifi_class, PROP_ACCURACY_LEVEL, gParamSpecs[PROP_ACCURACY_LEVEL]); } static void on_bss_added (WPAInterface *object, const gchar *path, GVariant *properties, gpointer user_data); static char * variant_to_string (GVariant *variant, guint *len) { guint n_bytes, i; char *ret; n_bytes = g_variant_n_children (variant); if (len != NULL) *len = n_bytes; if (n_bytes <= 0) return NULL; ret = g_malloc (n_bytes + 1); ret[n_bytes] = '\0'; for (i = 0; i < n_bytes; i++) g_variant_get_child (variant, i, "y", &ret[i]); return ret; } static char * get_ssid_from_bss (WPABSS *bss) { GVariant *variant = wpa_bss_get_ssid (bss); return variant_to_string (variant, NULL); } static char * get_bssid_from_bss (WPABSS *bss) { GVariant *variant; char *raw_bssid; char *bssid; guint raw_len, len, i, j; variant = wpa_bss_get_bssid (bss); raw_bssid = variant_to_string (variant, &raw_len); len = raw_len * 2 + raw_len; bssid = g_malloc (len); for (i = 0, j = 0; i < len; i = i + 3, j++) g_snprintf (bssid + i, 4, "%02x:", (unsigned char) raw_bssid[j]); bssid[len - 1] = '\0'; return bssid; } static void add_bss_proxy (GClueWifi *wifi, WPABSS *bss) { const char *path; path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (bss)); if (g_hash_table_replace (wifi->priv->bss_proxies, g_strdup (path), bss)) { char *ssid; wifi->priv->bss_list_changed = TRUE; ssid = get_ssid_from_bss (bss); g_debug ("WiFi AP '%s' added.", ssid); g_free (ssid); } } static void on_bss_signal_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); WPABSS *bss = WPA_BSS (gobject); const char *path; if (wpa_bss_get_signal (bss) <= -90) { char *bssid = get_bssid_from_bss (bss); g_debug ("WiFi AP '%s' still has very low strength (%u dBm)" ", ignoring again..", bssid, wpa_bss_get_signal (bss)); g_free (bssid); return; } g_signal_handlers_disconnect_by_func (G_OBJECT (bss), on_bss_signal_notify, user_data); add_bss_proxy (wifi, g_object_ref (bss)); path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (bss)); g_hash_table_remove (wifi->priv->ignored_bss_proxies, path); } static void on_bss_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); WPABSS *bss; GError *error = NULL; char *ssid; bss = wpa_bss_proxy_new_for_bus_finish (res, &error); if (bss == NULL) { g_debug ("%s", error->message); g_error_free (error); return; } if (gclue_mozilla_should_ignore_bss (bss)) { g_object_unref (bss); return; } ssid = get_ssid_from_bss (bss); g_debug ("WiFi AP '%s' added.", ssid); g_free (ssid); if (wpa_bss_get_signal (bss) <= -90) { const char *path; char *bssid = get_bssid_from_bss (bss); g_debug ("WiFi AP '%s' has very low strength (%u dBm)" ", ignoring for now..", bssid, wpa_bss_get_signal (bss)); g_free (bssid); g_signal_connect (G_OBJECT (bss), "notify::signal", G_CALLBACK (on_bss_signal_notify), user_data); path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (bss)); g_hash_table_replace (wifi->priv->ignored_bss_proxies, g_strdup (path), bss); return; } add_bss_proxy (wifi, bss); } static void on_bss_added (WPAInterface *object, const gchar *path, GVariant *properties, gpointer user_data) { wpa_bss_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, "fi.w1.wpa_supplicant1", path, NULL, on_bss_proxy_ready, user_data); } static gboolean remove_bss_from_hashtable (const gchar *path, GHashTable *hash_table) { char *ssid; WPABSS *bss = NULL; bss = g_hash_table_lookup (hash_table, path); if (bss == NULL) return FALSE; ssid = get_ssid_from_bss (bss); g_debug ("WiFi AP '%s' removed.", ssid); g_free (ssid); g_hash_table_remove (hash_table, path); return TRUE; } static void on_bss_removed (WPAInterface *object, const gchar *path, gpointer user_data) { GClueWifiPrivate *priv = GCLUE_WIFI (user_data)->priv; if (remove_bss_from_hashtable (path, priv->bss_proxies)) priv->bss_list_changed = TRUE; remove_bss_from_hashtable (path, priv->ignored_bss_proxies); } static void cancel_wifi_scan (GClueWifi *wifi) { GClueWifiPrivate *priv = wifi->priv; if (priv->scan_timeout != 0) { g_source_remove (priv->scan_timeout); priv->scan_timeout = 0; } if (priv->scan_done_id != 0) { g_signal_handler_disconnect (priv->interface, priv->scan_done_id); priv->scan_done_id = 0; } } static gboolean on_scan_timeout (gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); GClueWifiPrivate *priv = wifi->priv; GVariantBuilder builder; GVariant *args; if (priv->interface == NULL) return FALSE; g_debug ("WiFi scan timeout. Restarting-scan.."); priv->scan_timeout = 0; if (priv->scan_done_id == 0) priv->scan_done_id = g_signal_connect (priv->interface, "scan-done", G_CALLBACK (on_scan_done), wifi); g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); g_variant_builder_add (&builder, "{sv}", "Type", g_variant_new ("s", "passive")); args = g_variant_builder_end (&builder); wpa_interface_call_scan (WPA_INTERFACE (priv->interface), args, NULL, on_scan_call_done, wifi); return FALSE; } static void on_scan_done (WPAInterface *object, gboolean success, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); GClueWifiPrivate *priv = wifi->priv; guint timeout; if (!success) { g_warning ("WiFi scan failed"); return; } g_debug ("WiFi scan completed"); if (priv->interface == NULL) return; if (priv->bss_list_changed) { priv->bss_list_changed = FALSE; g_debug ("Refreshing location.."); gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); } /* With high-enough accuracy requests, we need to scan more often since * user's location can change quickly. With low accuracy, we don't since * we wouldn't want to drain power unnecessarily. */ if (priv->accuracy_level >= GCLUE_ACCURACY_LEVEL_STREET) timeout = WIFI_SCAN_TIMEOUT_HIGH_ACCURACY; else timeout = WIFI_SCAN_TIMEOUT_LOW_ACCURACY; priv->scan_timeout = g_timeout_add_seconds (timeout, on_scan_timeout, wifi); g_debug ("Next scan scheduled in %u seconds", timeout); } static void on_scan_call_done (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); GError *error = NULL; if (!wpa_interface_call_scan_finish (WPA_INTERFACE (source_object), res, &error)) { g_warning ("Scanning of WiFi networks failed: %s", error->message); g_error_free (error); cancel_wifi_scan (wifi); return; } } static void connect_bss_signals (GClueWifi *wifi) { GClueWifiPrivate *priv = wifi->priv; const gchar *const *bss_list; guint i; if (priv->bss_added_id != 0) return; if (priv->interface == NULL) { gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); return; } on_scan_timeout (wifi); priv->bss_list_changed = TRUE; priv->bss_added_id = g_signal_connect (priv->interface, "bss-added", G_CALLBACK (on_bss_added), wifi); priv->bss_removed_id = g_signal_connect (priv->interface, "bss-removed", G_CALLBACK (on_bss_removed), wifi); bss_list = wpa_interface_get_bsss (WPA_INTERFACE (priv->interface)); if (bss_list == NULL) return; for (i = 0; bss_list[i] != NULL; i++) on_bss_added (WPA_INTERFACE (priv->interface), bss_list[i], NULL, wifi); } static void disconnect_bss_signals (GClueWifi *wifi) { GClueWifiPrivate *priv = wifi->priv; if (priv->bss_added_id == 0 || priv->interface == NULL) return; cancel_wifi_scan (wifi); g_signal_handler_disconnect (priv->interface, priv->bss_added_id); priv->bss_added_id = 0; g_signal_handler_disconnect (priv->interface, priv->bss_removed_id); priv->bss_removed_id = 0; g_hash_table_remove_all (priv->bss_proxies); g_hash_table_remove_all (priv->ignored_bss_proxies); } static gboolean gclue_wifi_start (GClueLocationSource *source) { GClueLocationSourceClass *base_class; g_return_val_if_fail (GCLUE_IS_WIFI (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_wifi_parent_class); if (!base_class->start (source)) return FALSE; connect_bss_signals (GCLUE_WIFI (source)); return TRUE; } static gboolean gclue_wifi_stop (GClueLocationSource *source) { GClueLocationSourceClass *base_class; g_return_val_if_fail (GCLUE_IS_WIFI (source), FALSE); base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_wifi_parent_class); if (!base_class->stop (source)) return FALSE; disconnect_bss_signals (GCLUE_WIFI (source)); return TRUE; } static GClueAccuracyLevel gclue_wifi_get_available_accuracy_level (GClueWebSource *source, gboolean net_available) { GClueWifiPrivate *priv = GCLUE_WIFI (source)->priv; if (!net_available) return GCLUE_ACCURACY_LEVEL_NONE; else if (priv->interface != NULL && priv->accuracy_level != GCLUE_ACCURACY_LEVEL_CITY) return GCLUE_ACCURACY_LEVEL_STREET; else return GCLUE_ACCURACY_LEVEL_CITY; } static void on_interface_proxy_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); WPAInterface *interface; GError *error = NULL; interface = wpa_interface_proxy_new_for_bus_finish (res, &error); if (interface == NULL) { g_debug ("%s", error->message); g_error_free (error); return; } if (wifi->priv->interface != NULL) { g_object_unref (interface); return; } wifi->priv->interface = interface; g_debug ("WiFi device '%s' added.", wpa_interface_get_ifname (interface)); if (gclue_location_source_get_active (GCLUE_LOCATION_SOURCE (wifi))) connect_bss_signals (wifi); else gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); } static void on_interface_added (WPASupplicant *supplicant, const gchar *path, GVariant *properties, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); if (wifi->priv->interface != NULL) return; wpa_interface_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, "fi.w1.wpa_supplicant1", path, NULL, on_interface_proxy_ready, wifi); } static void on_interface_removed (WPASupplicant *supplicant, const gchar *path, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); GClueWifiPrivate *priv = wifi->priv; const char *object_path; if (priv->interface == NULL) return; object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (priv->interface)); if (g_strcmp0 (object_path, path) != 0) return; g_debug ("WiFi device '%s' removed.", wpa_interface_get_ifname (priv->interface)); disconnect_bss_signals (wifi); g_clear_object (&wifi->priv->interface); gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi)); } static void gclue_wifi_init (GClueWifi *wifi) { wifi->priv = G_TYPE_INSTANCE_GET_PRIVATE ((wifi), GCLUE_TYPE_WIFI, GClueWifiPrivate); wifi->priv->bss_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); wifi->priv->ignored_bss_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); } static void gclue_wifi_constructed (GObject *object) { GClueWifi *wifi = GCLUE_WIFI (object); GClueWifiPrivate *priv = wifi->priv; const gchar *const *interfaces; GError *error = NULL; G_OBJECT_CLASS (gclue_wifi_parent_class)->constructed (object); if (wifi->priv->accuracy_level == GCLUE_ACCURACY_LEVEL_CITY) { GClueConfig *config = gclue_config_get_singleton (); if (!gclue_config_get_enable_wifi_source (config)) goto refresh_n_exit; } /* FIXME: We should be using async variant */ priv->supplicant = wpa_supplicant_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, "fi.w1.wpa_supplicant1", "/fi/w1/wpa_supplicant1", NULL, &error); if (priv->supplicant == NULL) { g_warning ("Failed to connect to wpa_supplicant service: %s", error->message); g_error_free (error); goto refresh_n_exit; } g_signal_connect (priv->supplicant, "interface-added", G_CALLBACK (on_interface_added), wifi); g_signal_connect (priv->supplicant, "interface-removed", G_CALLBACK (on_interface_removed), wifi); interfaces = wpa_supplicant_get_interfaces (priv->supplicant); if (interfaces != NULL && interfaces[0] != NULL) on_interface_added (priv->supplicant, interfaces[0], NULL, wifi); refresh_n_exit: gclue_web_source_refresh (GCLUE_WEB_SOURCE (object)); } static void on_wifi_destroyed (gpointer data, GObject *where_the_object_was) { GClueWifi **wifi = (GClueWifi **) data; *wifi = NULL; } /** * gclue_wifi_new: * * Get the #GClueWifi singleton, for the specified max accuracy level @level. * * Returns: (transfer full): a new ref to #GClueWifi. Use g_object_unref() * when done. **/ GClueWifi * gclue_wifi_get_singleton (GClueAccuracyLevel level) { static GClueWifi *wifi[] = { NULL, NULL }; guint i; gboolean scramble_location = FALSE; g_return_val_if_fail (level >= GCLUE_ACCURACY_LEVEL_CITY, NULL); if (level == GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD) level = GCLUE_ACCURACY_LEVEL_CITY; if (level == GCLUE_ACCURACY_LEVEL_CITY) { GClueConfig *config = gclue_config_get_singleton (); i = 0; if (gclue_config_get_enable_wifi_source (config)) scramble_location = TRUE; } else { i = 1; } if (wifi[i] == NULL) { wifi[i] = g_object_new (GCLUE_TYPE_WIFI, "accuracy-level", level, "scramble-location", scramble_location, NULL); g_object_weak_ref (G_OBJECT (wifi[i]), on_wifi_destroyed, &wifi[i]); } else g_object_ref (wifi[i]); return wifi[i]; } GClueAccuracyLevel gclue_wifi_get_accuracy_level (GClueWifi *wifi) { g_return_val_if_fail (GCLUE_IS_WIFI (wifi), GCLUE_ACCURACY_LEVEL_NONE); return wifi->priv->accuracy_level; } static GList * get_bss_list (GClueWifi *wifi, GError **error) { if (wifi->priv->interface == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No WiFi devices available"); return NULL; } return g_hash_table_get_values (wifi->priv->bss_proxies); } static SoupMessage * gclue_wifi_create_query (GClueWebSource *source, GError **error) { GList *bss_list; /* As in Access Points */ bss_list = get_bss_list (GCLUE_WIFI (source), NULL); return gclue_mozilla_create_query (bss_list, NULL, error); } static GClueLocation * gclue_wifi_parse_response (GClueWebSource *source, const char *json, GError **error) { return gclue_mozilla_parse_response (json, error); } static SoupMessage * gclue_wifi_create_submit_query (GClueWebSource *source, GClueLocation *location, GError **error) { GList *bss_list; /* As in Access Points */ bss_list = get_bss_list (GCLUE_WIFI (source), error); if (bss_list == NULL) return NULL; return gclue_mozilla_create_submit_query (location, bss_list, NULL, error); } geoclue-2.5.2/src/gclue-wifi.h000066400000000000000000000045231341441426700161500ustar00rootroot00000000000000/* vim: set et ts=8 sw=8: */ /* * Copyright 2014 Red Hat, Inc. * * Geoclue 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. * * Geoclue 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 Geoclue; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Zeeshan Ali (Khattak) */ #ifndef GCLUE_WIFI_H #define GCLUE_WIFI_H #include #include #include "gclue-web-source.h" G_BEGIN_DECLS GType gclue_wifi_get_type (void) G_GNUC_CONST; #define GCLUE_TYPE_WIFI (gclue_wifi_get_type ()) #define GCLUE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCLUE_TYPE_WIFI, GClueWifi)) #define GCLUE_IS_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCLUE_TYPE_WIFI)) #define GCLUE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCLUE_TYPE_WIFI, GClueWifiClass)) #define GCLUE_IS_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCLUE_TYPE_WIFI)) #define GCLUE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCLUE_TYPE_WIFI, GClueWifiClass)) /** * GClueWifi: * * All the fields in the #GClueWifi structure are private and should never be accessed directly. **/ typedef struct _GClueWifi GClueWifi; typedef struct _GClueWifiClass GClueWifiClass; typedef struct _GClueWifiPrivate GClueWifiPrivate; struct _GClueWifi { /* */ GClueWebSource parent_instance; GClueWifiPrivate *priv; }; /** * GClueWifiClass: * * All the fields in the #GClueWifiClass structure are private and should never be accessed directly. **/ struct _GClueWifiClass { /* */ GClueWebSourceClass parent_class; }; GClueWifi * gclue_wifi_get_singleton (GClueAccuracyLevel level); GClueAccuracyLevel gclue_wifi_get_accuracy_level (GClueWifi *wifi); G_END_DECLS #endif /* GCLUE_WIFI_H */ geoclue-2.5.2/src/geoclue.pc.in000066400000000000000000000004771341441426700163240ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ datarootdir=@datarootdir@ datadir=@datadir@ dbus_interface=${datadir}/dbus-1/interfaces/org.freedesktop.GeoClue2.xml agent_dbus_interface=${datadir}/dbus-1/interfaces/org.freedesktop.GeoClue2.Agent.xml Name: Geoclue Description: The Geoinformation Service Version: @VERSION@ geoclue-2.5.2/src/meson.build000066400000000000000000000140361341441426700161060ustar00rootroot00000000000000dbus_interface_dir = join_paths(datadir, 'dbus-1', 'interfaces') subdir('agent') geoclue_deps = base_deps + [ dependency('json-glib-1.0', version: '>= 0.14.0'), dependency('libsoup-2.4', version: '>= 2.42.0') ] dbus_gen_src = [] # Client interface client_interface_xml = 'org.freedesktop.GeoClue2.Client.xml' dbus_gen_src += gnome.gdbus_codegen( 'gclue-client-interface', client_interface_xml, interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClueDBus', docbook: 'docs') # Location interface location_interface_xml = 'org.freedesktop.GeoClue2.Location.xml' dbus_gen_src += gnome.gdbus_codegen( 'gclue-location-interface', location_interface_xml, interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClueDBus', docbook: 'docs') # Manager interface manager_interface_xml = 'org.freedesktop.GeoClue2.Manager.xml' dbus_gen_src += gnome.gdbus_codegen( 'gclue-manager-interface', manager_interface_xml, interface_prefix: 'org.freedesktop.GeoClue2.', namespace: 'GClueDBus', docbook: 'docs') sources = [ dbus_gen_src, libgeoclue_public_api_gen_sources[1] ] annotations = [[ 'fi.w1.wpa_supplicant1', 'org.gtk.GDBus.C.Name', 'WPA_Supplicant' ], [ 'fi.w1.wpa_supplicant1.Interface', 'org.gtk.GDBus.C.Name', 'WPA_Interface' ], [ 'fi.w1.wpa_supplicant1.BSS', 'org.gtk.GDBus.C.Name', 'WPA_BSS' ], [ 'fi.w1.wpa_supplicant1.BSS:SSID', 'org.gtk.GDBus.C.ForceGVariant', 'whatever' ], [ 'fi.w1.wpa_supplicant1.BSS:BSSID', 'org.gtk.GDBus.C.ForceGVariant', 'whatever' ], [ 'fi.w1.wpa_supplicant1.Interface::BSSAdded', 'org.gtk.GDBus.C.Name', 'BSS_Added' ], [ 'fi.w1.wpa_supplicant1.Interface::BSSRemoved', 'org.gtk.GDBus.C.Name', 'BSS_Removed' ]] sources += gnome.gdbus_codegen('wpa_supplicant-interface', 'fi.w1.wpa_supplicant1.xml', interface_prefix: 'fi.w1.wpa_supplicant1.', annotations: annotations) sources += gnome.gdbus_codegen('compass-interface', 'net.hadess.SensorProxy.xml', interface_prefix: 'net.hadess.SensorProxy') sources += gnome.genmarshal('gclue-marshal', prefix: 'gclue_marshal', sources: ['gclue-marshal.list']) include_dirs = [ configinc, libgeoclue_agent_inc, libgeoclue_public_api_inc, include_directories('..') ] sources += [ 'gclue-main.c', 'gclue-3g-tower.h', 'gclue-client-info.h', 'gclue-client-info.c', 'gclue-compass.h', 'gclue-compass.c', 'gclue-config.h', 'gclue-config.c', 'gclue-error.h', 'gclue-error.c', 'gclue-location-source.h', 'gclue-location-source.c', 'gclue-locator.h', 'gclue-locator.c', 'gclue-service-manager.h', 'gclue-service-manager.c', 'gclue-service-client.h', 'gclue-service-client.c', 'gclue-service-location.h', 'gclue-service-location.c', 'gclue-web-source.c', 'gclue-web-source.h', 'gclue-wifi.h', 'gclue-wifi.c', 'gclue-mozilla.h', 'gclue-mozilla.c', 'gclue-min-uint.h', 'gclue-min-uint.c', 'gclue-location.h', 'gclue-location.c' ] if get_option('3g-source') or get_option('cdma-source') or get_option('modem-gps-source') geoclue_deps += [ dependency('mm-glib', version: '>= 1.6') ] sources += [ 'gclue-modem.c', 'gclue-modem.h', 'gclue-modem-manager.c', 'gclue-modem-manager.h' ] endif if get_option('3g-source') sources += [ 'gclue-3g.c', 'gclue-3g.h' ] endif if get_option('cdma-source') sources += [ 'gclue-cdma.c', 'gclue-cdma.h' ] endif if get_option('modem-gps-source') sources += [ 'gclue-modem-gps.c', 'gclue-modem-gps.h' ] endif if get_option('nmea-source') geoclue_deps += [ dependency('avahi-client', version: '>= 0.6.10'), dependency('avahi-glib', version: '>= 0.6.10') ] sources += [ 'gclue-nmea-source.h', 'gclue-nmea-source.c' ] endif c_args = [ '-DG_LOG_DOMAIN="Geoclue"' ] link_with = [ libgeoclue_public_api, libgeoclue_agent ] executable('geoclue', sources, link_with: link_with, include_directories: include_dirs, c_args: c_args, dependencies: geoclue_deps, install: true, install_dir: libexecdir) dbus_interface = join_paths(dbus_interface_dir, 'org.freedesktop.GeoClue2.xml') agent_dbus_interface = join_paths(dbus_interface_dir, 'org.freedesktop.GeoClue2.Agent.xml') pkgconf = import('pkgconfig') pkgconf.generate(version: gclue_version, name: 'Geoclue', description: 'The Geoinformation Service', filebase: 'geoclue-' + gclue_api_version, variables: [ 'apiversion=' + gclue_api_version, 'dbus_interface=' + dbus_interface, 'agent_dbus_interface=' + agent_dbus_interface ]) interface_files = [ location_interface_xml, client_interface_xml, manager_interface_xml ] # Provide a single interface file too for backwards compatiblity. # At least gnome-settings-daemon currently relies on that. unified_interface_xml = 'org.freedesktop.GeoClue2.xml' python = find_program('python3') create_interface = find_program('create-unified-xml.py') cmd = [python, create_interface, '@OUTPUT@', '@INPUT@' ] custom_target('gclue-xml-interface', input: interface_files, output: unified_interface_xml, install: true, install_dir: dbus_interface_dir, command: cmd) install_data(interface_files, install_dir: dbus_interface_dir) geoclue-2.5.2/src/net.hadess.SensorProxy.xml000066400000000000000000000042541341441426700210350ustar00rootroot00000000000000 geoclue-2.5.2/src/org.freedesktop.GeoClue2.Client.xml000066400000000000000000000105431341441426700224070ustar00rootroot00000000000000 geoclue-2.5.2/src/org.freedesktop.GeoClue2.Location.xml000066400000000000000000000051261341441426700227420ustar00rootroot00000000000000 geoclue-2.5.2/src/org.freedesktop.GeoClue2.Manager.xml000066400000000000000000000057621341441426700225520ustar00rootroot00000000000000