From a67ac9c9232525f278349388f891ed5ce0744bd1 Mon Sep 17 00:00:00 2001 From: Georg Sieber Date: Wed, 28 Apr 2021 21:45:56 +0200 Subject: [PATCH] initial commit --- .github/FUNDING.yml | 2 + .github/screenshot.png | Bin 0 -> 43309 bytes LICENSE.txt | 674 +++++++++++++++++++++++++++++++++++++++++ README.md | 4 + laps-gui.py | 261 ++++++++++++++++ 5 files changed, 941 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/screenshot.png create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100755 laps-gui.py diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..dac875b --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +custom: ['https://www.paypal.me/schorschii'] diff --git a/.github/screenshot.png b/.github/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..89fdc432fbcb26987e32f6964eec174ef5870ac7 GIT binary patch literal 43309 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 p +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + + Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + +0. Definitions. + +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +1. Source Code. + +The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +4. Conveying Verbatim Copies. + +You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +a) The work must carry prominent notices stating that you modified +it, and giving a relevant date. + +b) The work must carry prominent notices stating that it is +released under this License and any conditions added under section +7. This requirement modifies the requirement in section 4 to +"keep intact all notices". + +c) You must license the entire work, as a whole, under this +License to anyone who comes into possession of a copy. This +License will therefore apply, along with any applicable section 7 +additional terms, to the whole of the work, and all its parts, +regardless of how they are packaged. This License gives no +permission to license the work in any other way, but it does not +invalidate such permission if you have separately received it. + +d) If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your +work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +a) Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium +customarily used for software interchange. + +b) Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a +written offer, valid for at least three years and valid for as +long as you offer spare parts or customer support for that product +model, to give anyone who possesses the object code either (1) a +copy of the Corresponding Source for all the software in the +product that is covered by this License, on a durable physical +medium customarily used for software interchange, for a price no +more than your reasonable cost of physically performing this +conveying of source, or (2) access to copy the +Corresponding Source from a network server at no charge. + +c) Convey individual copies of the object code with a copy of the +written offer to provide the Corresponding Source. This +alternative is allowed only occasionally and noncommercially, and +only if you received the object code with such an offer, in accord +with subsection 6b. + +d) Convey the object code by offering access from a designated +place (gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to +copy the object code is a network server, the Corresponding Source +may be on a different server (operated by you or a third party) +that supports equivalent copying facilities, provided you maintain +clear directions next to the object code saying where to find the +Corresponding Source. Regardless of what server hosts the +Corresponding Source, you remain obligated to ensure that it is +available for as long as needed to satisfy these requirements. + +e) Convey the object code using peer-to-peer transmission, provided +you inform other peers where the object code and Corresponding +Source of the work are being offered to the general public at no +charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the +terms of sections 15 and 16 of this License; or + +b) Requiring preservation of specified reasonable legal notices or +author attributions in that material or in the Appropriate Legal +Notices displayed by works containing it; or + +c) Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or + +d) Limiting the use for publicity purposes of names of licensors or +authors of the material; or + +e) Declining to grant rights under trademark law for use of some +trade names, trademarks, or service marks; or + +f) Requiring indemnification of licensors and authors of that +material by anyone who conveys the material (or modified versions of +it) with contractual assumptions of liability to the recipient, for +any liability that these contractual assumptions directly impose on +those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. + +If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +15. Disclaimer of Warranty. + +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. + +16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + +17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 (C) + +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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) +This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + +The GNU 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. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..363a2f4 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# LAPS4LINUX +Linux implementation of the Local Administrator Password Solution (LAPS) from Microsoft. + +![screenshot](.github/screenshot.png) diff --git a/laps-gui.py b/laps-gui.py new file mode 100755 index 0000000..7831a5e --- /dev/null +++ b/laps-gui.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from ldap3 import ALL, Server, Connection, NTLM, extend, SUBTREE, utils, MODIFY_REPLACE +from PyQt5.QtWidgets import * +from PyQt5.QtGui import * +from PyQt5.QtCore import * +from pathlib import Path +from os import path +import json +import sys + +# Microsoft Timestamp Conversion +from datetime import datetime, timedelta, tzinfo +from calendar import timegm +EPOCH_AS_FILETIME = 116444736000000000 # January 1, 1970 as MS file time +HUNDREDS_OF_NANOSECONDS = 10000000 +ZERO = timedelta(0) +HOUR = timedelta(hours=1) +class UTC(tzinfo): + def utcoffset(self, dt): + return ZERO + def tzname(self, dt): + return "UTC" + def dst(self, dt): + return ZERO +def dt_to_filetime(dt): + utc = UTC() + if(dt.tzinfo is None) or (dt.tzinfo.utcoffset(dt) is None): dt = dt.replace(tzinfo=utc) + return EPOCH_AS_FILETIME + (timegm(dt.timetuple()) * HUNDREDS_OF_NANOSECONDS) +def filetime_to_dt(ft): + return datetime.utcfromtimestamp((ft - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS) + + +class LapsMainWindow(QMainWindow): + PRODUCT_NAME = "LAPS4LINUX" + PRODUCT_VERSION = "0.1.0" + PRODUCT_WEBSITE = "https://georg-sieber.de" + + cfgPath = str(Path.home())+'/.laps-gui.json' + cfgServer = "" + cfgDomain = "" + cfgUsername = "" + cfgPassword = "" + tmpDn = "" + + def __init__(self): + super(LapsMainWindow, self).__init__() + self.LoadSettings() + self.InitUI() + + def InitUI(self): + # Menubar + mainMenu = self.menuBar() + + # File Menu + fileMenu = mainMenu.addMenu('&File') + + fileMenu.addSeparator() + quitAction = QAction('&Quit', self) + quitAction.setShortcut('Ctrl+Q') + quitAction.triggered.connect(self.OnQuit) + fileMenu.addAction(quitAction) + + # Help Menu + editMenu = mainMenu.addMenu('&Help') + + aboutAction = QAction('&About', self) + aboutAction.setShortcut('F1') + #aboutAction.triggered.connect(self.OnOpenAboutDialog) + editMenu.addAction(aboutAction) + + # Statusbar + self.statusBar = self.statusBar() + + # Window Content + grid = QGridLayout() + + self.lblSearchComputer = QLabel('Computer Name') + grid.addWidget(self.lblSearchComputer, 0, 0) + self.txtSearchComputer = QLineEdit() + self.txtSearchComputer.returnPressed.connect(self.OnReturnSearch) + grid.addWidget(self.txtSearchComputer, 1, 0) + self.btnSearchComputer = QPushButton('Search') + self.btnSearchComputer.clicked.connect(self.OnClickSearch) + grid.addWidget(self.btnSearchComputer, 1, 1) + + self.lblPassword = QLabel('Password') + grid.addWidget(self.lblPassword, 2, 0) + self.txtPassword = QLineEdit() + self.txtPassword.setReadOnly(True) + font = QFontDatabase.systemFont(QFontDatabase.FixedFont) + font.setPointSize(14) + self.txtPassword.setFont(font) + grid.addWidget(self.txtPassword, 3, 0) + + self.lblPasswordExpires = QLabel('Password Expires') + grid.addWidget(self.lblPasswordExpires, 4, 0) + self.txtPasswordExpires = QLineEdit() + self.txtPasswordExpires.setReadOnly(True) + grid.addWidget(self.txtPasswordExpires, 5, 0) + + self.lblNewExpirationTime = QLabel('New Expiration Time') + grid.addWidget(self.lblNewExpirationTime, 6, 0) + self.cwNewExpirationTime = QCalendarWidget() + grid.addWidget(self.cwNewExpirationTime, 7, 0) + self.btnSetExpirationTime = QPushButton('Set') + self.btnSetExpirationTime.setEnabled(False) + self.btnSetExpirationTime.clicked.connect(self.OnClickSetExpiry) + grid.addWidget(self.btnSetExpirationTime, 7, 1) + + widget = QWidget(self) + widget.setLayout(grid) + self.setCentralWidget(widget) + + # Window Settings + self.setMinimumSize(490, 350) + self.setWindowTitle(self.PRODUCT_NAME+" v"+self.PRODUCT_VERSION) + + # Show Note + if not 'slub' in self.cfgDomain: + self.statusBar.showMessage("If you like LAPS4LINUX please consider making a donation to support further development ("+self.PRODUCT_WEBSITE+").") + + def OnQuit(self, e): + sys.exit() + + def OnReturnSearch(self): + self.OnClickSearch(None) + + def OnClickSearch(self, e): + # check and escape input + computerName = self.txtSearchComputer.text() + if computerName.strip() == "": return + computerName = utils.conv.escape_filter_chars(computerName) + + # ask for credentials + if not self.checkCredentials(): return + + try: + # connect to server and start query + s = Server(self.cfgServer, get_info=ALL) + c = Connection(s, user=self.cfgDomain+'\\'+self.cfgUsername, password=self.cfgPassword, authentication=NTLM, auto_bind=True) + c.search(search_base=self.createLdapBase(self.cfgDomain), search_filter='(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(name='+computerName+'))',attributes=['ms-MCS-AdmPwd','ms-MCS-AdmPwdExpirationTime','SAMAccountname','distinguishedName']) + for entry in c.entries: + # display result + print('expiration time: '+str(entry['ms-Mcs-AdmPwdExpirationTime'])) + self.txtPassword.setText(str(entry['ms-Mcs-AdmPwd'])) + self.txtPasswordExpires.setText(str(entry['ms-Mcs-AdmPwdExpirationTime'])) + self.statusBar.showMessage('Found: '+str(entry['sAMAccountName'])+' ('+self.cfgServer+': '+self.cfgUsername+'@'+self.cfgDomain+')') + self.tmpDn = str(entry['distinguishedName']) + self.btnSetExpirationTime.setEnabled(True) + try: + self.txtPasswordExpires.setText( str(filetime_to_dt( int(str(entry['ms-Mcs-AdmPwdExpirationTime'])) )) ) + except Exception as e: print(str(e)) + return + + # no result found + self.txtPassword.setText('') + self.txtPasswordExpires.setText('') + self.tmpDn = '' + self.btnSetExpirationTime.setEnabled(False) + self.statusBar.showMessage('No Result For: '+computerName+' ('+self.cfgServer+': '+self.cfgUsername+'@'+self.cfgDomain+')') + except Exception as e: + # display error + self.statusBar.showMessage(str(e)) + self.cfgUsername = '' + self.cfgPassword = '' + self.tmpDn = '' + self.btnSetExpirationTime.setEnabled(False) + + def OnClickSetExpiry(self, e): + # check if dn of target computer object is known + if self.tmpDn.strip() == '': return + + # ask for credentials + if not self.checkCredentials(): return + + try: + # calc new time + newExpirationDateTime = dt_to_filetime( datetime.combine(self.cwNewExpirationTime.selectedDate().toPyDate(), datetime.min.time()) ) + print('new expiration time: '+str(newExpirationDateTime)) + + # connect to server and start query + s = Server(self.cfgServer, get_info=ALL) + c = Connection(s, user=self.cfgDomain+'\\'+self.cfgUsername, password=self.cfgPassword, authentication=NTLM, auto_bind=True) + c.modify(self.tmpDn, { 'ms-Mcs-AdmPwdExpirationTime': [(MODIFY_REPLACE, [str(newExpirationDateTime)])] }) + if c.result['result'] == 0: + self.statusBar.showMessage('Expiration Date changed successfully: '+self.tmpDn+' ('+self.cfgServer+': '+self.cfgUsername+'@'+self.cfgDomain+')') + except Exception as e: + # display error + self.statusBar.showMessage(str(e)) + + def checkCredentials(self): + if self.cfgServer == "": + item, ok = QInputDialog.getText(self, '💻 Server Address', 'Please enter your LDAP server IP address or DNS name.') + if ok and item: self.cfgServer = item + else: return False + if self.cfgDomain == "": + item, ok = QInputDialog.getText(self, '♕ Domain', 'Please enter your Domain name (e.g. example.com).') + if ok and item: self.cfgDomain = item + else: return False + if self.cfgUsername == "": + item, ok = QInputDialog.getText(self, '👤 Username', 'Please enter the username which should be used to connect to your LDAP server.') + if ok and item: self.cfgUsername = item + else: return False + if self.cfgPassword == "": + item, ok = QInputDialog.getText(self, '🔑 Password', 'Please enter the password which should be used to connect to your LDAP server.', QLineEdit.Password) + if ok and item: self.cfgPassword = item + else: return False + self.SaveSettings() + return True + + def createLdapBase(self, domain): + search_base = "" + base = domain.split(".") + for b in base: + search_base += "DC=" + b + "," + return search_base[:-1] + + def LoadSettings(self): + if(not path.isfile(self.cfgPath)): return + try: + with open(self.cfgPath) as f: + cfgJson = json.load(f) + self.cfgServer = cfgJson['server'] + self.cfgDomain = cfgJson['domain'] + self.cfgUsername = cfgJson['username'] + except Exception as e: + print(str(e)) + msg = QMessageBox() + msg.setIcon(QMessageBox.Critical) + msg.setWindowTitle('Error loading command file') + msg.setText(str(e)) + msg.setStandardButtons(QMessageBox.Ok) + retval = msg.exec_() + + def SaveSettings(self): + try: + with open(self.cfgPath, 'w') as json_file: + json.dump({ + 'server': self.cfgServer, + 'domain': self.cfgDomain, + 'username': self.cfgUsername + }, json_file, indent=4) + except Exception as e: + print(str(e)) + msg = QMessageBox() + msg.setIcon(QMessageBox.Critical) + msg.setWindowTitle('Error loading command file') + msg.setText(str(e)) + msg.setStandardButtons(QMessageBox.Ok) + retval = msg.exec_() + +def main(): + app = QApplication(sys.argv) + window = LapsMainWindow() + window.show() + sys.exit(app.exec_()) + +if __name__ == '__main__': + main()