[cosmetics] convert CRLF to LF line endings
|
|
@ -1,282 +1,282 @@
|
|||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
-------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['runner', 'version_check']
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['runner', 'version_check']
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from version_check import service # pylint: disable=import-error
|
||||
|
||||
service.run()
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from version_check import service # pylint: disable=import-error
|
||||
|
||||
service.run()
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['apt_daemon_handler', 'common', 'handler', 'json_interface', 'service',
|
||||
'shell_handler_apt', 'versions', 'viewer']
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['apt_daemon_handler', 'common', 'handler', 'json_interface', 'service',
|
||||
'shell_handler_apt', 'versions', 'viewer']
|
||||
|
|
|
|||
|
|
@ -1,120 +1,120 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from .common import log
|
||||
from .handler import Handler
|
||||
|
||||
try:
|
||||
import apt
|
||||
from aptdaemon import client
|
||||
from aptdaemon import errors
|
||||
except ImportError:
|
||||
apt = None
|
||||
client = None
|
||||
errors = None
|
||||
log('ImportError: apt, aptdaemon')
|
||||
|
||||
|
||||
class AptDaemonHandler(Handler):
|
||||
""" Apt daemon handler
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Handler.__init__(self)
|
||||
self.apt_client = client.AptClient()
|
||||
|
||||
def _check_versions(self, package):
|
||||
""" Check apt package versions
|
||||
|
||||
:param package: package to check
|
||||
:type package: str
|
||||
:return: installed version, candidate version
|
||||
:rtype: str, str / False, False
|
||||
"""
|
||||
if self.update and not self._update_cache():
|
||||
return False, False
|
||||
try:
|
||||
trans = self.apt_client.upgrade_packages([package])
|
||||
# trans = self.apt_client.upgrade_packages('bla')
|
||||
trans.simulate(reply_handler=self._apt_trans_started,
|
||||
error_handler=self._apt_error_handler)
|
||||
pkg = trans.packages[4][0]
|
||||
if pkg == package:
|
||||
cache = apt.Cache()
|
||||
cache.open(None)
|
||||
cache.upgrade()
|
||||
if cache[pkg].installed:
|
||||
return cache[pkg].installed.version, cache[pkg].candidate.version
|
||||
|
||||
return False, False
|
||||
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while checking versions: %s' % error)
|
||||
return False, False
|
||||
|
||||
def _update_cache(self):
|
||||
""" Update apt client cache
|
||||
|
||||
:return: success of updating apt cache
|
||||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
return self.apt_client.update_cache(wait=True) == 'exit-success'
|
||||
except errors.NotAuthorizedError:
|
||||
log('You are not allowed to update the cache')
|
||||
return False
|
||||
|
||||
def upgrade_package(self, package):
|
||||
""" Upgrade apt package
|
||||
|
||||
:param package: package to upgrade
|
||||
:type package: str
|
||||
:return: success of apt package upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
log('Installing new version')
|
||||
if self.apt_client.upgrade_packages([package], wait=True) == 'exit-success':
|
||||
log('Upgrade successful')
|
||||
return True
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception during upgrade: %s' % error)
|
||||
return False
|
||||
|
||||
def upgrade_system(self):
|
||||
""" Upgrade system
|
||||
|
||||
:return: success of system upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
log('Upgrading system')
|
||||
if self.apt_client.upgrade_system(wait=True) == 'exit-success':
|
||||
return True
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception during system upgrade: %s' % error)
|
||||
return False
|
||||
|
||||
def _apt_trans_started(self):
|
||||
""" Apt transfer reply handler
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _apt_error_handler(error):
|
||||
""" Apt transfer error handler
|
||||
|
||||
:param error: apt error message
|
||||
:type error: str
|
||||
"""
|
||||
log('Apt Error %s' % error)
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from .common import log
|
||||
from .handler import Handler
|
||||
|
||||
try:
|
||||
import apt
|
||||
from aptdaemon import client
|
||||
from aptdaemon import errors
|
||||
except ImportError:
|
||||
apt = None
|
||||
client = None
|
||||
errors = None
|
||||
log('ImportError: apt, aptdaemon')
|
||||
|
||||
|
||||
class AptDaemonHandler(Handler):
|
||||
""" Apt daemon handler
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Handler.__init__(self)
|
||||
self.apt_client = client.AptClient()
|
||||
|
||||
def _check_versions(self, package):
|
||||
""" Check apt package versions
|
||||
|
||||
:param package: package to check
|
||||
:type package: str
|
||||
:return: installed version, candidate version
|
||||
:rtype: str, str / False, False
|
||||
"""
|
||||
if self.update and not self._update_cache():
|
||||
return False, False
|
||||
try:
|
||||
trans = self.apt_client.upgrade_packages([package])
|
||||
# trans = self.apt_client.upgrade_packages('bla')
|
||||
trans.simulate(reply_handler=self._apt_trans_started,
|
||||
error_handler=self._apt_error_handler)
|
||||
pkg = trans.packages[4][0]
|
||||
if pkg == package:
|
||||
cache = apt.Cache()
|
||||
cache.open(None)
|
||||
cache.upgrade()
|
||||
if cache[pkg].installed:
|
||||
return cache[pkg].installed.version, cache[pkg].candidate.version
|
||||
|
||||
return False, False
|
||||
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while checking versions: %s' % error)
|
||||
return False, False
|
||||
|
||||
def _update_cache(self):
|
||||
""" Update apt client cache
|
||||
|
||||
:return: success of updating apt cache
|
||||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
return self.apt_client.update_cache(wait=True) == 'exit-success'
|
||||
except errors.NotAuthorizedError:
|
||||
log('You are not allowed to update the cache')
|
||||
return False
|
||||
|
||||
def upgrade_package(self, package):
|
||||
""" Upgrade apt package
|
||||
|
||||
:param package: package to upgrade
|
||||
:type package: str
|
||||
:return: success of apt package upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
log('Installing new version')
|
||||
if self.apt_client.upgrade_packages([package], wait=True) == 'exit-success':
|
||||
log('Upgrade successful')
|
||||
return True
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception during upgrade: %s' % error)
|
||||
return False
|
||||
|
||||
def upgrade_system(self):
|
||||
""" Upgrade system
|
||||
|
||||
:return: success of system upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
try:
|
||||
log('Upgrading system')
|
||||
if self.apt_client.upgrade_system(wait=True) == 'exit-success':
|
||||
return True
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception during system upgrade: %s' % error)
|
||||
return False
|
||||
|
||||
def _apt_trans_started(self):
|
||||
""" Apt transfer reply handler
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _apt_error_handler(error):
|
||||
""" Apt transfer error handler
|
||||
|
||||
:param error: apt error message
|
||||
:type error: str
|
||||
"""
|
||||
log('Apt Error %s' % error)
|
||||
|
|
|
|||
|
|
@ -1,288 +1,288 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcaddon # pylint: disable=import-error
|
||||
import xbmcgui # pylint: disable=import-error
|
||||
import xbmcvfs # pylint: disable=import-error
|
||||
|
||||
try:
|
||||
xbmc.translatePath = xbmcvfs.translatePath
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
ADDON = xbmcaddon.Addon('service.xbmc.versioncheck')
|
||||
ADDON_VERSION = ADDON.getAddonInfo('version')
|
||||
ADDON_NAME = ADDON.getAddonInfo('name')
|
||||
if sys.version_info[0] >= 3:
|
||||
ADDON_PATH = ADDON.getAddonInfo('path')
|
||||
ADDON_PROFILE = xbmc.translatePath(ADDON.getAddonInfo('profile'))
|
||||
else:
|
||||
ADDON_PATH = ADDON.getAddonInfo('path').decode('utf-8')
|
||||
ADDON_PROFILE = xbmc.translatePath(ADDON.getAddonInfo('profile')).decode('utf-8')
|
||||
ICON = ADDON.getAddonInfo('icon')
|
||||
KODI_VERSION_MAJOR = int(xbmc.getInfoLabel('System.BuildVersion')[0:2])
|
||||
|
||||
MONITOR = xbmc.Monitor()
|
||||
|
||||
|
||||
# Fixes unicode problems
|
||||
def string_unicode(text, encoding='utf-8'):
|
||||
""" Python 2/3 -> unicode/str
|
||||
|
||||
:param text: text to convert
|
||||
:type text: unicode (py2) / str (py3) / bytes (py3)
|
||||
:param encoding: text encoding
|
||||
:type encoding: str
|
||||
:return: converted text
|
||||
:rtype: unicode (py2) / str (py3)
|
||||
"""
|
||||
try:
|
||||
if sys.version_info[0] >= 3:
|
||||
text = str(text)
|
||||
else:
|
||||
text = unicode(text, encoding) # pylint: disable=undefined-variable
|
||||
except: # pylint: disable=bare-except
|
||||
pass
|
||||
return text
|
||||
|
||||
|
||||
def normalize_string(text):
|
||||
""" Normalize string
|
||||
|
||||
:param text: text to normalize
|
||||
:type text: unicode (py2) / str (py3) / bytes (py3)
|
||||
:return: normalized text
|
||||
:rtype: unicode (py2) / str (py3)
|
||||
"""
|
||||
try:
|
||||
text = unicodedata.normalize('NFKD', string_unicode(text)).encode('ascii', 'ignore') # pylint: disable=undefined-variable
|
||||
except: # pylint: disable=bare-except
|
||||
pass
|
||||
return text
|
||||
|
||||
|
||||
def localise(string_id):
|
||||
""" Localise string id
|
||||
|
||||
:param string_id: id of the string to localise
|
||||
:type string_id: int
|
||||
:return: localised string
|
||||
:rtype: unicode (py2) / str (py3)
|
||||
"""
|
||||
string = normalize_string(ADDON.getLocalizedString(string_id))
|
||||
return string
|
||||
|
||||
|
||||
def log(txt):
|
||||
""" Log text at xbmc.LOGDEBUG level
|
||||
|
||||
:param txt: text to log
|
||||
:type txt: str / unicode / bytes (py3)
|
||||
"""
|
||||
if sys.version_info[0] >= 3:
|
||||
if isinstance(txt, bytes):
|
||||
txt = txt.decode('utf-8')
|
||||
message = '%s: %s' % (ADDON_NAME, txt)
|
||||
else:
|
||||
if isinstance(txt, str):
|
||||
txt = txt.decode('utf-8')
|
||||
message = (u'%s: %s' % (ADDON_NAME, txt)).encode('utf-8') # pylint: disable=redundant-u-string-prefix
|
||||
xbmc.log(msg=message, level=xbmc.LOGDEBUG)
|
||||
|
||||
|
||||
def notification(heading, message, icon=None, time=15000, sound=True):
|
||||
""" Create a notification
|
||||
|
||||
:param heading: notification heading
|
||||
:type heading: str
|
||||
:param message: notification message
|
||||
:type message: str
|
||||
:param icon: path and filename for the notification icon
|
||||
:type icon: str
|
||||
:param time: time to display notification
|
||||
:type time: int
|
||||
:param sound: is notification audible
|
||||
:type sound: bool
|
||||
"""
|
||||
if not icon:
|
||||
icon = ICON
|
||||
xbmcgui.Dialog().notification(heading, message, icon, time, sound)
|
||||
|
||||
|
||||
def get_password_from_user():
|
||||
""" Prompt user to input password
|
||||
|
||||
:return: password
|
||||
:rtype: str
|
||||
"""
|
||||
pwd = ''
|
||||
keyboard = xbmc.Keyboard('', ADDON_NAME + ': ' + localise(32022), True)
|
||||
keyboard.doModal()
|
||||
if keyboard.isConfirmed():
|
||||
pwd = keyboard.getText()
|
||||
return pwd
|
||||
|
||||
|
||||
def message_upgrade_success():
|
||||
""" Upgrade success notification
|
||||
"""
|
||||
notification(ADDON_NAME, localise(32013))
|
||||
|
||||
|
||||
def message_restart():
|
||||
""" Prompt user to restart Kodi
|
||||
"""
|
||||
if dialog_yes_no(32014):
|
||||
xbmc.executebuiltin('RestartApp')
|
||||
|
||||
|
||||
def dialog_yes_no(line1=0, line2=0):
|
||||
""" Prompt user with yes/no dialog
|
||||
|
||||
:param line1: string id for the first line of the dialog
|
||||
:type line1: int
|
||||
:param line2: string id for the second line of the dialog
|
||||
:type line2: int
|
||||
:return: users selection (yes / no)
|
||||
:rtype: bool
|
||||
"""
|
||||
return xbmcgui.Dialog().yesno(ADDON_NAME, '[CR]'.join([localise(line1), localise(line2)]))
|
||||
|
||||
|
||||
def upgrade_message(msg):
|
||||
""" Prompt user with upgrade suggestion message
|
||||
|
||||
:param msg: string id for prompt message
|
||||
:type msg: int
|
||||
"""
|
||||
wait_for_end_of_video()
|
||||
|
||||
if ADDON.getSetting('lastnotified_version') < ADDON_VERSION:
|
||||
xbmcgui.Dialog().ok(
|
||||
ADDON_NAME,
|
||||
'[CR]'.join([localise(msg), localise(32001), localise(32002)])
|
||||
)
|
||||
else:
|
||||
log('Already notified one time for upgrading.')
|
||||
|
||||
|
||||
def upgrade_message2(version_installed, version_available, version_stable, old_version):
|
||||
""" Prompt user with upgrade suggestion message
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param version_available: available version
|
||||
:type version_available: dict
|
||||
:param version_stable: latest stable version
|
||||
:type version_stable: dict
|
||||
:param old_version: whether using an old version
|
||||
:type old_version: bool / 'stable'
|
||||
"""
|
||||
# shorten releasecandidate to rc
|
||||
if version_installed['tag'] == 'releasecandidate':
|
||||
version_installed['tag'] = 'rc'
|
||||
if version_available['tag'] == 'releasecandidate':
|
||||
version_available['tag'] = 'rc'
|
||||
# convert json-rpc result to strings for usage
|
||||
msg_current = '%i.%i %s%s' % (version_installed['major'],
|
||||
version_installed['minor'],
|
||||
version_installed['tag'],
|
||||
version_installed.get('tagversion', ''))
|
||||
msg_available = version_available['major'] + '.' + version_available['minor'] + ' ' + \
|
||||
version_available['tag'] + version_available.get('tagversion', '')
|
||||
msg_stable = version_stable['major'] + '.' + version_stable['minor'] + ' ' + \
|
||||
version_stable['tag'] + version_stable.get('tagversion', '')
|
||||
msg = localise(32034) % (msg_current, msg_available)
|
||||
|
||||
wait_for_end_of_video()
|
||||
|
||||
# hack: convert current version number to stable string
|
||||
# so users don't get notified again. remove in future
|
||||
if ADDON.getSetting('lastnotified_version') == '0.1.24':
|
||||
ADDON.setSetting('lastnotified_stable', msg_stable)
|
||||
|
||||
# Show different dialogs depending if there's a newer stable available.
|
||||
# Also split them between xbmc and kodi notifications to reduce possible confusion.
|
||||
# People will find out once they visit the website.
|
||||
# For stable only notify once and when there's a newer stable available.
|
||||
# Ignore any add-on updates as those only count for != stable
|
||||
if old_version == 'stable' and ADDON.getSetting('lastnotified_stable') != msg_stable:
|
||||
if xbmcaddon.Addon('xbmc.addon').getAddonInfo('version') < '13.9.0':
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32030), localise(32031)]))
|
||||
else:
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32032), localise(32033)]))
|
||||
ADDON.setSetting('lastnotified_stable', msg_stable)
|
||||
|
||||
elif old_version != 'stable' and ADDON.getSetting('lastnotified_version') != msg_available:
|
||||
if xbmcaddon.Addon('xbmc.addon').getAddonInfo('version') < '13.9.0':
|
||||
# point them to xbmc.org
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32035), localise(32031)]))
|
||||
else:
|
||||
# use kodi.tv
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32035), localise(32033)]))
|
||||
|
||||
ADDON.setSetting('lastnotified_version', msg_available)
|
||||
|
||||
else:
|
||||
log('Already notified one time for upgrading.')
|
||||
|
||||
|
||||
def abort_requested():
|
||||
""" Kodi 13+ compatible xbmc.Monitor().abortRequested()
|
||||
|
||||
:return: whether abort requested
|
||||
:rtype: bool
|
||||
"""
|
||||
if KODI_VERSION_MAJOR > 13:
|
||||
return MONITOR.abortRequested()
|
||||
|
||||
return xbmc.abortRequested
|
||||
|
||||
|
||||
def wait_for_abort(seconds):
|
||||
""" Kodi 13+ compatible xbmc.Monitor().waitForAbort()
|
||||
|
||||
:param seconds: seconds to wait for abort
|
||||
:type seconds: int / float
|
||||
:return: whether abort was requested
|
||||
:rtype: bool
|
||||
"""
|
||||
if KODI_VERSION_MAJOR > 13:
|
||||
return MONITOR.waitForAbort(seconds)
|
||||
|
||||
for _ in range(0, seconds * 1000 / 200):
|
||||
if xbmc.abortRequested:
|
||||
return True
|
||||
xbmc.sleep(200)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def wait_for_end_of_video():
|
||||
""" Wait for video playback to end
|
||||
"""
|
||||
# Don't show notify while watching a video
|
||||
while xbmc.Player().isPlayingVideo() and not abort_requested():
|
||||
if wait_for_abort(1):
|
||||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
i = 0
|
||||
while i < 10 and not abort_requested():
|
||||
if wait_for_abort(1):
|
||||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
i += 1
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcaddon # pylint: disable=import-error
|
||||
import xbmcgui # pylint: disable=import-error
|
||||
import xbmcvfs # pylint: disable=import-error
|
||||
|
||||
try:
|
||||
xbmc.translatePath = xbmcvfs.translatePath
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
ADDON = xbmcaddon.Addon('service.xbmc.versioncheck')
|
||||
ADDON_VERSION = ADDON.getAddonInfo('version')
|
||||
ADDON_NAME = ADDON.getAddonInfo('name')
|
||||
if sys.version_info[0] >= 3:
|
||||
ADDON_PATH = ADDON.getAddonInfo('path')
|
||||
ADDON_PROFILE = xbmc.translatePath(ADDON.getAddonInfo('profile'))
|
||||
else:
|
||||
ADDON_PATH = ADDON.getAddonInfo('path').decode('utf-8')
|
||||
ADDON_PROFILE = xbmc.translatePath(ADDON.getAddonInfo('profile')).decode('utf-8')
|
||||
ICON = ADDON.getAddonInfo('icon')
|
||||
KODI_VERSION_MAJOR = int(xbmc.getInfoLabel('System.BuildVersion')[0:2])
|
||||
|
||||
MONITOR = xbmc.Monitor()
|
||||
|
||||
|
||||
# Fixes unicode problems
|
||||
def string_unicode(text, encoding='utf-8'):
|
||||
""" Python 2/3 -> unicode/str
|
||||
|
||||
:param text: text to convert
|
||||
:type text: unicode (py2) / str (py3) / bytes (py3)
|
||||
:param encoding: text encoding
|
||||
:type encoding: str
|
||||
:return: converted text
|
||||
:rtype: unicode (py2) / str (py3)
|
||||
"""
|
||||
try:
|
||||
if sys.version_info[0] >= 3:
|
||||
text = str(text)
|
||||
else:
|
||||
text = unicode(text, encoding) # pylint: disable=undefined-variable
|
||||
except: # pylint: disable=bare-except
|
||||
pass
|
||||
return text
|
||||
|
||||
|
||||
def normalize_string(text):
|
||||
""" Normalize string
|
||||
|
||||
:param text: text to normalize
|
||||
:type text: unicode (py2) / str (py3) / bytes (py3)
|
||||
:return: normalized text
|
||||
:rtype: unicode (py2) / str (py3)
|
||||
"""
|
||||
try:
|
||||
text = unicodedata.normalize('NFKD', string_unicode(text)).encode('ascii', 'ignore') # pylint: disable=undefined-variable
|
||||
except: # pylint: disable=bare-except
|
||||
pass
|
||||
return text
|
||||
|
||||
|
||||
def localise(string_id):
|
||||
""" Localise string id
|
||||
|
||||
:param string_id: id of the string to localise
|
||||
:type string_id: int
|
||||
:return: localised string
|
||||
:rtype: unicode (py2) / str (py3)
|
||||
"""
|
||||
string = normalize_string(ADDON.getLocalizedString(string_id))
|
||||
return string
|
||||
|
||||
|
||||
def log(txt):
|
||||
""" Log text at xbmc.LOGDEBUG level
|
||||
|
||||
:param txt: text to log
|
||||
:type txt: str / unicode / bytes (py3)
|
||||
"""
|
||||
if sys.version_info[0] >= 3:
|
||||
if isinstance(txt, bytes):
|
||||
txt = txt.decode('utf-8')
|
||||
message = '%s: %s' % (ADDON_NAME, txt)
|
||||
else:
|
||||
if isinstance(txt, str):
|
||||
txt = txt.decode('utf-8')
|
||||
message = (u'%s: %s' % (ADDON_NAME, txt)).encode('utf-8') # pylint: disable=redundant-u-string-prefix
|
||||
xbmc.log(msg=message, level=xbmc.LOGDEBUG)
|
||||
|
||||
|
||||
def notification(heading, message, icon=None, time=15000, sound=True):
|
||||
""" Create a notification
|
||||
|
||||
:param heading: notification heading
|
||||
:type heading: str
|
||||
:param message: notification message
|
||||
:type message: str
|
||||
:param icon: path and filename for the notification icon
|
||||
:type icon: str
|
||||
:param time: time to display notification
|
||||
:type time: int
|
||||
:param sound: is notification audible
|
||||
:type sound: bool
|
||||
"""
|
||||
if not icon:
|
||||
icon = ICON
|
||||
xbmcgui.Dialog().notification(heading, message, icon, time, sound)
|
||||
|
||||
|
||||
def get_password_from_user():
|
||||
""" Prompt user to input password
|
||||
|
||||
:return: password
|
||||
:rtype: str
|
||||
"""
|
||||
pwd = ''
|
||||
keyboard = xbmc.Keyboard('', ADDON_NAME + ': ' + localise(32022), True)
|
||||
keyboard.doModal()
|
||||
if keyboard.isConfirmed():
|
||||
pwd = keyboard.getText()
|
||||
return pwd
|
||||
|
||||
|
||||
def message_upgrade_success():
|
||||
""" Upgrade success notification
|
||||
"""
|
||||
notification(ADDON_NAME, localise(32013))
|
||||
|
||||
|
||||
def message_restart():
|
||||
""" Prompt user to restart Kodi
|
||||
"""
|
||||
if dialog_yes_no(32014):
|
||||
xbmc.executebuiltin('RestartApp')
|
||||
|
||||
|
||||
def dialog_yes_no(line1=0, line2=0):
|
||||
""" Prompt user with yes/no dialog
|
||||
|
||||
:param line1: string id for the first line of the dialog
|
||||
:type line1: int
|
||||
:param line2: string id for the second line of the dialog
|
||||
:type line2: int
|
||||
:return: users selection (yes / no)
|
||||
:rtype: bool
|
||||
"""
|
||||
return xbmcgui.Dialog().yesno(ADDON_NAME, '[CR]'.join([localise(line1), localise(line2)]))
|
||||
|
||||
|
||||
def upgrade_message(msg):
|
||||
""" Prompt user with upgrade suggestion message
|
||||
|
||||
:param msg: string id for prompt message
|
||||
:type msg: int
|
||||
"""
|
||||
wait_for_end_of_video()
|
||||
|
||||
if ADDON.getSetting('lastnotified_version') < ADDON_VERSION:
|
||||
xbmcgui.Dialog().ok(
|
||||
ADDON_NAME,
|
||||
'[CR]'.join([localise(msg), localise(32001), localise(32002)])
|
||||
)
|
||||
else:
|
||||
log('Already notified one time for upgrading.')
|
||||
|
||||
|
||||
def upgrade_message2(version_installed, version_available, version_stable, old_version):
|
||||
""" Prompt user with upgrade suggestion message
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param version_available: available version
|
||||
:type version_available: dict
|
||||
:param version_stable: latest stable version
|
||||
:type version_stable: dict
|
||||
:param old_version: whether using an old version
|
||||
:type old_version: bool / 'stable'
|
||||
"""
|
||||
# shorten releasecandidate to rc
|
||||
if version_installed['tag'] == 'releasecandidate':
|
||||
version_installed['tag'] = 'rc'
|
||||
if version_available['tag'] == 'releasecandidate':
|
||||
version_available['tag'] = 'rc'
|
||||
# convert json-rpc result to strings for usage
|
||||
msg_current = '%i.%i %s%s' % (version_installed['major'],
|
||||
version_installed['minor'],
|
||||
version_installed['tag'],
|
||||
version_installed.get('tagversion', ''))
|
||||
msg_available = version_available['major'] + '.' + version_available['minor'] + ' ' + \
|
||||
version_available['tag'] + version_available.get('tagversion', '')
|
||||
msg_stable = version_stable['major'] + '.' + version_stable['minor'] + ' ' + \
|
||||
version_stable['tag'] + version_stable.get('tagversion', '')
|
||||
msg = localise(32034) % (msg_current, msg_available)
|
||||
|
||||
wait_for_end_of_video()
|
||||
|
||||
# hack: convert current version number to stable string
|
||||
# so users don't get notified again. remove in future
|
||||
if ADDON.getSetting('lastnotified_version') == '0.1.24':
|
||||
ADDON.setSetting('lastnotified_stable', msg_stable)
|
||||
|
||||
# Show different dialogs depending if there's a newer stable available.
|
||||
# Also split them between xbmc and kodi notifications to reduce possible confusion.
|
||||
# People will find out once they visit the website.
|
||||
# For stable only notify once and when there's a newer stable available.
|
||||
# Ignore any add-on updates as those only count for != stable
|
||||
if old_version == 'stable' and ADDON.getSetting('lastnotified_stable') != msg_stable:
|
||||
if xbmcaddon.Addon('xbmc.addon').getAddonInfo('version') < '13.9.0':
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32030), localise(32031)]))
|
||||
else:
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32032), localise(32033)]))
|
||||
ADDON.setSetting('lastnotified_stable', msg_stable)
|
||||
|
||||
elif old_version != 'stable' and ADDON.getSetting('lastnotified_version') != msg_available:
|
||||
if xbmcaddon.Addon('xbmc.addon').getAddonInfo('version') < '13.9.0':
|
||||
# point them to xbmc.org
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32035), localise(32031)]))
|
||||
else:
|
||||
# use kodi.tv
|
||||
xbmcgui.Dialog().ok(ADDON_NAME, '[CR]'.join([msg, localise(32035), localise(32033)]))
|
||||
|
||||
ADDON.setSetting('lastnotified_version', msg_available)
|
||||
|
||||
else:
|
||||
log('Already notified one time for upgrading.')
|
||||
|
||||
|
||||
def abort_requested():
|
||||
""" Kodi 13+ compatible xbmc.Monitor().abortRequested()
|
||||
|
||||
:return: whether abort requested
|
||||
:rtype: bool
|
||||
"""
|
||||
if KODI_VERSION_MAJOR > 13:
|
||||
return MONITOR.abortRequested()
|
||||
|
||||
return xbmc.abortRequested
|
||||
|
||||
|
||||
def wait_for_abort(seconds):
|
||||
""" Kodi 13+ compatible xbmc.Monitor().waitForAbort()
|
||||
|
||||
:param seconds: seconds to wait for abort
|
||||
:type seconds: int / float
|
||||
:return: whether abort was requested
|
||||
:rtype: bool
|
||||
"""
|
||||
if KODI_VERSION_MAJOR > 13:
|
||||
return MONITOR.waitForAbort(seconds)
|
||||
|
||||
for _ in range(0, seconds * 1000 / 200):
|
||||
if xbmc.abortRequested:
|
||||
return True
|
||||
xbmc.sleep(200)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def wait_for_end_of_video():
|
||||
""" Wait for video playback to end
|
||||
"""
|
||||
# Don't show notify while watching a video
|
||||
while xbmc.Player().isPlayingVideo() and not abort_requested():
|
||||
if wait_for_abort(1):
|
||||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
i = 0
|
||||
while i < 10 and not abort_requested():
|
||||
if wait_for_abort(1):
|
||||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
i += 1
|
||||
|
|
|
|||
|
|
@ -1,95 +1,95 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from .common import get_password_from_user
|
||||
from .common import log
|
||||
|
||||
|
||||
class Handler:
|
||||
""" Base handler class for apt_daemon_handler, and shell_handler_apt
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._pwd = ''
|
||||
self._update = True
|
||||
|
||||
@property
|
||||
def pwd(self):
|
||||
""" password property
|
||||
|
||||
:return: password
|
||||
:rtype: str
|
||||
"""
|
||||
return self._pwd
|
||||
|
||||
@pwd.setter
|
||||
def pwd(self, value):
|
||||
""" password setter
|
||||
|
||||
:param value: password
|
||||
:type value: str
|
||||
"""
|
||||
self._pwd = value
|
||||
|
||||
@property
|
||||
def update(self):
|
||||
""" update apt-cache property
|
||||
|
||||
:return: whether to update apt-cache or not when checking for upgrades
|
||||
:rtype: bool
|
||||
"""
|
||||
return self._update
|
||||
|
||||
@update.setter
|
||||
def update(self, value):
|
||||
""" update apt-cache setter
|
||||
|
||||
:param value: whether to update apt-cache or not when checking for upgrades
|
||||
:type value: bool
|
||||
"""
|
||||
self._update = value
|
||||
|
||||
def _check_versions(self, package):
|
||||
raise NotImplementedError
|
||||
|
||||
def check_upgrade_available(self, package):
|
||||
""" Check if package upgrade is available
|
||||
|
||||
:param package: package to check for upgrade availability
|
||||
:type package: str
|
||||
:return: whether an upgrade exists for the provided package
|
||||
:rtype: bool
|
||||
"""
|
||||
installed, candidate = self._check_versions(package)
|
||||
if installed and candidate:
|
||||
if installed != candidate:
|
||||
log('Version installed %s' % installed)
|
||||
log('Version available %s' % candidate)
|
||||
return True
|
||||
log('Already on newest version')
|
||||
return False
|
||||
|
||||
if not installed:
|
||||
log('No installed package found')
|
||||
|
||||
return False
|
||||
|
||||
def _get_password(self):
|
||||
""" Get password, ask user for password if not known
|
||||
|
||||
:return: password
|
||||
:rtype: str
|
||||
"""
|
||||
if not self.pwd:
|
||||
self.pwd = get_password_from_user()
|
||||
return self.pwd
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from .common import get_password_from_user
|
||||
from .common import log
|
||||
|
||||
|
||||
class Handler:
|
||||
""" Base handler class for apt_daemon_handler, and shell_handler_apt
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._pwd = ''
|
||||
self._update = True
|
||||
|
||||
@property
|
||||
def pwd(self):
|
||||
""" password property
|
||||
|
||||
:return: password
|
||||
:rtype: str
|
||||
"""
|
||||
return self._pwd
|
||||
|
||||
@pwd.setter
|
||||
def pwd(self, value):
|
||||
""" password setter
|
||||
|
||||
:param value: password
|
||||
:type value: str
|
||||
"""
|
||||
self._pwd = value
|
||||
|
||||
@property
|
||||
def update(self):
|
||||
""" update apt-cache property
|
||||
|
||||
:return: whether to update apt-cache or not when checking for upgrades
|
||||
:rtype: bool
|
||||
"""
|
||||
return self._update
|
||||
|
||||
@update.setter
|
||||
def update(self, value):
|
||||
""" update apt-cache setter
|
||||
|
||||
:param value: whether to update apt-cache or not when checking for upgrades
|
||||
:type value: bool
|
||||
"""
|
||||
self._update = value
|
||||
|
||||
def _check_versions(self, package):
|
||||
raise NotImplementedError
|
||||
|
||||
def check_upgrade_available(self, package):
|
||||
""" Check if package upgrade is available
|
||||
|
||||
:param package: package to check for upgrade availability
|
||||
:type package: str
|
||||
:return: whether an upgrade exists for the provided package
|
||||
:rtype: bool
|
||||
"""
|
||||
installed, candidate = self._check_versions(package)
|
||||
if installed and candidate:
|
||||
if installed != candidate:
|
||||
log('Version installed %s' % installed)
|
||||
log('Version available %s' % candidate)
|
||||
return True
|
||||
log('Already on newest version')
|
||||
return False
|
||||
|
||||
if not installed:
|
||||
log('No installed package found')
|
||||
|
||||
return False
|
||||
|
||||
def _get_password(self):
|
||||
""" Get password, ask user for password if not known
|
||||
|
||||
:return: password
|
||||
:rtype: str
|
||||
"""
|
||||
if not self.pwd:
|
||||
self.pwd = get_password_from_user()
|
||||
return self.pwd
|
||||
|
|
|
|||
|
|
@ -1,67 +1,67 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from contextlib import closing
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcvfs # pylint: disable=import-error
|
||||
|
||||
from .common import ADDON_PATH
|
||||
|
||||
|
||||
def get_installed_version():
|
||||
""" Retrieve the currently installed version
|
||||
|
||||
:return: currently installed version
|
||||
:rtype: dict
|
||||
"""
|
||||
query = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "Application.GetProperties",
|
||||
"params": {
|
||||
"properties": ["version", "name"]
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
json_query = xbmc.executeJSONRPC(json.dumps(query))
|
||||
if sys.version_info[0] >= 3:
|
||||
json_query = str(json_query)
|
||||
else:
|
||||
json_query = unicode(json_query, 'utf-8', errors='ignore') # pylint: disable=undefined-variable
|
||||
json_query = json.loads(json_query)
|
||||
version_installed = []
|
||||
if 'result' in json_query and 'version' in json_query['result']:
|
||||
version_installed = json_query['result']['version']
|
||||
return version_installed
|
||||
|
||||
|
||||
def get_version_file_list():
|
||||
""" Retrieve version lists from supplied version file (resources/versions.txt)
|
||||
|
||||
:return: all provided versions
|
||||
:rtype: dict
|
||||
"""
|
||||
version_file = os.path.join(ADDON_PATH, 'resources/versions.txt')
|
||||
with closing(xbmcvfs.File(version_file)) as open_file:
|
||||
data = open_file.read()
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
version_query = str(data)
|
||||
else:
|
||||
version_query = unicode(data, 'utf-8', errors='ignore') # pylint: disable=undefined-variable
|
||||
version_query = json.loads(version_query)
|
||||
return version_query
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from contextlib import closing
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcvfs # pylint: disable=import-error
|
||||
|
||||
from .common import ADDON_PATH
|
||||
|
||||
|
||||
def get_installed_version():
|
||||
""" Retrieve the currently installed version
|
||||
|
||||
:return: currently installed version
|
||||
:rtype: dict
|
||||
"""
|
||||
query = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "Application.GetProperties",
|
||||
"params": {
|
||||
"properties": ["version", "name"]
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
json_query = xbmc.executeJSONRPC(json.dumps(query))
|
||||
if sys.version_info[0] >= 3:
|
||||
json_query = str(json_query)
|
||||
else:
|
||||
json_query = unicode(json_query, 'utf-8', errors='ignore') # pylint: disable=undefined-variable
|
||||
json_query = json.loads(json_query)
|
||||
version_installed = []
|
||||
if 'result' in json_query and 'version' in json_query['result']:
|
||||
version_installed = json_query['result']['version']
|
||||
return version_installed
|
||||
|
||||
|
||||
def get_version_file_list():
|
||||
""" Retrieve version lists from supplied version file (resources/versions.txt)
|
||||
|
||||
:return: all provided versions
|
||||
:rtype: dict
|
||||
"""
|
||||
version_file = os.path.join(ADDON_PATH, 'resources/versions.txt')
|
||||
with closing(xbmcvfs.File(version_file)) as open_file:
|
||||
data = open_file.read()
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
version_query = str(data)
|
||||
else:
|
||||
version_query = unicode(data, 'utf-8', errors='ignore') # pylint: disable=undefined-variable
|
||||
version_query = json.loads(version_query)
|
||||
return version_query
|
||||
|
|
|
|||
|
|
@ -1,165 +1,165 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
import platform
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcgui # pylint: disable=import-error
|
||||
|
||||
from .common import ADDON
|
||||
from .common import ADDON_NAME
|
||||
from .common import ADDON_VERSION
|
||||
from .common import dialog_yes_no
|
||||
from .common import localise
|
||||
from .common import log
|
||||
from .common import wait_for_abort
|
||||
from .common import message_restart
|
||||
from .common import message_upgrade_success
|
||||
from .common import upgrade_message
|
||||
from .common import upgrade_message2
|
||||
from .json_interface import get_version_file_list
|
||||
from .json_interface import get_installed_version
|
||||
from .versions import compare_version
|
||||
|
||||
|
||||
DISTRIBUTION = ''
|
||||
|
||||
if sys.platform.startswith('linux'):
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] >= 8:
|
||||
try:
|
||||
from .distro import distro
|
||||
|
||||
DISTRIBUTION = distro.linux_distribution(full_distribution_name=False)[0].lower()
|
||||
|
||||
except (AttributeError, ImportError):
|
||||
DISTRIBUTION = ''
|
||||
|
||||
else:
|
||||
DISTRIBUTION = platform.linux_distribution(full_distribution_name=0)[0].lower() # pylint: disable=no-member
|
||||
|
||||
if not DISTRIBUTION:
|
||||
DISTRIBUTION = platform.uname()[0].lower()
|
||||
|
||||
|
||||
def _version_check():
|
||||
""" Check versions (non-linux)
|
||||
|
||||
:return: old, current, available, and stable versions
|
||||
:rtype: bool / 'stable', dict, dict, dict
|
||||
"""
|
||||
# retrieve version_lists from supplied version file
|
||||
version_list = get_version_file_list()
|
||||
# retrieve version installed
|
||||
version_installed = get_installed_version()
|
||||
# compare installed and available
|
||||
old_version, version_installed, version_available, version_stable = \
|
||||
compare_version(version_installed, version_list)
|
||||
return old_version, version_installed, version_available, version_stable
|
||||
|
||||
|
||||
def _version_check_linux(packages):
|
||||
""" Check package version on linux
|
||||
|
||||
:param packages: list of packages to check
|
||||
:type packages: list of str
|
||||
"""
|
||||
if DISTRIBUTION in ['ubuntu', 'debian', 'linuxmint']:
|
||||
try:
|
||||
# try aptdaemon first
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from .apt_daemon_handler import AptDaemonHandler
|
||||
handler = AptDaemonHandler()
|
||||
except: # pylint: disable=bare-except
|
||||
# fallback to shell
|
||||
# since we need the user password, ask to check for new version first
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from .shell_handler_apt import ShellHandlerApt
|
||||
handler = ShellHandlerApt(use_sudo=True)
|
||||
if dialog_yes_no(32015):
|
||||
pass
|
||||
elif dialog_yes_no(32009, 32010):
|
||||
log('disabling addon by user request')
|
||||
ADDON.setSetting('versioncheck_enable', 'false')
|
||||
return
|
||||
|
||||
if handler:
|
||||
if handler.check_upgrade_available(packages[0]):
|
||||
if upgrade_message(32012):
|
||||
if ADDON.getSetting('upgrade_system') == 'false':
|
||||
result = handler.upgrade_package(packages[0])
|
||||
else:
|
||||
result = handler.upgrade_system()
|
||||
if result:
|
||||
message_upgrade_success()
|
||||
message_restart()
|
||||
else:
|
||||
log('Error during upgrade')
|
||||
return
|
||||
|
||||
log('No upgrade available')
|
||||
return
|
||||
|
||||
log('Error: no handler found')
|
||||
return
|
||||
|
||||
log('Unsupported platform %s' % DISTRIBUTION)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def _check_cryptography():
|
||||
""" Check for cryptography package, and version
|
||||
|
||||
Python cryptography < 1.7 (still shipped with Ubuntu 16.04) has issues with
|
||||
pyOpenSSL integration, leading to all sorts of weird bugs - check here to save
|
||||
on some troubleshooting. This check may be removed in the future (when switching
|
||||
to Python3?)
|
||||
See https://github.com/pyca/pyopenssl/issues/542
|
||||
"""
|
||||
try:
|
||||
import cryptography # pylint: disable=import-outside-toplevel
|
||||
ver = cryptography.__version__
|
||||
except ImportError:
|
||||
# If the module is not found - no problem
|
||||
return
|
||||
|
||||
ver_parts = list(map(int, ver.split('.')))
|
||||
if len(ver_parts) < 2 or ver_parts[0] < 1 or (ver_parts[0] == 1 and ver_parts[1] < 7):
|
||||
log('Python cryptography module version %s is too old, at least version 1.7 needed' % ver)
|
||||
xbmcgui.Dialog().ok(
|
||||
ADDON_NAME,
|
||||
'[CR]'.join([localise(32040) % ver, localise(32041), localise(32042)])
|
||||
)
|
||||
|
||||
|
||||
def run():
|
||||
""" Service entry-point
|
||||
"""
|
||||
_check_cryptography()
|
||||
|
||||
if ADDON.getSetting('versioncheck_enable') == 'false':
|
||||
log('Disabled')
|
||||
else:
|
||||
log('Version %s started' % ADDON_VERSION)
|
||||
|
||||
if wait_for_abort(5):
|
||||
sys.exit(0)
|
||||
|
||||
if (xbmc.getCondVisibility('System.Platform.Linux') and
|
||||
ADDON.getSetting('upgrade_apt') == 'true'):
|
||||
_version_check_linux(['kodi'])
|
||||
else:
|
||||
old_version, version_installed, version_available, version_stable = _version_check()
|
||||
if old_version:
|
||||
upgrade_message2(version_installed, version_available, version_stable, old_version)
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
import platform
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcgui # pylint: disable=import-error
|
||||
|
||||
from .common import ADDON
|
||||
from .common import ADDON_NAME
|
||||
from .common import ADDON_VERSION
|
||||
from .common import dialog_yes_no
|
||||
from .common import localise
|
||||
from .common import log
|
||||
from .common import wait_for_abort
|
||||
from .common import message_restart
|
||||
from .common import message_upgrade_success
|
||||
from .common import upgrade_message
|
||||
from .common import upgrade_message2
|
||||
from .json_interface import get_version_file_list
|
||||
from .json_interface import get_installed_version
|
||||
from .versions import compare_version
|
||||
|
||||
|
||||
DISTRIBUTION = ''
|
||||
|
||||
if sys.platform.startswith('linux'):
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] >= 8:
|
||||
try:
|
||||
from .distro import distro
|
||||
|
||||
DISTRIBUTION = distro.linux_distribution(full_distribution_name=False)[0].lower()
|
||||
|
||||
except (AttributeError, ImportError):
|
||||
DISTRIBUTION = ''
|
||||
|
||||
else:
|
||||
DISTRIBUTION = platform.linux_distribution(full_distribution_name=0)[0].lower() # pylint: disable=no-member
|
||||
|
||||
if not DISTRIBUTION:
|
||||
DISTRIBUTION = platform.uname()[0].lower()
|
||||
|
||||
|
||||
def _version_check():
|
||||
""" Check versions (non-linux)
|
||||
|
||||
:return: old, current, available, and stable versions
|
||||
:rtype: bool / 'stable', dict, dict, dict
|
||||
"""
|
||||
# retrieve version_lists from supplied version file
|
||||
version_list = get_version_file_list()
|
||||
# retrieve version installed
|
||||
version_installed = get_installed_version()
|
||||
# compare installed and available
|
||||
old_version, version_installed, version_available, version_stable = \
|
||||
compare_version(version_installed, version_list)
|
||||
return old_version, version_installed, version_available, version_stable
|
||||
|
||||
|
||||
def _version_check_linux(packages):
|
||||
""" Check package version on linux
|
||||
|
||||
:param packages: list of packages to check
|
||||
:type packages: list of str
|
||||
"""
|
||||
if DISTRIBUTION in ['ubuntu', 'debian', 'linuxmint']:
|
||||
try:
|
||||
# try aptdaemon first
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from .apt_daemon_handler import AptDaemonHandler
|
||||
handler = AptDaemonHandler()
|
||||
except: # pylint: disable=bare-except
|
||||
# fallback to shell
|
||||
# since we need the user password, ask to check for new version first
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from .shell_handler_apt import ShellHandlerApt
|
||||
handler = ShellHandlerApt(use_sudo=True)
|
||||
if dialog_yes_no(32015):
|
||||
pass
|
||||
elif dialog_yes_no(32009, 32010):
|
||||
log('disabling addon by user request')
|
||||
ADDON.setSetting('versioncheck_enable', 'false')
|
||||
return
|
||||
|
||||
if handler:
|
||||
if handler.check_upgrade_available(packages[0]):
|
||||
if upgrade_message(32012):
|
||||
if ADDON.getSetting('upgrade_system') == 'false':
|
||||
result = handler.upgrade_package(packages[0])
|
||||
else:
|
||||
result = handler.upgrade_system()
|
||||
if result:
|
||||
message_upgrade_success()
|
||||
message_restart()
|
||||
else:
|
||||
log('Error during upgrade')
|
||||
return
|
||||
|
||||
log('No upgrade available')
|
||||
return
|
||||
|
||||
log('Error: no handler found')
|
||||
return
|
||||
|
||||
log('Unsupported platform %s' % DISTRIBUTION)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def _check_cryptography():
|
||||
""" Check for cryptography package, and version
|
||||
|
||||
Python cryptography < 1.7 (still shipped with Ubuntu 16.04) has issues with
|
||||
pyOpenSSL integration, leading to all sorts of weird bugs - check here to save
|
||||
on some troubleshooting. This check may be removed in the future (when switching
|
||||
to Python3?)
|
||||
See https://github.com/pyca/pyopenssl/issues/542
|
||||
"""
|
||||
try:
|
||||
import cryptography # pylint: disable=import-outside-toplevel
|
||||
ver = cryptography.__version__
|
||||
except ImportError:
|
||||
# If the module is not found - no problem
|
||||
return
|
||||
|
||||
ver_parts = list(map(int, ver.split('.')))
|
||||
if len(ver_parts) < 2 or ver_parts[0] < 1 or (ver_parts[0] == 1 and ver_parts[1] < 7):
|
||||
log('Python cryptography module version %s is too old, at least version 1.7 needed' % ver)
|
||||
xbmcgui.Dialog().ok(
|
||||
ADDON_NAME,
|
||||
'[CR]'.join([localise(32040) % ver, localise(32041), localise(32042)])
|
||||
)
|
||||
|
||||
|
||||
def run():
|
||||
""" Service entry-point
|
||||
"""
|
||||
_check_cryptography()
|
||||
|
||||
if ADDON.getSetting('versioncheck_enable') == 'false':
|
||||
log('Disabled')
|
||||
else:
|
||||
log('Version %s started' % ADDON_VERSION)
|
||||
|
||||
if wait_for_abort(5):
|
||||
sys.exit(0)
|
||||
|
||||
if (xbmc.getCondVisibility('System.Platform.Linux') and
|
||||
ADDON.getSetting('upgrade_apt') == 'true'):
|
||||
_version_check_linux(['kodi'])
|
||||
else:
|
||||
old_version, version_installed, version_available, version_stable = _version_check()
|
||||
if old_version:
|
||||
upgrade_message2(version_installed, version_available, version_stable, old_version)
|
||||
|
|
|
|||
|
|
@ -1,132 +1,132 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from .common import log
|
||||
from .handler import Handler
|
||||
|
||||
try:
|
||||
from subprocess import check_output
|
||||
except ImportError:
|
||||
check_output = None
|
||||
log('ImportError: subprocess')
|
||||
|
||||
|
||||
class ShellHandlerApt(Handler):
|
||||
""" Apt shell handler
|
||||
"""
|
||||
|
||||
def __init__(self, use_sudo=False):
|
||||
Handler.__init__(self)
|
||||
self.sudo = use_sudo
|
||||
self._update = False
|
||||
installed, _ = self._check_versions('kodi')
|
||||
if not installed:
|
||||
# there is no package installed via repo, so we exit here
|
||||
log('No installed package found, exiting')
|
||||
sys.exit(0)
|
||||
self._update = True
|
||||
|
||||
def _check_versions(self, package):
|
||||
""" Check apt package versions
|
||||
|
||||
:param package: package to check
|
||||
:type package: str
|
||||
:return: installed version, candidate version
|
||||
:rtype: str, str / False, False
|
||||
"""
|
||||
_cmd = 'apt-cache policy ' + package
|
||||
|
||||
if self.update and not self._update_cache():
|
||||
return False, False
|
||||
|
||||
try:
|
||||
result = check_output([_cmd], shell=True).split('\n')
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('ShellHandlerApt: exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False, False
|
||||
|
||||
if result[0].replace(':', '') == package:
|
||||
installed = result[1].split()[1]
|
||||
candidate = result[2].split()[1]
|
||||
if installed == '(none)':
|
||||
installed = False
|
||||
if candidate == '(none)':
|
||||
candidate = False
|
||||
return installed, candidate
|
||||
|
||||
log('ShellHandlerApt: error during version check')
|
||||
return False, False
|
||||
|
||||
def _update_cache(self):
|
||||
""" Update apt cache
|
||||
|
||||
:return: success of updating apt cache
|
||||
:rtype: bool
|
||||
"""
|
||||
_cmd = 'apt-get update'
|
||||
try:
|
||||
if self.sudo:
|
||||
_ = check_output('echo \'%s\' | sudo -S %s' %
|
||||
(self._get_password(), _cmd), shell=True)
|
||||
else:
|
||||
_ = check_output(_cmd.split())
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def upgrade_package(self, package):
|
||||
""" Upgrade apt package
|
||||
|
||||
:param package: package to upgrade
|
||||
:type package: str
|
||||
:return: success of apt package upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
_cmd = 'apt-get install -y ' + package
|
||||
try:
|
||||
if self.sudo:
|
||||
_ = check_output('echo \'%s\' | sudo -S %s' %
|
||||
(self._get_password(), _cmd), shell=True)
|
||||
else:
|
||||
_ = check_output(_cmd.split())
|
||||
log('Upgrade successful')
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def upgrade_system(self):
|
||||
""" Upgrade system
|
||||
|
||||
:return: success of system upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
_cmd = 'apt-get upgrade -y'
|
||||
try:
|
||||
log('Upgrading system')
|
||||
if self.sudo:
|
||||
_ = check_output('echo \'%s\' | sudo -S %s' %
|
||||
(self._get_password(), _cmd), shell=True)
|
||||
else:
|
||||
_ = check_output(_cmd.split())
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False
|
||||
|
||||
return True
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from .common import log
|
||||
from .handler import Handler
|
||||
|
||||
try:
|
||||
from subprocess import check_output
|
||||
except ImportError:
|
||||
check_output = None
|
||||
log('ImportError: subprocess')
|
||||
|
||||
|
||||
class ShellHandlerApt(Handler):
|
||||
""" Apt shell handler
|
||||
"""
|
||||
|
||||
def __init__(self, use_sudo=False):
|
||||
Handler.__init__(self)
|
||||
self.sudo = use_sudo
|
||||
self._update = False
|
||||
installed, _ = self._check_versions('kodi')
|
||||
if not installed:
|
||||
# there is no package installed via repo, so we exit here
|
||||
log('No installed package found, exiting')
|
||||
sys.exit(0)
|
||||
self._update = True
|
||||
|
||||
def _check_versions(self, package):
|
||||
""" Check apt package versions
|
||||
|
||||
:param package: package to check
|
||||
:type package: str
|
||||
:return: installed version, candidate version
|
||||
:rtype: str, str / False, False
|
||||
"""
|
||||
_cmd = 'apt-cache policy ' + package
|
||||
|
||||
if self.update and not self._update_cache():
|
||||
return False, False
|
||||
|
||||
try:
|
||||
result = check_output([_cmd], shell=True).split('\n')
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('ShellHandlerApt: exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False, False
|
||||
|
||||
if result[0].replace(':', '') == package:
|
||||
installed = result[1].split()[1]
|
||||
candidate = result[2].split()[1]
|
||||
if installed == '(none)':
|
||||
installed = False
|
||||
if candidate == '(none)':
|
||||
candidate = False
|
||||
return installed, candidate
|
||||
|
||||
log('ShellHandlerApt: error during version check')
|
||||
return False, False
|
||||
|
||||
def _update_cache(self):
|
||||
""" Update apt cache
|
||||
|
||||
:return: success of updating apt cache
|
||||
:rtype: bool
|
||||
"""
|
||||
_cmd = 'apt-get update'
|
||||
try:
|
||||
if self.sudo:
|
||||
_ = check_output('echo \'%s\' | sudo -S %s' %
|
||||
(self._get_password(), _cmd), shell=True)
|
||||
else:
|
||||
_ = check_output(_cmd.split())
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def upgrade_package(self, package):
|
||||
""" Upgrade apt package
|
||||
|
||||
:param package: package to upgrade
|
||||
:type package: str
|
||||
:return: success of apt package upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
_cmd = 'apt-get install -y ' + package
|
||||
try:
|
||||
if self.sudo:
|
||||
_ = check_output('echo \'%s\' | sudo -S %s' %
|
||||
(self._get_password(), _cmd), shell=True)
|
||||
else:
|
||||
_ = check_output(_cmd.split())
|
||||
log('Upgrade successful')
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def upgrade_system(self):
|
||||
""" Upgrade system
|
||||
|
||||
:return: success of system upgrade
|
||||
:rtype: bool
|
||||
"""
|
||||
_cmd = 'apt-get upgrade -y'
|
||||
try:
|
||||
log('Upgrading system')
|
||||
if self.sudo:
|
||||
_ = check_output('echo \'%s\' | sudo -S %s' %
|
||||
(self._get_password(), _cmd), shell=True)
|
||||
else:
|
||||
_ = check_output(_cmd.split())
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
log('Exception while executing shell command %s: %s' % (_cmd, error))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,216 +1,216 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from .common import log
|
||||
|
||||
|
||||
def compare_version(version_installed, version_list):
|
||||
""" Compare the installed version against the provided version list
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param version_list: provided versions to compare against
|
||||
:type version_list: dict
|
||||
:return: old, current, available, and stable versions
|
||||
:rtype: bool / 'stable', dict, dict, dict
|
||||
"""
|
||||
# Create separate version lists
|
||||
version_list_stable = version_list['releases']['stable']
|
||||
version_list_rc = version_list['releases']['releasecandidate']
|
||||
version_list_beta = version_list['releases']['beta']
|
||||
version_list_alpha = version_list['releases']['alpha']
|
||||
# version_list_prealpha = version_list['releases']['prealpha']
|
||||
|
||||
stable_version = version_list_stable[0]
|
||||
rc_version = version_list_rc[0]
|
||||
beta_version = version_list_beta[0]
|
||||
alpha_version = version_list_alpha[0]
|
||||
|
||||
log('Version installed %s' % version_installed)
|
||||
|
||||
# Check to upgrade to newest available stable version
|
||||
# check on smaller major version. Smaller version than available always notify
|
||||
|
||||
# check for stable versions
|
||||
old_version, version_available = _check_for_stable_version(version_installed, stable_version)
|
||||
|
||||
if not old_version:
|
||||
# Already skipped a possible newer stable build. Let's continue with non stable builds.
|
||||
# Check also 'old version' hasn't been set to 'stable' or true by previous checks because
|
||||
# if so, those part need to be skipped
|
||||
old_version, version_available = _check_for_rc_version(version_installed,
|
||||
rc_version, beta_version)
|
||||
|
||||
if not old_version:
|
||||
# check for beta builds
|
||||
old_version, version_available = _check_for_beta_version(version_installed, beta_version)
|
||||
|
||||
if not old_version:
|
||||
# check for alpha builds
|
||||
old_version, version_available = _check_for_alpha_version(version_installed, alpha_version)
|
||||
|
||||
return old_version, version_installed, version_available, stable_version
|
||||
|
||||
|
||||
def _check_for_stable_version(version_installed, stable_version):
|
||||
""" Compare the installed version against the latest stable version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param stable_version: latest stable version
|
||||
:type stable_version: dict
|
||||
:return: whether using an old version, and available version if newer stable version available
|
||||
:rtype: bool / 'stable', dict
|
||||
"""
|
||||
# check if installed major version is smaller than available major stable
|
||||
# here we don't care if running non stable
|
||||
old_version = False
|
||||
version_available = {}
|
||||
|
||||
if version_installed['major'] < int(stable_version['major']):
|
||||
version_available = stable_version
|
||||
old_version = 'stable'
|
||||
log('Version available %s' % stable_version)
|
||||
log('You are running an older version')
|
||||
|
||||
# check if installed major version is equal than available major stable
|
||||
# however also check on minor version and still don't care about non stable
|
||||
elif version_installed['major'] == int(stable_version['major']):
|
||||
if version_installed['minor'] < int(stable_version['minor']):
|
||||
version_available = stable_version
|
||||
old_version = 'stable'
|
||||
log('Version available %s' % stable_version)
|
||||
log('You are running an older minor version')
|
||||
# check for <= minor !stable
|
||||
elif version_installed['tag'] != 'stable' and \
|
||||
version_installed['minor'] <= int(stable_version['minor']):
|
||||
version_available = stable_version
|
||||
old_version = True
|
||||
log('Version available %s' % stable_version)
|
||||
log('You are running an older non stable minor version')
|
||||
else:
|
||||
log('Version available %s' % stable_version)
|
||||
log('There is no newer stable available')
|
||||
|
||||
return old_version, version_available
|
||||
|
||||
|
||||
def _check_for_rc_version(version_installed, rc_version, beta_version):
|
||||
""" Compare the installed version against the latest RC version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param rc_version: latest rc version
|
||||
:type rc_version: dict
|
||||
:param beta_version: latest beta version
|
||||
:type beta_version: dict
|
||||
:return: whether using an old version, and available version if newer rc version available
|
||||
:rtype: bool, dict
|
||||
"""
|
||||
old_version = False
|
||||
version_available = {}
|
||||
# check for RC builds
|
||||
if version_installed['tag'] in ['releasecandidate']:
|
||||
# check if you are using a RC build lower than current available RC
|
||||
# then check if you are using a beta/alpha lower than current available RC
|
||||
# 14.0rc3 is newer than: 14.0rc1, 14.0b9, 14.0a15
|
||||
if version_installed['major'] <= int(rc_version['major']):
|
||||
if version_installed['minor'] <= int(rc_version['minor']):
|
||||
if version_installed.get('tagversion', '') < rc_version['tagversion']:
|
||||
version_available = rc_version
|
||||
old_version = True
|
||||
log('Version available %s' % rc_version)
|
||||
log('You are running an older RC version')
|
||||
# now check if installed !=rc
|
||||
elif version_installed['tag'] in ['beta', 'alpha', 'prealpha']:
|
||||
if version_installed['major'] <= int(rc_version['major']):
|
||||
if version_installed['minor'] <= int(beta_version['minor']):
|
||||
version_available = rc_version
|
||||
old_version = True
|
||||
log('Version available %s' % rc_version)
|
||||
log('You are running an older non RC version')
|
||||
|
||||
return old_version, version_available
|
||||
|
||||
|
||||
def _check_for_beta_version(version_installed, beta_version):
|
||||
""" Compare the installed version against the latest beta version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param beta_version: latest beta version
|
||||
:type beta_version: dict
|
||||
:return: whether using an old version, and available version if newer beta version available
|
||||
:rtype: bool, dict
|
||||
"""
|
||||
old_version = False
|
||||
version_available = {}
|
||||
# check for beta builds
|
||||
if not old_version and version_installed['tag'] == 'beta':
|
||||
# check if you are using a RC build lower than current available RC
|
||||
# then check if you are using a beta/alpha lower than current available RC
|
||||
# 14.0b3 is newer than: 14.0b1, 14.0a15
|
||||
if version_installed['major'] <= int(beta_version['major']):
|
||||
if version_installed['minor'] <= int(beta_version['minor']):
|
||||
if version_installed.get('tagversion', '') < beta_version['tagversion']:
|
||||
version_available = beta_version
|
||||
old_version = True
|
||||
log('Version available %s' % beta_version)
|
||||
log('You are running an older beta version')
|
||||
# now check if installed !=beta
|
||||
elif not old_version and version_installed['tag'] in ['alpha', 'prealpha']:
|
||||
if version_installed['major'] <= int(beta_version['major']):
|
||||
if version_installed['minor'] <= int(beta_version['minor']):
|
||||
version_available = beta_version
|
||||
old_version = True
|
||||
log('Version available %s' % beta_version)
|
||||
log('You are running an older non beta version')
|
||||
|
||||
return old_version, version_available
|
||||
|
||||
|
||||
def _check_for_alpha_version(version_installed, alpha_version):
|
||||
""" Compare the installed version against the latest alpha version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param alpha_version: latest alpha version
|
||||
:type alpha_version: dict
|
||||
:return: whether using an old version, and available version if newer alpha version available
|
||||
:rtype: bool, dict
|
||||
"""
|
||||
old_version = False
|
||||
version_available = {}
|
||||
# check for alpha builds and older
|
||||
if version_installed['tag'] == 'alpha':
|
||||
# check if you are using a RC build lower than current available RC
|
||||
# then check if you are using a beta/alpha lower than current available RC
|
||||
# 14.0a3 is newer than: 14.0a1 or pre-alpha
|
||||
if version_installed['major'] <= int(alpha_version['major']):
|
||||
if version_installed['minor'] <= int(alpha_version['minor']):
|
||||
if version_installed.get('tagversion', '') < alpha_version['tagversion']:
|
||||
version_available = alpha_version
|
||||
old_version = True
|
||||
log('Version available %s' % alpha_version)
|
||||
log('You are running an older alpha version')
|
||||
# now check if installed !=alpha
|
||||
elif version_installed['tag'] in ['prealpha']:
|
||||
if version_installed['major'] <= int(alpha_version['major']):
|
||||
if version_installed['minor'] <= int(alpha_version['minor']):
|
||||
version_available = alpha_version
|
||||
old_version = True
|
||||
log('Version available %s' % alpha_version)
|
||||
log('You are running an older non alpha version')
|
||||
|
||||
return old_version, version_available
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from .common import log
|
||||
|
||||
|
||||
def compare_version(version_installed, version_list):
|
||||
""" Compare the installed version against the provided version list
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param version_list: provided versions to compare against
|
||||
:type version_list: dict
|
||||
:return: old, current, available, and stable versions
|
||||
:rtype: bool / 'stable', dict, dict, dict
|
||||
"""
|
||||
# Create separate version lists
|
||||
version_list_stable = version_list['releases']['stable']
|
||||
version_list_rc = version_list['releases']['releasecandidate']
|
||||
version_list_beta = version_list['releases']['beta']
|
||||
version_list_alpha = version_list['releases']['alpha']
|
||||
# version_list_prealpha = version_list['releases']['prealpha']
|
||||
|
||||
stable_version = version_list_stable[0]
|
||||
rc_version = version_list_rc[0]
|
||||
beta_version = version_list_beta[0]
|
||||
alpha_version = version_list_alpha[0]
|
||||
|
||||
log('Version installed %s' % version_installed)
|
||||
|
||||
# Check to upgrade to newest available stable version
|
||||
# check on smaller major version. Smaller version than available always notify
|
||||
|
||||
# check for stable versions
|
||||
old_version, version_available = _check_for_stable_version(version_installed, stable_version)
|
||||
|
||||
if not old_version:
|
||||
# Already skipped a possible newer stable build. Let's continue with non stable builds.
|
||||
# Check also 'old version' hasn't been set to 'stable' or true by previous checks because
|
||||
# if so, those part need to be skipped
|
||||
old_version, version_available = _check_for_rc_version(version_installed,
|
||||
rc_version, beta_version)
|
||||
|
||||
if not old_version:
|
||||
# check for beta builds
|
||||
old_version, version_available = _check_for_beta_version(version_installed, beta_version)
|
||||
|
||||
if not old_version:
|
||||
# check for alpha builds
|
||||
old_version, version_available = _check_for_alpha_version(version_installed, alpha_version)
|
||||
|
||||
return old_version, version_installed, version_available, stable_version
|
||||
|
||||
|
||||
def _check_for_stable_version(version_installed, stable_version):
|
||||
""" Compare the installed version against the latest stable version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param stable_version: latest stable version
|
||||
:type stable_version: dict
|
||||
:return: whether using an old version, and available version if newer stable version available
|
||||
:rtype: bool / 'stable', dict
|
||||
"""
|
||||
# check if installed major version is smaller than available major stable
|
||||
# here we don't care if running non stable
|
||||
old_version = False
|
||||
version_available = {}
|
||||
|
||||
if version_installed['major'] < int(stable_version['major']):
|
||||
version_available = stable_version
|
||||
old_version = 'stable'
|
||||
log('Version available %s' % stable_version)
|
||||
log('You are running an older version')
|
||||
|
||||
# check if installed major version is equal than available major stable
|
||||
# however also check on minor version and still don't care about non stable
|
||||
elif version_installed['major'] == int(stable_version['major']):
|
||||
if version_installed['minor'] < int(stable_version['minor']):
|
||||
version_available = stable_version
|
||||
old_version = 'stable'
|
||||
log('Version available %s' % stable_version)
|
||||
log('You are running an older minor version')
|
||||
# check for <= minor !stable
|
||||
elif version_installed['tag'] != 'stable' and \
|
||||
version_installed['minor'] <= int(stable_version['minor']):
|
||||
version_available = stable_version
|
||||
old_version = True
|
||||
log('Version available %s' % stable_version)
|
||||
log('You are running an older non stable minor version')
|
||||
else:
|
||||
log('Version available %s' % stable_version)
|
||||
log('There is no newer stable available')
|
||||
|
||||
return old_version, version_available
|
||||
|
||||
|
||||
def _check_for_rc_version(version_installed, rc_version, beta_version):
|
||||
""" Compare the installed version against the latest RC version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param rc_version: latest rc version
|
||||
:type rc_version: dict
|
||||
:param beta_version: latest beta version
|
||||
:type beta_version: dict
|
||||
:return: whether using an old version, and available version if newer rc version available
|
||||
:rtype: bool, dict
|
||||
"""
|
||||
old_version = False
|
||||
version_available = {}
|
||||
# check for RC builds
|
||||
if version_installed['tag'] in ['releasecandidate']:
|
||||
# check if you are using a RC build lower than current available RC
|
||||
# then check if you are using a beta/alpha lower than current available RC
|
||||
# 14.0rc3 is newer than: 14.0rc1, 14.0b9, 14.0a15
|
||||
if version_installed['major'] <= int(rc_version['major']):
|
||||
if version_installed['minor'] <= int(rc_version['minor']):
|
||||
if version_installed.get('tagversion', '') < rc_version['tagversion']:
|
||||
version_available = rc_version
|
||||
old_version = True
|
||||
log('Version available %s' % rc_version)
|
||||
log('You are running an older RC version')
|
||||
# now check if installed !=rc
|
||||
elif version_installed['tag'] in ['beta', 'alpha', 'prealpha']:
|
||||
if version_installed['major'] <= int(rc_version['major']):
|
||||
if version_installed['minor'] <= int(beta_version['minor']):
|
||||
version_available = rc_version
|
||||
old_version = True
|
||||
log('Version available %s' % rc_version)
|
||||
log('You are running an older non RC version')
|
||||
|
||||
return old_version, version_available
|
||||
|
||||
|
||||
def _check_for_beta_version(version_installed, beta_version):
|
||||
""" Compare the installed version against the latest beta version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param beta_version: latest beta version
|
||||
:type beta_version: dict
|
||||
:return: whether using an old version, and available version if newer beta version available
|
||||
:rtype: bool, dict
|
||||
"""
|
||||
old_version = False
|
||||
version_available = {}
|
||||
# check for beta builds
|
||||
if not old_version and version_installed['tag'] == 'beta':
|
||||
# check if you are using a RC build lower than current available RC
|
||||
# then check if you are using a beta/alpha lower than current available RC
|
||||
# 14.0b3 is newer than: 14.0b1, 14.0a15
|
||||
if version_installed['major'] <= int(beta_version['major']):
|
||||
if version_installed['minor'] <= int(beta_version['minor']):
|
||||
if version_installed.get('tagversion', '') < beta_version['tagversion']:
|
||||
version_available = beta_version
|
||||
old_version = True
|
||||
log('Version available %s' % beta_version)
|
||||
log('You are running an older beta version')
|
||||
# now check if installed !=beta
|
||||
elif not old_version and version_installed['tag'] in ['alpha', 'prealpha']:
|
||||
if version_installed['major'] <= int(beta_version['major']):
|
||||
if version_installed['minor'] <= int(beta_version['minor']):
|
||||
version_available = beta_version
|
||||
old_version = True
|
||||
log('Version available %s' % beta_version)
|
||||
log('You are running an older non beta version')
|
||||
|
||||
return old_version, version_available
|
||||
|
||||
|
||||
def _check_for_alpha_version(version_installed, alpha_version):
|
||||
""" Compare the installed version against the latest alpha version
|
||||
|
||||
:param version_installed: currently installed version
|
||||
:type version_installed: dict
|
||||
:param alpha_version: latest alpha version
|
||||
:type alpha_version: dict
|
||||
:return: whether using an old version, and available version if newer alpha version available
|
||||
:rtype: bool, dict
|
||||
"""
|
||||
old_version = False
|
||||
version_available = {}
|
||||
# check for alpha builds and older
|
||||
if version_installed['tag'] == 'alpha':
|
||||
# check if you are using a RC build lower than current available RC
|
||||
# then check if you are using a beta/alpha lower than current available RC
|
||||
# 14.0a3 is newer than: 14.0a1 or pre-alpha
|
||||
if version_installed['major'] <= int(alpha_version['major']):
|
||||
if version_installed['minor'] <= int(alpha_version['minor']):
|
||||
if version_installed.get('tagversion', '') < alpha_version['tagversion']:
|
||||
version_available = alpha_version
|
||||
old_version = True
|
||||
log('Version available %s' % alpha_version)
|
||||
log('You are running an older alpha version')
|
||||
# now check if installed !=alpha
|
||||
elif version_installed['tag'] in ['prealpha']:
|
||||
if version_installed['major'] <= int(alpha_version['major']):
|
||||
if version_installed['minor'] <= int(alpha_version['minor']):
|
||||
version_available = alpha_version
|
||||
old_version = True
|
||||
log('Version available %s' % alpha_version)
|
||||
log('You are running an older non alpha version')
|
||||
|
||||
return old_version, version_available
|
||||
|
|
|
|||
|
|
@ -1,159 +1,159 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2011-2013 Martijn Kaijser
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from contextlib import closing
|
||||
import os
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcaddon # pylint: disable=import-error
|
||||
import xbmcgui # pylint: disable=import-error
|
||||
import xbmcvfs # pylint: disable=import-error
|
||||
|
||||
_ADDON = xbmcaddon.Addon('service.xbmc.versioncheck')
|
||||
_ADDON_NAME = _ADDON.getAddonInfo('name')
|
||||
if sys.version_info[0] >= 3:
|
||||
_ADDON_PATH = _ADDON.getAddonInfo('path')
|
||||
else:
|
||||
_ADDON_PATH = _ADDON.getAddonInfo('path').decode('utf-8')
|
||||
_ICON = _ADDON.getAddonInfo('icon')
|
||||
|
||||
|
||||
class Viewer:
|
||||
""" Show user a text viewer (WINDOW_DIALOG_TEXT_VIEWER)
|
||||
Include the text file for the viewers body in the resources/ directory
|
||||
|
||||
usage:
|
||||
script_path = os.path.join(_ADDON_PATH, 'resources', 'lib', 'version_check', 'viewer.py')
|
||||
xbmc.executebuiltin('RunScript(%s,%s,%s)' % (script_path, 'Heading', 'notice.txt'))
|
||||
|
||||
:param heading: text viewer heading
|
||||
:type heading: str
|
||||
:param filename: filename to use for text viewers body
|
||||
:type filename: str
|
||||
"""
|
||||
WINDOW = 10147
|
||||
CONTROL_LABEL = 1
|
||||
CONTROL_TEXTBOX = 5
|
||||
|
||||
def __init__(self, heading, filename):
|
||||
self.heading = heading
|
||||
self.filename = filename
|
||||
# activate the text viewer window
|
||||
xbmc.executebuiltin('ActivateWindow(%d)' % (self.WINDOW,))
|
||||
# get window
|
||||
self.window = xbmcgui.Window(self.WINDOW)
|
||||
# give window time to initialize
|
||||
xbmc.sleep(100)
|
||||
# set controls
|
||||
self.set_controls()
|
||||
|
||||
def set_controls(self):
|
||||
""" Set the window controls
|
||||
"""
|
||||
# get text viewer body text
|
||||
text = self.get_text()
|
||||
# set heading
|
||||
self.window.getControl(self.CONTROL_LABEL).setLabel('%s : %s' % (_ADDON_NAME,
|
||||
self.heading,))
|
||||
# set text
|
||||
self.window.getControl(self.CONTROL_TEXTBOX).setText(text)
|
||||
xbmc.sleep(2000)
|
||||
|
||||
def get_text(self):
|
||||
""" Get the text viewers body text from self.filename
|
||||
|
||||
:return: contents of self.filename
|
||||
:rtype: str
|
||||
"""
|
||||
try:
|
||||
return self.read_file(self.filename)
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
xbmc.log(_ADDON_NAME + ': ' + str(error), xbmc.LOGERROR)
|
||||
return ''
|
||||
|
||||
@staticmethod
|
||||
def read_file(filename):
|
||||
""" Read the contents of the provided file, from
|
||||
os.path.join(_ADDON_PATH, 'resources', filename)
|
||||
|
||||
:param filename: name of file to read
|
||||
:type filename: str
|
||||
:return: contents of the provided file
|
||||
:rtype: str
|
||||
"""
|
||||
filename = os.path.join(_ADDON_PATH, 'resources', filename)
|
||||
with closing(xbmcvfs.File(filename)) as open_file:
|
||||
contents = open_file.read()
|
||||
return contents
|
||||
|
||||
|
||||
class WebBrowser:
|
||||
""" Display url using the default browser
|
||||
|
||||
usage:
|
||||
script_path = os.path.join(_ADDON_PATH, 'resources', 'lib', 'version_check', 'viewer.py')
|
||||
xbmc.executebuiltin('RunScript(%s,%s,%s)' % (script_path, 'webbrowser', 'https://kodi.tv/'))
|
||||
|
||||
:param url: url to open
|
||||
:type url: str
|
||||
"""
|
||||
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
try:
|
||||
# notify user
|
||||
self.notification(_ADDON_NAME, self.url)
|
||||
xbmc.sleep(100)
|
||||
# launch url
|
||||
self.launch_url()
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
xbmc.log(_ADDON_NAME + ': ' + str(error), xbmc.LOGERROR)
|
||||
|
||||
@staticmethod
|
||||
def notification(heading, message, icon=None, time=15000, sound=True):
|
||||
""" Create a notification
|
||||
|
||||
:param heading: notification heading
|
||||
:type heading: str
|
||||
:param message: notification message
|
||||
:type message: str
|
||||
:param icon: path and filename for the notification icon
|
||||
:type icon: str
|
||||
:param time: time to display notification
|
||||
:type time: int
|
||||
:param sound: is notification audible
|
||||
:type sound: bool
|
||||
"""
|
||||
if not icon:
|
||||
icon = _ICON
|
||||
xbmcgui.Dialog().notification(heading, message, icon, time, sound)
|
||||
|
||||
def launch_url(self):
|
||||
""" Open self.url in the default web browser
|
||||
"""
|
||||
import webbrowser # pylint: disable=import-outside-toplevel
|
||||
webbrowser.open(self.url)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if sys.argv[1] == 'webbrowser':
|
||||
WebBrowser(sys.argv[2])
|
||||
else:
|
||||
Viewer(sys.argv[1], sys.argv[2])
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
xbmc.log(_ADDON_NAME + ': ' + str(err), xbmc.LOGERROR)
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
Copyright (C) 2011-2013 Martijn Kaijser
|
||||
Copyright (C) 2013-2014 Team-XBMC
|
||||
Copyright (C) 2014-2019 Team Kodi
|
||||
|
||||
This file is part of service.xbmc.versioncheck
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
See LICENSES/GPL-3.0-or-later.txt for more information.
|
||||
|
||||
"""
|
||||
|
||||
from contextlib import closing
|
||||
import os
|
||||
import sys
|
||||
|
||||
import xbmc # pylint: disable=import-error
|
||||
import xbmcaddon # pylint: disable=import-error
|
||||
import xbmcgui # pylint: disable=import-error
|
||||
import xbmcvfs # pylint: disable=import-error
|
||||
|
||||
_ADDON = xbmcaddon.Addon('service.xbmc.versioncheck')
|
||||
_ADDON_NAME = _ADDON.getAddonInfo('name')
|
||||
if sys.version_info[0] >= 3:
|
||||
_ADDON_PATH = _ADDON.getAddonInfo('path')
|
||||
else:
|
||||
_ADDON_PATH = _ADDON.getAddonInfo('path').decode('utf-8')
|
||||
_ICON = _ADDON.getAddonInfo('icon')
|
||||
|
||||
|
||||
class Viewer:
|
||||
""" Show user a text viewer (WINDOW_DIALOG_TEXT_VIEWER)
|
||||
Include the text file for the viewers body in the resources/ directory
|
||||
|
||||
usage:
|
||||
script_path = os.path.join(_ADDON_PATH, 'resources', 'lib', 'version_check', 'viewer.py')
|
||||
xbmc.executebuiltin('RunScript(%s,%s,%s)' % (script_path, 'Heading', 'notice.txt'))
|
||||
|
||||
:param heading: text viewer heading
|
||||
:type heading: str
|
||||
:param filename: filename to use for text viewers body
|
||||
:type filename: str
|
||||
"""
|
||||
WINDOW = 10147
|
||||
CONTROL_LABEL = 1
|
||||
CONTROL_TEXTBOX = 5
|
||||
|
||||
def __init__(self, heading, filename):
|
||||
self.heading = heading
|
||||
self.filename = filename
|
||||
# activate the text viewer window
|
||||
xbmc.executebuiltin('ActivateWindow(%d)' % (self.WINDOW,))
|
||||
# get window
|
||||
self.window = xbmcgui.Window(self.WINDOW)
|
||||
# give window time to initialize
|
||||
xbmc.sleep(100)
|
||||
# set controls
|
||||
self.set_controls()
|
||||
|
||||
def set_controls(self):
|
||||
""" Set the window controls
|
||||
"""
|
||||
# get text viewer body text
|
||||
text = self.get_text()
|
||||
# set heading
|
||||
self.window.getControl(self.CONTROL_LABEL).setLabel('%s : %s' % (_ADDON_NAME,
|
||||
self.heading,))
|
||||
# set text
|
||||
self.window.getControl(self.CONTROL_TEXTBOX).setText(text)
|
||||
xbmc.sleep(2000)
|
||||
|
||||
def get_text(self):
|
||||
""" Get the text viewers body text from self.filename
|
||||
|
||||
:return: contents of self.filename
|
||||
:rtype: str
|
||||
"""
|
||||
try:
|
||||
return self.read_file(self.filename)
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
xbmc.log(_ADDON_NAME + ': ' + str(error), xbmc.LOGERROR)
|
||||
return ''
|
||||
|
||||
@staticmethod
|
||||
def read_file(filename):
|
||||
""" Read the contents of the provided file, from
|
||||
os.path.join(_ADDON_PATH, 'resources', filename)
|
||||
|
||||
:param filename: name of file to read
|
||||
:type filename: str
|
||||
:return: contents of the provided file
|
||||
:rtype: str
|
||||
"""
|
||||
filename = os.path.join(_ADDON_PATH, 'resources', filename)
|
||||
with closing(xbmcvfs.File(filename)) as open_file:
|
||||
contents = open_file.read()
|
||||
return contents
|
||||
|
||||
|
||||
class WebBrowser:
|
||||
""" Display url using the default browser
|
||||
|
||||
usage:
|
||||
script_path = os.path.join(_ADDON_PATH, 'resources', 'lib', 'version_check', 'viewer.py')
|
||||
xbmc.executebuiltin('RunScript(%s,%s,%s)' % (script_path, 'webbrowser', 'https://kodi.tv/'))
|
||||
|
||||
:param url: url to open
|
||||
:type url: str
|
||||
"""
|
||||
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
try:
|
||||
# notify user
|
||||
self.notification(_ADDON_NAME, self.url)
|
||||
xbmc.sleep(100)
|
||||
# launch url
|
||||
self.launch_url()
|
||||
except Exception as error: # pylint: disable=broad-except
|
||||
xbmc.log(_ADDON_NAME + ': ' + str(error), xbmc.LOGERROR)
|
||||
|
||||
@staticmethod
|
||||
def notification(heading, message, icon=None, time=15000, sound=True):
|
||||
""" Create a notification
|
||||
|
||||
:param heading: notification heading
|
||||
:type heading: str
|
||||
:param message: notification message
|
||||
:type message: str
|
||||
:param icon: path and filename for the notification icon
|
||||
:type icon: str
|
||||
:param time: time to display notification
|
||||
:type time: int
|
||||
:param sound: is notification audible
|
||||
:type sound: bool
|
||||
"""
|
||||
if not icon:
|
||||
icon = _ICON
|
||||
xbmcgui.Dialog().notification(heading, message, icon, time, sound)
|
||||
|
||||
def launch_url(self):
|
||||
""" Open self.url in the default web browser
|
||||
"""
|
||||
import webbrowser # pylint: disable=import-outside-toplevel
|
||||
webbrowser.open(self.url)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if sys.argv[1] == 'webbrowser':
|
||||
WebBrowser(sys.argv[2])
|
||||
else:
|
||||
Viewer(sys.argv[1], sys.argv[2])
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
xbmc.log(_ADDON_NAME + ': ' + str(err), xbmc.LOGERROR)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
If you run Kodi/XBMC standalone and/or do want to have password less upgrades, copy the file
|
||||
10-allow-update.conf to /etc/polkit-1/localauthority/50-local.d/
|
||||
|
||||
Make sure to adjust the username if it is different from "kodi"
|
||||
|
||||
For this to work, you must have python-apt and python-aptdaemon installed:
|
||||
sudo apt-get install python-apt python-aptdaemon
|
||||
|
||||
|
||||
If those packages are not installed, this script will fallback to calling apt directly and ask you
|
||||
for your password.
|
||||
If you run Kodi/XBMC standalone and/or do want to have password less upgrades, copy the file
|
||||
10-allow-update.conf to /etc/polkit-1/localauthority/50-local.d/
|
||||
|
||||
Make sure to adjust the username if it is different from "kodi"
|
||||
|
||||
For this to work, you must have python-apt and python-aptdaemon installed:
|
||||
sudo apt-get install python-apt python-aptdaemon
|
||||
|
||||
|
||||
If those packages are not installed, this script will fallback to calling apt directly and ask you
|
||||
for your password.
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#a4c639" stroke-width=".27763"/>
|
||||
<path d="m21.059 281.63c0-0.62897-0.50779-1.1406-1.1391-1.1406-0.63126 0-1.1421 0.50935-1.1421 1.1422v4.7769c0 0.62508 0.51165 1.1421 1.1445 1.1421 0.62818 0 1.1391-0.51705 1.1391-1.1421v-4.7846h-0.0079zm-12.929-0.92221 0.0032 7.4085c0 0.68298 0.54328 1.227 1.2139 1.227h0.82033v2.5312c0 0.63281 0.50933 1.1437 1.1344 1.1437 0.62509 0 1.1321-0.50932 1.1421-1.1328v-2.5312h1.538v2.5312c0 0.63511 0.50933 1.1444 1.1344 1.1444 0.63512 0 1.1437-0.50932 1.1437-1.1499v-2.5312h0.83191c0.67139 0 1.2139-0.54791 1.2139-1.2178v-7.4316l-10.209 6e-3 0.03086 2e-3zm7.4455-2.2611c-0.23923 0-0.43216-0.1928-0.43216-0.43214 0-0.23538 0.19294-0.43063 0.43216-0.43217 0.23923 0 0.43216 0.19688 0.43216 0.43217 0 0.23917-0.19294 0.43214-0.43216 0.43214m-4.6766 0c-0.23923 0-0.43216-0.1928-0.43216-0.43214 0-0.23684 0.19294-0.43063 0.43216-0.43063 0.23923 0 0.43216 0.19688 0.43216 0.43987 0 0.24297-0.19449 0.43757-0.43988 0.43757m4.8541-2.238 0.7941-1.4593c0.04629-0.0811 0.01079-0.17442-0.05866-0.21992-0.08027-0.0347-0.17287-0.0117-0.21916 0.0694l-0.8103 1.4662c-0.66985-0.31253-1.4323-0.48616-2.2303-0.48616-0.79795 0-1.5573 0.16596-2.2318 0.46534l-0.79795-1.4686c-0.04089-0.0755-0.13892-0.10413-0.21452-0.0618-0.07718 0.0347-0.10494 0.13884-0.06175 0.20826l0.79487 1.447c-1.5666 0.80799-2.6238 2.346-2.6238 4.1132h10.285c0-1.7672-1.0557-3.3053-2.6207-4.1132m-9.2127 4.3002c-0.63049 0-1.1421 0.51319-1.1421 1.1445v4.7785c0 0.63281 0.51242 1.1421 1.1452 1.1421 0.62817 0 1.1398-0.50932 1.1398-1.1421v-4.7769c0-0.62897-0.50933-1.1406-1.1344-1.1406" fill="#ffffff" stroke-width=".77172"/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#a4c639" stroke-width=".27763"/>
|
||||
<path d="m21.059 281.63c0-0.62897-0.50779-1.1406-1.1391-1.1406-0.63126 0-1.1421 0.50935-1.1421 1.1422v4.7769c0 0.62508 0.51165 1.1421 1.1445 1.1421 0.62818 0 1.1391-0.51705 1.1391-1.1421v-4.7846h-0.0079zm-12.929-0.92221 0.0032 7.4085c0 0.68298 0.54328 1.227 1.2139 1.227h0.82033v2.5312c0 0.63281 0.50933 1.1437 1.1344 1.1437 0.62509 0 1.1321-0.50932 1.1421-1.1328v-2.5312h1.538v2.5312c0 0.63511 0.50933 1.1444 1.1344 1.1444 0.63512 0 1.1437-0.50932 1.1437-1.1499v-2.5312h0.83191c0.67139 0 1.2139-0.54791 1.2139-1.2178v-7.4316l-10.209 6e-3 0.03086 2e-3zm7.4455-2.2611c-0.23923 0-0.43216-0.1928-0.43216-0.43214 0-0.23538 0.19294-0.43063 0.43216-0.43217 0.23923 0 0.43216 0.19688 0.43216 0.43217 0 0.23917-0.19294 0.43214-0.43216 0.43214m-4.6766 0c-0.23923 0-0.43216-0.1928-0.43216-0.43214 0-0.23684 0.19294-0.43063 0.43216-0.43063 0.23923 0 0.43216 0.19688 0.43216 0.43987 0 0.24297-0.19449 0.43757-0.43988 0.43757m4.8541-2.238 0.7941-1.4593c0.04629-0.0811 0.01079-0.17442-0.05866-0.21992-0.08027-0.0347-0.17287-0.0117-0.21916 0.0694l-0.8103 1.4662c-0.66985-0.31253-1.4323-0.48616-2.2303-0.48616-0.79795 0-1.5573 0.16596-2.2318 0.46534l-0.79795-1.4686c-0.04089-0.0755-0.13892-0.10413-0.21452-0.0618-0.07718 0.0347-0.10494 0.13884-0.06175 0.20826l0.79487 1.447c-1.5666 0.80799-2.6238 2.346-2.6238 4.1132h10.285c0-1.7672-1.0557-3.3053-2.6207-4.1132m-9.2127 4.3002c-0.63049 0-1.1421 0.51319-1.1421 1.1445v4.7785c0 0.63281 0.51242 1.1421 1.1452 1.1421 0.62817 0 1.1398-0.50932 1.1398-1.1421v-4.7769c0-0.62897-0.50933-1.1406-1.1344-1.1406" fill="#ffffff" stroke-width=".77172"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
|
@ -1,19 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect x="-1.4211e-14" y="8.5449e-6" width="26.458" height="26.458" fill="#294172" stroke-width=".27763"/>
|
||||
<path id="voice" d="m22.489 13.23c0-5.1145-4.1461-9.2611-9.2602-9.2611-5.1122 0-9.2567 4.1428-9.2602 9.2541v7.1663c0.00273 1.1606 0.94405 2.1001 2.1054 2.1001h7.1587c5.1128-0.0018 9.2567-4.1468 9.2567-9.2602" fill="#ffffff" stroke-width=".069562"/>
|
||||
<path id="in" d="m9.3076 13.825h3.3282v3.3282c0 1.8372-1.491 3.3282-3.3282 3.3282s-3.3282-1.491-3.3282-3.3282 1.491-3.3282 3.3282-3.3282z" fill="none" stroke="#3c6eb4" stroke-width="2.0319"/>
|
||||
<use id="finity" transform="rotate(180 12.628 13.834)" width="100%" height="100%" xlink:href="#in"/>
|
||||
<path id="free" d="m13.654 12.819v4.3369c0 2.4002-1.946 4.3463-4.3463 4.3463-0.36415 0-0.62303-0.04112-0.96015-0.12923-0.49152-0.12863-0.89321-0.53163-0.89339-1.0004 0-0.5666 0.41128-0.9787 1.026-0.9787 0.2926 0 0.39878 0.05618 0.82744 0.05618 1.2654 0 2.2919-1.025 2.2941-2.2904v-1.9934c0-0.17862-0.14515-0.32334-0.32407-0.32334l-1.5071-2.72e-4c-0.56151 0-1.0152-0.44787-1.0152-1.0109-2.996e-4 -0.56656 0.45833-1.0126 1.0259-1.0126" fill="#294172" stroke-width=".069562"/>
|
||||
<use id="dom" transform="rotate(180 12.628 13.834)" width="100%" height="100%" xlink:href="#free"/>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect x="-1.4211e-14" y="8.5449e-6" width="26.458" height="26.458" fill="#294172" stroke-width=".27763"/>
|
||||
<path id="voice" d="m22.489 13.23c0-5.1145-4.1461-9.2611-9.2602-9.2611-5.1122 0-9.2567 4.1428-9.2602 9.2541v7.1663c0.00273 1.1606 0.94405 2.1001 2.1054 2.1001h7.1587c5.1128-0.0018 9.2567-4.1468 9.2567-9.2602" fill="#ffffff" stroke-width=".069562"/>
|
||||
<path id="in" d="m9.3076 13.825h3.3282v3.3282c0 1.8372-1.491 3.3282-3.3282 3.3282s-3.3282-1.491-3.3282-3.3282 1.491-3.3282 3.3282-3.3282z" fill="none" stroke="#3c6eb4" stroke-width="2.0319"/>
|
||||
<use id="finity" transform="rotate(180 12.628 13.834)" width="100%" height="100%" xlink:href="#in"/>
|
||||
<path id="free" d="m13.654 12.819v4.3369c0 2.4002-1.946 4.3463-4.3463 4.3463-0.36415 0-0.62303-0.04112-0.96015-0.12923-0.49152-0.12863-0.89321-0.53163-0.89339-1.0004 0-0.5666 0.41128-0.9787 1.026-0.9787 0.2926 0 0.39878 0.05618 0.82744 0.05618 1.2654 0 2.2919-1.025 2.2941-2.2904v-1.9934c0-0.17862-0.14515-0.32334-0.32407-0.32334l-1.5071-2.72e-4c-0.56151 0-1.0152-0.44787-1.0152-1.0109-2.996e-4 -0.56656 0.45833-1.0126 1.0259-1.0126" fill="#294172" stroke-width=".069562"/>
|
||||
<use id="dom" transform="rotate(180 12.628 13.834)" width="100%" height="100%" xlink:href="#free"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,18 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#990000" stroke-width=".27763"/>
|
||||
<path d="m22.42 274.83c0.99718 0.99658-1.7672 5.3777-2.2346 5.8453-0.46729 0.46662-1.6543 0.0373-2.6509-0.95968-0.99718-0.99659-1.4267-2.1838-0.95938-2.6512 0.46707-0.46751 4.8479-3.2317 5.8449-2.2345m-13.983 1.0545c-1.5223-0.86371-3.6886-1.8246-4.3776-1.1354-0.6982 0.6979 0.29779 2.9128 1.1707 4.4379a9.3614 9.3614 0 0 1 3.2069 -3.3025" fill="#ffffff" stroke-width=".073821"/>
|
||||
<path d="m20.831 280.03c0.14342 0.48638 0.11767 0.88818-0.11495 1.1204-0.54326 0.54348-2.0108-0.0351-3.3337-1.2941a6.7507 6.7507 0 0 1 -0.27393 -0.25891c-0.47838-0.47853-0.85057-0.98787-1.0886-1.457-0.46335-0.83123-0.57928-1.5654-0.22907-1.9156 0.19085-0.19062 0.4962-0.24258 0.8687-0.17559 0.24289-0.15363 0.52966-0.32476 0.84408-0.50006-1.2786-0.66689-2.7322-1.0435-4.2742-1.0435-5.1145 0-9.2608 4.1456-9.2608 9.2606 0 5.1141 4.1464 9.2602 9.2608 9.2602 5.1146 0 9.2607-4.1461 9.2607-9.2602 0-1.6518-0.43352-3.2006-1.1908-4.5433-0.16366 0.2987-0.3228 0.57233-0.46811 0.80715" fill="#ffffff" stroke-width=".075526"/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#990000" stroke-width=".27763"/>
|
||||
<path d="m22.42 274.83c0.99718 0.99658-1.7672 5.3777-2.2346 5.8453-0.46729 0.46662-1.6543 0.0373-2.6509-0.95968-0.99718-0.99659-1.4267-2.1838-0.95938-2.6512 0.46707-0.46751 4.8479-3.2317 5.8449-2.2345m-13.983 1.0545c-1.5223-0.86371-3.6886-1.8246-4.3776-1.1354-0.6982 0.6979 0.29779 2.9128 1.1707 4.4379a9.3614 9.3614 0 0 1 3.2069 -3.3025" fill="#ffffff" stroke-width=".073821"/>
|
||||
<path d="m20.831 280.03c0.14342 0.48638 0.11767 0.88818-0.11495 1.1204-0.54326 0.54348-2.0108-0.0351-3.3337-1.2941a6.7507 6.7507 0 0 1 -0.27393 -0.25891c-0.47838-0.47853-0.85057-0.98787-1.0886-1.457-0.46335-0.83123-0.57928-1.5654-0.22907-1.9156 0.19085-0.19062 0.4962-0.24258 0.8687-0.17559 0.24289-0.15363 0.52966-0.32476 0.84408-0.50006-1.2786-0.66689-2.7322-1.0435-4.2742-1.0435-5.1145 0-9.2608 4.1456-9.2608 9.2606 0 5.1141 4.1464 9.2602 9.2608 9.2602 5.1146 0 9.2607-4.1461 9.2607-9.2602 0-1.6518-0.43352-3.2006-1.1908-4.5433-0.16366 0.2987-0.3228 0.57233-0.46811 0.80715" fill="#ffffff" stroke-width=".075526"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#73ba25" stroke-width=".27763"/>
|
||||
<path d="m11.815 286.7 0.0272-3e-3 0.0049-0.0319c-0.0073-0.0247-0.02355-0.0471-0.04953-0.35762-0.02172-0.27466-0.06577-1.0274 0.32276-1.401 0.15042-0.14554 0.38102-0.27545 0.5621-0.31703 0.74439-0.17742 1.6173-0.0547 2.442 0.87606 0.4267 0.4812 0.63517 0.70041 0.73992 0.79883l0.03613 0.0321 0.04324 0.0311c0.03451 0.0186 1.4185 0.64 1.4185 0.64l0.02822-7e-3 3.91e-4 -0.0289c-0.0087-0.0101-0.87694-1.1044-0.72307-2.0056 0.1222-0.71783 0.70805-0.65327 1.5178-0.56376 0.2645 0.0295 0.56616 0.0636 0.87735 0.0701 0.87024 5e-3 1.8079-0.1507 2.386-0.39724 0.37351-0.15901 0.61183-0.26417 0.76123-0.39684 0.054-0.0434 0.08161-0.11426 0.11063-0.18971l0.0203-0.0507c0.02416-0.061 0.05948-0.1909 0.07491-0.2614 0.0071-0.0315 0.01035-0.065-0.01197-0.082l-0.08039 0.0145c-0.25293 0.14871-0.8873 0.4309-1.4809 0.44219-0.73586 0.0149-2.2179-0.722-2.3728-0.79982l-0.01462-0.0172c-0.03694-0.0863-0.25882-0.59941-0.30652-0.70793 1.0674 0.68555 1.9518 1.0646 2.6294 1.1236 0.75454 0.0653 1.342-0.33585 1.5939-0.50754 0.04913-0.0321 0.08648-0.0584 0.1015-0.0642l0.01624-0.0257c-0.04162-0.25821-0.43563-1.5089-0.73342-1.8099-0.08242-0.082-0.14859-0.16237-0.28196-0.23841-1.0781-0.61309-3.6369-0.983-3.7571-1l-0.0203 6e-3 -0.0075 0.0178s-0.01035 0.51764-0.01117 0.57506c-0.26227-0.085-2.1621-0.68358-3.943-0.74378-1.5101-0.0521-3.7091-0.24218-6.6238 1.5054l-0.08627 0.0527c-1.371 0.83467-2.3174 1.863-2.8123 3.0587-0.15509 0.37585-0.36418 1.225-0.15793 2.0234 0.08972 0.34912 0.25618 0.69941 0.48008 1.0139 0.50607 0.70932 1.3552 1.18 2.2707 1.2596 1.2913 0.11227 2.2701-0.45348 2.6176-1.5131 0.23933-0.73109 0-1.8042-0.91673-2.3515-0.74581-0.44535-1.548-0.34357-2.0131-0.044-0.40416 0.26119-0.63294 0.66654-0.62888 1.1123 0.0093 0.79011 0.70764 1.2101 1.2092 1.2111 0.14616 0 0.29231-0.0244 0.45735-0.077 0.05846-0.0176 0.11449-0.039 0.17498-0.0756l0.01908-0.0115 0.01259-8e-3 -0.0049 2e-3c0.11449-0.0754 0.18391-0.1992 0.18391-0.33207 0-0.036-0.0055-0.0731-0.01604-0.1101-0.05887-0.19961-0.26146-0.32061-0.47156-0.28377l-0.02842 6e-3 -0.03857 0.0121-0.05582 0.0182c-0.1155 0.0283-0.20218 0.0301-0.22045 0.0309-0.05927-4e-3 -0.34794-0.0881-0.34794-0.39684v-4e-3c6.12e-4 -0.11308 0.04709-0.19288 0.07288-0.23625 0.08911-0.13723 0.33535-0.27248 0.66847-0.24357 0.43583 0.0364 0.75007 0.25446 0.95814 0.66616 0.19366 0.38298 0.14311 0.85327-0.13032 1.1986-0.271 0.34218-0.75352 0.48694-1.3962 0.41902-0.64776-0.0695-1.195-0.43328-1.5018-0.99942-0.30003-0.55289-0.31667-1.2089-0.04243-1.7127 0.65588-1.207 1.8938-1.1943 2.5728-1.0806 1.0052 0.1701 2.1479 1.0749 2.5539 2.1188 0.06516 0.16634 0.09845 0.29842 0.12667 0.41823l0.04405 0.18079 1.1352 0.5408zm7.9773-5.8922c-0.21416 0.19426-0.33616 0.45902-0.34651 0.74418-0.0199 0.58813 0.45309 1.0832 1.0554 1.1054 0.29414 0.01 0.57204-0.0913 0.7858-0.28653 0.21376-0.19426 0.33576-0.45863 0.34692-0.74319 0.0203-0.58833-0.45268-1.0846-1.0566-1.106-0.29211-0.01-0.57123 0.0915-0.78498 0.28613" clip-rule="evenodd" fill="#ffffff" fill-rule="evenodd" stroke-width=".20049"/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#73ba25" stroke-width=".27763"/>
|
||||
<path d="m11.815 286.7 0.0272-3e-3 0.0049-0.0319c-0.0073-0.0247-0.02355-0.0471-0.04953-0.35762-0.02172-0.27466-0.06577-1.0274 0.32276-1.401 0.15042-0.14554 0.38102-0.27545 0.5621-0.31703 0.74439-0.17742 1.6173-0.0547 2.442 0.87606 0.4267 0.4812 0.63517 0.70041 0.73992 0.79883l0.03613 0.0321 0.04324 0.0311c0.03451 0.0186 1.4185 0.64 1.4185 0.64l0.02822-7e-3 3.91e-4 -0.0289c-0.0087-0.0101-0.87694-1.1044-0.72307-2.0056 0.1222-0.71783 0.70805-0.65327 1.5178-0.56376 0.2645 0.0295 0.56616 0.0636 0.87735 0.0701 0.87024 5e-3 1.8079-0.1507 2.386-0.39724 0.37351-0.15901 0.61183-0.26417 0.76123-0.39684 0.054-0.0434 0.08161-0.11426 0.11063-0.18971l0.0203-0.0507c0.02416-0.061 0.05948-0.1909 0.07491-0.2614 0.0071-0.0315 0.01035-0.065-0.01197-0.082l-0.08039 0.0145c-0.25293 0.14871-0.8873 0.4309-1.4809 0.44219-0.73586 0.0149-2.2179-0.722-2.3728-0.79982l-0.01462-0.0172c-0.03694-0.0863-0.25882-0.59941-0.30652-0.70793 1.0674 0.68555 1.9518 1.0646 2.6294 1.1236 0.75454 0.0653 1.342-0.33585 1.5939-0.50754 0.04913-0.0321 0.08648-0.0584 0.1015-0.0642l0.01624-0.0257c-0.04162-0.25821-0.43563-1.5089-0.73342-1.8099-0.08242-0.082-0.14859-0.16237-0.28196-0.23841-1.0781-0.61309-3.6369-0.983-3.7571-1l-0.0203 6e-3 -0.0075 0.0178s-0.01035 0.51764-0.01117 0.57506c-0.26227-0.085-2.1621-0.68358-3.943-0.74378-1.5101-0.0521-3.7091-0.24218-6.6238 1.5054l-0.08627 0.0527c-1.371 0.83467-2.3174 1.863-2.8123 3.0587-0.15509 0.37585-0.36418 1.225-0.15793 2.0234 0.08972 0.34912 0.25618 0.69941 0.48008 1.0139 0.50607 0.70932 1.3552 1.18 2.2707 1.2596 1.2913 0.11227 2.2701-0.45348 2.6176-1.5131 0.23933-0.73109 0-1.8042-0.91673-2.3515-0.74581-0.44535-1.548-0.34357-2.0131-0.044-0.40416 0.26119-0.63294 0.66654-0.62888 1.1123 0.0093 0.79011 0.70764 1.2101 1.2092 1.2111 0.14616 0 0.29231-0.0244 0.45735-0.077 0.05846-0.0176 0.11449-0.039 0.17498-0.0756l0.01908-0.0115 0.01259-8e-3 -0.0049 2e-3c0.11449-0.0754 0.18391-0.1992 0.18391-0.33207 0-0.036-0.0055-0.0731-0.01604-0.1101-0.05887-0.19961-0.26146-0.32061-0.47156-0.28377l-0.02842 6e-3 -0.03857 0.0121-0.05582 0.0182c-0.1155 0.0283-0.20218 0.0301-0.22045 0.0309-0.05927-4e-3 -0.34794-0.0881-0.34794-0.39684v-4e-3c6.12e-4 -0.11308 0.04709-0.19288 0.07288-0.23625 0.08911-0.13723 0.33535-0.27248 0.66847-0.24357 0.43583 0.0364 0.75007 0.25446 0.95814 0.66616 0.19366 0.38298 0.14311 0.85327-0.13032 1.1986-0.271 0.34218-0.75352 0.48694-1.3962 0.41902-0.64776-0.0695-1.195-0.43328-1.5018-0.99942-0.30003-0.55289-0.31667-1.2089-0.04243-1.7127 0.65588-1.207 1.8938-1.1943 2.5728-1.0806 1.0052 0.1701 2.1479 1.0749 2.5539 2.1188 0.06516 0.16634 0.09845 0.29842 0.12667 0.41823l0.04405 0.18079 1.1352 0.5408zm7.9773-5.8922c-0.21416 0.19426-0.33616 0.45902-0.34651 0.74418-0.0199 0.58813 0.45309 1.0832 1.0554 1.1054 0.29414 0.01 0.57204-0.0913 0.7858-0.28653 0.21376-0.19426 0.33576-0.45863 0.34692-0.74319 0.0203-0.58833-0.45268-1.0846-1.0566-1.106-0.29211-0.01-0.57123 0.0915-0.78498 0.28613" clip-rule="evenodd" fill="#ffffff" fill-rule="evenodd" stroke-width=".20049"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.6 KiB |
|
|
@ -1,23 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect x="-1.4211e-14" y="8.5449e-6" width="26.458" height="26.458" fill="#dd4814" stroke-width=".27763"/>
|
||||
<circle cx="13.229" cy="13.229" r="9.2604" fill="#ffffff" stroke-width=".065339"/>
|
||||
<g transform="matrix(.87503 0 0 .87503 1.6534 -235.08)" fill="#dd4814" stroke-width=".074671">
|
||||
<circle cx="6.0325" cy="283.77" r="1.4129"/>
|
||||
<path d="m9.8237 288.88c-1.2365-0.82612-2.1564-2.0891-2.5385-3.5684 0.44639-0.36374 0.73151-0.91772 0.73151-1.5387s-0.28512-1.175-0.73151-1.5387c0.38207-1.4793 1.3019-2.7423 2.5385-3.5684l1.033 1.7304c-1.0611 0.74683-1.7551 1.9802-1.7551 3.3767 0 1.3966 0.69392 2.6299 1.7551 3.3767z"/>
|
||||
<circle transform="rotate(120)" cx="231.94" cy="-153.34" r="1.4129"/>
|
||||
<path d="m10.509 278.27c1.3337-0.6578 2.8874-0.82293 4.3596-0.41416 0.0918 0.56846 0.42901 1.0924 0.96681 1.4029s1.1601 0.34057 1.6983 0.13585c1.0901 1.0705 1.7239 2.4987 1.8211 3.9826l-2.0151 0.0294c-0.1162-1.2924-0.83735-2.51-2.0468-3.2083-1.2094-0.69828-2.6245-0.714-3.8019-0.16843z"/>
|
||||
<circle transform="rotate(240)" cx="-259.56" cy="-130.43" r="1.4129"/>
|
||||
<path d="m19.355 284.17c-0.09718 1.4839-0.73103 2.912-1.8211 3.9826-0.5382-0.20472-1.1605-0.17465-1.6983 0.13585s-0.87501 0.83441-0.96681 1.4029c-1.4722 0.40877-3.0259 0.24364-4.3596-0.41416l0.98207-1.7598c1.1773 0.54557 2.5924 0.52985 3.8019-0.16843 1.2094-0.69827 1.9306-1.9159 2.0468-3.2083z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect x="-1.4211e-14" y="8.5449e-6" width="26.458" height="26.458" fill="#dd4814" stroke-width=".27763"/>
|
||||
<circle cx="13.229" cy="13.229" r="9.2604" fill="#ffffff" stroke-width=".065339"/>
|
||||
<g transform="matrix(.87503 0 0 .87503 1.6534 -235.08)" fill="#dd4814" stroke-width=".074671">
|
||||
<circle cx="6.0325" cy="283.77" r="1.4129"/>
|
||||
<path d="m9.8237 288.88c-1.2365-0.82612-2.1564-2.0891-2.5385-3.5684 0.44639-0.36374 0.73151-0.91772 0.73151-1.5387s-0.28512-1.175-0.73151-1.5387c0.38207-1.4793 1.3019-2.7423 2.5385-3.5684l1.033 1.7304c-1.0611 0.74683-1.7551 1.9802-1.7551 3.3767 0 1.3966 0.69392 2.6299 1.7551 3.3767z"/>
|
||||
<circle transform="rotate(120)" cx="231.94" cy="-153.34" r="1.4129"/>
|
||||
<path d="m10.509 278.27c1.3337-0.6578 2.8874-0.82293 4.3596-0.41416 0.0918 0.56846 0.42901 1.0924 0.96681 1.4029s1.1601 0.34057 1.6983 0.13585c1.0901 1.0705 1.7239 2.4987 1.8211 3.9826l-2.0151 0.0294c-0.1162-1.2924-0.83735-2.51-2.0468-3.2083-1.2094-0.69828-2.6245-0.714-3.8019-0.16843z"/>
|
||||
<circle transform="rotate(240)" cx="-259.56" cy="-130.43" r="1.4129"/>
|
||||
<path d="m19.355 284.17c-0.09718 1.4839-0.73103 2.912-1.8211 3.9826-0.5382-0.20472-1.1605-0.17465-1.6983 0.13585s-0.87501 0.83441-0.96681 1.4029c-1.4722 0.40877-3.0259 0.24364-4.3596-0.41416l0.98207-1.7598c1.1773 0.54557 2.5924 0.52985 3.8019-0.16843 1.2094-0.69827 1.9306-1.9159 2.0468-3.2083z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#0078d7" stroke-width=".27763"/>
|
||||
<path d="m3.9688 277.17 7.5241-1.041v7.2933h-7.5241m8.4494-7.4099 10.071-1.504v8.7974h-10.071m-8.4494 0.92604h7.5241v7.2934l-7.5241-1.0434m8.4494-6.25h10.071v8.7974l-9.9549-1.3898" fill="#ffffff" stroke-width=".7717"/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(0 -270.54)">
|
||||
<rect x="-1.4211e-14" y="270.54" width="26.458" height="26.458" fill="#0078d7" stroke-width=".27763"/>
|
||||
<path d="m3.9688 277.17 7.5241-1.041v7.2933h-7.5241m8.4494-7.4099 10.071-1.504v8.7974h-10.071m-8.4494 0.92604h7.5241v7.2934l-7.5241-1.0434m8.4494-6.25h10.071v8.7974l-9.9549-1.3898" fill="#ffffff" stroke-width=".7717"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 963 B After Width: | Height: | Size: 946 B |
|
|
@ -1,182 +1,182 @@
|
|||
diff --git a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
|
||||
index 638446d776..063be46a7d 100644
|
||||
--- a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
|
||||
+++ b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
|
||||
@@ -564,8 +564,10 @@ static int
|
||||
socketpair(int, int, int, SOCKET sockets[2]) // we ignore the first two params: we only use this for a strictly limited case
|
||||
{
|
||||
int result = 0;
|
||||
+ socklen_t name_length = 0;
|
||||
+ int reuse = 1;
|
||||
|
||||
- // initialize with default values
|
||||
+ // initialize with default values
|
||||
sockets[0] = INVALID_SOCKET;
|
||||
sockets[1] = INVALID_SOCKET;
|
||||
|
||||
@@ -578,15 +580,14 @@ socketpair(int, int, int, SOCKET sockets[2]) // we ignore the first two params:
|
||||
memset(&inet_address, 0, sizeof(inet_address));
|
||||
inet_address.sin_family = AF_INET;
|
||||
inet_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
- int reuse = 1;
|
||||
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
|
||||
result = bind(listener, (const sockaddr*)&inet_address, sizeof(inet_address));
|
||||
if (result != 0) goto fail;
|
||||
listen(listener, 1);
|
||||
|
||||
// read the port that was assigned to the listener socket
|
||||
- socklen_t name_length = sizeof(inet_address);
|
||||
- result = getsockname(listener, (struct sockaddr*)&inet_address, &name_length);
|
||||
+ name_length = sizeof(inet_address);
|
||||
+ result = getsockname(listener, (struct sockaddr*)&inet_address, &name_length);
|
||||
if (result != 0) goto fail;
|
||||
|
||||
// create the first socket
|
||||
diff --git a/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp b/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp
|
||||
index 8f3c6b7a0d..3ab979ad3b 100644
|
||||
--- a/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp
|
||||
+++ b/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp
|
||||
@@ -441,7 +441,7 @@ NPT_Win32Thread::NPT_Win32Thread(NPT_Thread* delegator,
|
||||
m_Delegator(delegator),
|
||||
m_Target(target),
|
||||
m_Detached(detached),
|
||||
- m_ThreadHandle(0),
|
||||
+ m_ThreadHandle(nullptr),
|
||||
m_ThreadId(0)
|
||||
{
|
||||
}
|
||||
@@ -567,7 +567,7 @@ NPT_Win32Thread::EntryPoint(void* argument)
|
||||
NPT_Result
|
||||
NPT_Win32Thread::Start()
|
||||
{
|
||||
- if (m_ThreadHandle > 0) {
|
||||
+ if (m_ThreadHandle != nullptr) {
|
||||
// failed
|
||||
NPT_LOG_WARNING("thread already started !");
|
||||
return NPT_ERROR_INVALID_STATE;
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
|
||||
index bae654572c..7d476d1806 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
|
||||
@@ -805,8 +805,9 @@ PLT_CtrlPoint::ProcessEventNotification(PLT_EventSubscriberReference subscriber,
|
||||
var = service->FindStateVariable(property->GetTag());
|
||||
if (var == NULL) continue;
|
||||
|
||||
- if (NPT_FAILED(var->SetValue(property->GetText()?*property->GetText():""))) {
|
||||
- NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
|
||||
+ if (NPT_FAILED(var->SetValue(property->GetText() ? property->GetText()->GetChars() : "")))
|
||||
+ {
|
||||
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
|
||||
}
|
||||
|
||||
vars.Add(var);
|
||||
@@ -1662,12 +1663,11 @@ PLT_CtrlPoint::ProcessSubscribeResponse(NPT_Result res,
|
||||
goto remove_sub;
|
||||
|
||||
failure:
|
||||
- NPT_LOG_SEVERE_4("%subscription failed of sub \"%s\" for service \"%s\" of device \"%s\"",
|
||||
- (const char*)subscription?"S":"Uns",
|
||||
- (const char*)(sid?*sid:"Unknown"),
|
||||
- (const char*)service->GetServiceID(),
|
||||
- (const char*)service->GetDevice()->GetFriendlyName());
|
||||
- res = NPT_FAILED(res)?res:NPT_FAILURE;
|
||||
+ NPT_LOG_SEVERE_4(
|
||||
+ "%subscription failed of sub \"%s\" for service \"%s\" of device \"%s\"",
|
||||
+ (const char*)subscription ? "S" : "Uns", (const char*)(sid ? sid->GetChars() : "Unknown"),
|
||||
+ (const char*)service->GetServiceID(), (const char*)service->GetDevice()->GetFriendlyName());
|
||||
+ res = NPT_FAILED(res) ? res : NPT_FAILURE;
|
||||
|
||||
remove_sub:
|
||||
// in case it was a renewal look for the subscriber with that service and remove it from the list
|
||||
@@ -1814,7 +1814,8 @@ PLT_CtrlPoint::ProcessActionResponse(NPT_Result res,
|
||||
NPT_XmlElementNode* child = (*args)->AsElementNode();
|
||||
if (!child) continue;
|
||||
|
||||
- action->SetArgumentValue(child->GetTag(), child->GetText()?*child->GetText():"");
|
||||
+ action->SetArgumentValue(child->GetTag(),
|
||||
+ child->GetText() ? child->GetText()->GetChars() : "");
|
||||
if (NPT_FAILED(res)) goto failure;
|
||||
}
|
||||
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
|
||||
index b6de5c202d..6f5f09f9cf 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
|
||||
@@ -305,11 +305,12 @@ PLT_DeviceHost::Announce(PLT_DeviceData* device,
|
||||
break;
|
||||
}
|
||||
PLT_UPnPMessageHelper::SetNTS(req, nts);
|
||||
-
|
||||
- NPT_LOG_FINER_3("Sending SSDP NOTIFY (%s) Request to %s (%s)",
|
||||
- nts.GetChars(),
|
||||
+
|
||||
+ NPT_LOG_FINER_3("Sending SSDP NOTIFY (%s) Request to %s (%s)", nts.GetChars(),
|
||||
(const char*)req.GetUrl().ToString(),
|
||||
- (const char*)(PLT_UPnPMessageHelper::GetLocation(req)?*PLT_UPnPMessageHelper::GetLocation(req):""));
|
||||
+ (const char*)(PLT_UPnPMessageHelper::GetLocation(req)
|
||||
+ ? PLT_UPnPMessageHelper::GetLocation(req)->GetChars()
|
||||
+ : ""));
|
||||
|
||||
// upnp:rootdevice
|
||||
if (device->m_ParentUUID.IsEmpty()) {
|
||||
@@ -585,14 +586,13 @@ PLT_DeviceHost::ProcessHttpPostRequest(NPT_HttpRequest& request,
|
||||
name = "ObjectID";
|
||||
}
|
||||
|
||||
- res = action->SetArgumentValue(
|
||||
- name,
|
||||
- child->GetText()?*child->GetText():"");
|
||||
+ res = action->SetArgumentValue(name, child->GetText() ? child->GetText()->GetChars() : "");
|
||||
|
||||
- // test if value was correct
|
||||
- if (res == NPT_ERROR_INVALID_PARAMETERS) {
|
||||
- action->SetError(701, "Invalid Name");
|
||||
- goto error;
|
||||
+ // test if value was correct
|
||||
+ if (res == NPT_ERROR_INVALID_PARAMETERS)
|
||||
+ {
|
||||
+ action->SetError(701, "Invalid Name");
|
||||
+ goto error;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Core/PltUtilities.h b/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
|
||||
index bdc1340173..4677f5be0e 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
|
||||
+++ b/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
|
||||
@@ -140,7 +140,8 @@ public:
|
||||
|
||||
const NPT_String* text = child->GetText();
|
||||
// DLNA 7.3.17
|
||||
- value = text?text->SubString(0, max_size):"";
|
||||
+ if (text)
|
||||
+ value = text->SubString(0, max_size);
|
||||
return NPT_SUCCESS;
|
||||
}
|
||||
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
|
||||
index feeb537648..8686aa9294 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
|
||||
@@ -401,7 +401,7 @@ PLT_MediaServer::ParseTagList(const NPT_String& updates, NPT_Map<NPT_String,NPT_
|
||||
NPT_XmlElementNode* child = (*children)->AsElementNode();
|
||||
if (!child) continue;
|
||||
const NPT_String *txt = child->GetText();
|
||||
- tags[child->GetTag()] = txt ? *txt : "";
|
||||
+ tags[child->GetTag()] = txt ? txt->GetChars() : "";
|
||||
}
|
||||
|
||||
return NPT_SUCCESS;
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
|
||||
index 27d81fae86..794b56be17 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
|
||||
@@ -245,7 +245,7 @@ PLT_SyncMediaBrowser::OnMSStateVariablesChanged(PLT_Service* se
|
||||
if (value.GetLength()) {
|
||||
index = value.Find(',');
|
||||
update_id = (index<0)?value:value.Left(index);
|
||||
- value = (index<0)?"":value.SubString(index+1);
|
||||
+ value = (index < 0) ? "" : value.SubString(index + 1).GetChars();
|
||||
|
||||
// clear cache for that device
|
||||
if (m_UseCache) m_Cache.Clear(device->GetUUID(), item_id);
|
||||
diff --git a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
|
||||
index 638446d776..063be46a7d 100644
|
||||
--- a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
|
||||
+++ b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
|
||||
@@ -564,8 +564,10 @@ static int
|
||||
socketpair(int, int, int, SOCKET sockets[2]) // we ignore the first two params: we only use this for a strictly limited case
|
||||
{
|
||||
int result = 0;
|
||||
+ socklen_t name_length = 0;
|
||||
+ int reuse = 1;
|
||||
|
||||
- // initialize with default values
|
||||
+ // initialize with default values
|
||||
sockets[0] = INVALID_SOCKET;
|
||||
sockets[1] = INVALID_SOCKET;
|
||||
|
||||
@@ -578,15 +580,14 @@ socketpair(int, int, int, SOCKET sockets[2]) // we ignore the first two params:
|
||||
memset(&inet_address, 0, sizeof(inet_address));
|
||||
inet_address.sin_family = AF_INET;
|
||||
inet_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
- int reuse = 1;
|
||||
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
|
||||
result = bind(listener, (const sockaddr*)&inet_address, sizeof(inet_address));
|
||||
if (result != 0) goto fail;
|
||||
listen(listener, 1);
|
||||
|
||||
// read the port that was assigned to the listener socket
|
||||
- socklen_t name_length = sizeof(inet_address);
|
||||
- result = getsockname(listener, (struct sockaddr*)&inet_address, &name_length);
|
||||
+ name_length = sizeof(inet_address);
|
||||
+ result = getsockname(listener, (struct sockaddr*)&inet_address, &name_length);
|
||||
if (result != 0) goto fail;
|
||||
|
||||
// create the first socket
|
||||
diff --git a/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp b/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp
|
||||
index 8f3c6b7a0d..3ab979ad3b 100644
|
||||
--- a/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp
|
||||
+++ b/lib/libUPnP/Neptune/Source/System/Win32/NptWin32Threads.cpp
|
||||
@@ -441,7 +441,7 @@ NPT_Win32Thread::NPT_Win32Thread(NPT_Thread* delegator,
|
||||
m_Delegator(delegator),
|
||||
m_Target(target),
|
||||
m_Detached(detached),
|
||||
- m_ThreadHandle(0),
|
||||
+ m_ThreadHandle(nullptr),
|
||||
m_ThreadId(0)
|
||||
{
|
||||
}
|
||||
@@ -567,7 +567,7 @@ NPT_Win32Thread::EntryPoint(void* argument)
|
||||
NPT_Result
|
||||
NPT_Win32Thread::Start()
|
||||
{
|
||||
- if (m_ThreadHandle > 0) {
|
||||
+ if (m_ThreadHandle != nullptr) {
|
||||
// failed
|
||||
NPT_LOG_WARNING("thread already started !");
|
||||
return NPT_ERROR_INVALID_STATE;
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
|
||||
index bae654572c..7d476d1806 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
|
||||
@@ -805,8 +805,9 @@ PLT_CtrlPoint::ProcessEventNotification(PLT_EventSubscriberReference subscriber,
|
||||
var = service->FindStateVariable(property->GetTag());
|
||||
if (var == NULL) continue;
|
||||
|
||||
- if (NPT_FAILED(var->SetValue(property->GetText()?*property->GetText():""))) {
|
||||
- NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
|
||||
+ if (NPT_FAILED(var->SetValue(property->GetText() ? property->GetText()->GetChars() : "")))
|
||||
+ {
|
||||
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
|
||||
}
|
||||
|
||||
vars.Add(var);
|
||||
@@ -1662,12 +1663,11 @@ PLT_CtrlPoint::ProcessSubscribeResponse(NPT_Result res,
|
||||
goto remove_sub;
|
||||
|
||||
failure:
|
||||
- NPT_LOG_SEVERE_4("%subscription failed of sub \"%s\" for service \"%s\" of device \"%s\"",
|
||||
- (const char*)subscription?"S":"Uns",
|
||||
- (const char*)(sid?*sid:"Unknown"),
|
||||
- (const char*)service->GetServiceID(),
|
||||
- (const char*)service->GetDevice()->GetFriendlyName());
|
||||
- res = NPT_FAILED(res)?res:NPT_FAILURE;
|
||||
+ NPT_LOG_SEVERE_4(
|
||||
+ "%subscription failed of sub \"%s\" for service \"%s\" of device \"%s\"",
|
||||
+ (const char*)subscription ? "S" : "Uns", (const char*)(sid ? sid->GetChars() : "Unknown"),
|
||||
+ (const char*)service->GetServiceID(), (const char*)service->GetDevice()->GetFriendlyName());
|
||||
+ res = NPT_FAILED(res) ? res : NPT_FAILURE;
|
||||
|
||||
remove_sub:
|
||||
// in case it was a renewal look for the subscriber with that service and remove it from the list
|
||||
@@ -1814,7 +1814,8 @@ PLT_CtrlPoint::ProcessActionResponse(NPT_Result res,
|
||||
NPT_XmlElementNode* child = (*args)->AsElementNode();
|
||||
if (!child) continue;
|
||||
|
||||
- action->SetArgumentValue(child->GetTag(), child->GetText()?*child->GetText():"");
|
||||
+ action->SetArgumentValue(child->GetTag(),
|
||||
+ child->GetText() ? child->GetText()->GetChars() : "");
|
||||
if (NPT_FAILED(res)) goto failure;
|
||||
}
|
||||
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
|
||||
index b6de5c202d..6f5f09f9cf 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
|
||||
@@ -305,11 +305,12 @@ PLT_DeviceHost::Announce(PLT_DeviceData* device,
|
||||
break;
|
||||
}
|
||||
PLT_UPnPMessageHelper::SetNTS(req, nts);
|
||||
-
|
||||
- NPT_LOG_FINER_3("Sending SSDP NOTIFY (%s) Request to %s (%s)",
|
||||
- nts.GetChars(),
|
||||
+
|
||||
+ NPT_LOG_FINER_3("Sending SSDP NOTIFY (%s) Request to %s (%s)", nts.GetChars(),
|
||||
(const char*)req.GetUrl().ToString(),
|
||||
- (const char*)(PLT_UPnPMessageHelper::GetLocation(req)?*PLT_UPnPMessageHelper::GetLocation(req):""));
|
||||
+ (const char*)(PLT_UPnPMessageHelper::GetLocation(req)
|
||||
+ ? PLT_UPnPMessageHelper::GetLocation(req)->GetChars()
|
||||
+ : ""));
|
||||
|
||||
// upnp:rootdevice
|
||||
if (device->m_ParentUUID.IsEmpty()) {
|
||||
@@ -585,14 +586,13 @@ PLT_DeviceHost::ProcessHttpPostRequest(NPT_HttpRequest& request,
|
||||
name = "ObjectID";
|
||||
}
|
||||
|
||||
- res = action->SetArgumentValue(
|
||||
- name,
|
||||
- child->GetText()?*child->GetText():"");
|
||||
+ res = action->SetArgumentValue(name, child->GetText() ? child->GetText()->GetChars() : "");
|
||||
|
||||
- // test if value was correct
|
||||
- if (res == NPT_ERROR_INVALID_PARAMETERS) {
|
||||
- action->SetError(701, "Invalid Name");
|
||||
- goto error;
|
||||
+ // test if value was correct
|
||||
+ if (res == NPT_ERROR_INVALID_PARAMETERS)
|
||||
+ {
|
||||
+ action->SetError(701, "Invalid Name");
|
||||
+ goto error;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Core/PltUtilities.h b/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
|
||||
index bdc1340173..4677f5be0e 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
|
||||
+++ b/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
|
||||
@@ -140,7 +140,8 @@ public:
|
||||
|
||||
const NPT_String* text = child->GetText();
|
||||
// DLNA 7.3.17
|
||||
- value = text?text->SubString(0, max_size):"";
|
||||
+ if (text)
|
||||
+ value = text->SubString(0, max_size);
|
||||
return NPT_SUCCESS;
|
||||
}
|
||||
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
|
||||
index feeb537648..8686aa9294 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
|
||||
@@ -401,7 +401,7 @@ PLT_MediaServer::ParseTagList(const NPT_String& updates, NPT_Map<NPT_String,NPT_
|
||||
NPT_XmlElementNode* child = (*children)->AsElementNode();
|
||||
if (!child) continue;
|
||||
const NPT_String *txt = child->GetText();
|
||||
- tags[child->GetTag()] = txt ? *txt : "";
|
||||
+ tags[child->GetTag()] = txt ? txt->GetChars() : "";
|
||||
}
|
||||
|
||||
return NPT_SUCCESS;
|
||||
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
|
||||
index 27d81fae86..794b56be17 100644
|
||||
--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
|
||||
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
|
||||
@@ -245,7 +245,7 @@ PLT_SyncMediaBrowser::OnMSStateVariablesChanged(PLT_Service* se
|
||||
if (value.GetLength()) {
|
||||
index = value.Find(',');
|
||||
update_id = (index<0)?value:value.Left(index);
|
||||
- value = (index<0)?"":value.SubString(index+1);
|
||||
+ value = (index < 0) ? "" : value.SubString(index + 1).GetChars();
|
||||
|
||||
// clear cache for that device
|
||||
if (m_UseCache) m_Cache.Clear(device->GetUUID(), item_id);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Kodi_Icon" xmlns:xodm="http://www.corel.com/coreldraw/odm/2003"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 256 256"
|
||||
style="enable-background:new 0 0 256 256;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:url(#Border_00000101104235666603682920000002035333013992593321_);}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:url(#Kodi_00000034792859328757966830000000135640982814228155_);}
|
||||
</style>
|
||||
<rect id="Boundary_Box" class="st0" width="256" height="256"/>
|
||||
<linearGradient id="Border_00000015318469695191313500000001378236376235353531_" gradientUnits="userSpaceOnUse" x1="-351.5" y1="457.5287" x2="-351.5" y2="341.4705" gradientTransform="matrix(2 0 0 -2 831 927)">
|
||||
<stop offset="0" style="stop-color:#FEFEFE"/>
|
||||
<stop offset="1" style="stop-color:#DFDFDF"/>
|
||||
</linearGradient>
|
||||
<path id="Border" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#Border_00000015318469695191313500000001378236376235353531_);" d="
|
||||
M17.3,114.9l97.6-97.6c7.2-7.2,19-7.2,26.2,0l97.6,97.6c7.2,7.2,7.2,19,0,26.2l-97.6,97.6c-7.2,7.2-19,7.2-26.2,0l-97.6-97.6
|
||||
C10.1,133.9,10.1,122.1,17.3,114.9z"/>
|
||||
<linearGradient id="Kodi_00000070798206131893957420000016692771746482146463_" gradientUnits="userSpaceOnUse" x1="-351.4952" y1="450.368" x2="-351.4952" y2="348.632" gradientTransform="matrix(2 0 0 -2 831 927)">
|
||||
<stop offset="0" style="stop-color:#33ADDD"/>
|
||||
<stop offset="1" style="stop-color:#148FBF"/>
|
||||
</linearGradient>
|
||||
<path id="Kodi" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#Kodi_00000070798206131893957420000016692771746482146463_);" d="
|
||||
M61.6,96.1c0-4.4-2.1-6.4-4-4.4l-31.3,31.3c-2.8,2.8-2.8,7.3,0,10.1l31.3,31.3c1.9,1.9,4,0,4-4.4L61.6,96.1z M152.5,123l33.6-33.6
|
||||
c2.8-2.8,7.3-2.8,10.1,0l33.6,33.6c2.8,2.8,2.8,7.3,0,10.1l-33.6,33.6c-2.8,2.8-7.3,2.8-10.1,0L152.5,133
|
||||
C149.7,130.3,149.7,125.7,152.5,123z M89.4,186.1l33.6-33.6c2.8-2.8,7.3-2.8,10.1,0l33.6,33.6c2.8,2.8,2.8,7.3,0,10.1L133,229.7
|
||||
c-2.8,2.8-7.3,2.8-10.1,0l-33.6-33.6C86.6,193.4,86.6,188.8,89.4,186.1z M88.5,65.8c0-3.5,1-6,3.4-8.5c10.4-10.4,20.7-20.7,31-31.1
|
||||
c2.8-2.8,7.3-2.8,10.1,0l33.6,33.6c2.8,2.8,2.8,7.3,0,10.1c-24.8,24.8-49.5,49.5-74.3,74.3c-1.9,1.9-3.8,0-3.8-4.4L88.5,65.8
|
||||
L88.5,65.8z"/>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Kodi_Icon" xmlns:xodm="http://www.corel.com/coreldraw/odm/2003"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 256 256"
|
||||
style="enable-background:new 0 0 256 256;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:url(#Border_00000101104235666603682920000002035333013992593321_);}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:url(#Kodi_00000034792859328757966830000000135640982814228155_);}
|
||||
</style>
|
||||
<rect id="Boundary_Box" class="st0" width="256" height="256"/>
|
||||
<linearGradient id="Border_00000015318469695191313500000001378236376235353531_" gradientUnits="userSpaceOnUse" x1="-351.5" y1="457.5287" x2="-351.5" y2="341.4705" gradientTransform="matrix(2 0 0 -2 831 927)">
|
||||
<stop offset="0" style="stop-color:#FEFEFE"/>
|
||||
<stop offset="1" style="stop-color:#DFDFDF"/>
|
||||
</linearGradient>
|
||||
<path id="Border" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#Border_00000015318469695191313500000001378236376235353531_);" d="
|
||||
M17.3,114.9l97.6-97.6c7.2-7.2,19-7.2,26.2,0l97.6,97.6c7.2,7.2,7.2,19,0,26.2l-97.6,97.6c-7.2,7.2-19,7.2-26.2,0l-97.6-97.6
|
||||
C10.1,133.9,10.1,122.1,17.3,114.9z"/>
|
||||
<linearGradient id="Kodi_00000070798206131893957420000016692771746482146463_" gradientUnits="userSpaceOnUse" x1="-351.4952" y1="450.368" x2="-351.4952" y2="348.632" gradientTransform="matrix(2 0 0 -2 831 927)">
|
||||
<stop offset="0" style="stop-color:#33ADDD"/>
|
||||
<stop offset="1" style="stop-color:#148FBF"/>
|
||||
</linearGradient>
|
||||
<path id="Kodi" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#Kodi_00000070798206131893957420000016692771746482146463_);" d="
|
||||
M61.6,96.1c0-4.4-2.1-6.4-4-4.4l-31.3,31.3c-2.8,2.8-2.8,7.3,0,10.1l31.3,31.3c1.9,1.9,4,0,4-4.4L61.6,96.1z M152.5,123l33.6-33.6
|
||||
c2.8-2.8,7.3-2.8,10.1,0l33.6,33.6c2.8,2.8,2.8,7.3,0,10.1l-33.6,33.6c-2.8,2.8-7.3,2.8-10.1,0L152.5,133
|
||||
C149.7,130.3,149.7,125.7,152.5,123z M89.4,186.1l33.6-33.6c2.8-2.8,7.3-2.8,10.1,0l33.6,33.6c2.8,2.8,2.8,7.3,0,10.1L133,229.7
|
||||
c-2.8,2.8-7.3,2.8-10.1,0l-33.6-33.6C86.6,193.4,86.6,188.8,89.4,186.1z M88.5,65.8c0-3.5,1-6,3.4-8.5c10.4-10.4,20.7-20.7,31-31.1
|
||||
c2.8-2.8,7.3-2.8,10.1,0l33.6,33.6c2.8,2.8,2.8,7.3,0,10.1c-24.8,24.8-49.5,49.5-74.3,74.3c-1.9,1.9-3.8,0-3.8-4.4L88.5,65.8
|
||||
L88.5,65.8z"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
|
@ -1,100 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Team Kodi
|
||||
* This file is part of Kodi - https://kodi.tv
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* See LICENSES/README.md for more information.
|
||||
*/
|
||||
|
||||
#include "OSScreenSaverWebOS.h"
|
||||
|
||||
#include "CompileInfo.h"
|
||||
#include "utils/JSONVariantParser.h"
|
||||
#include "utils/JSONVariantWriter.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const char* LUNA_REGISTER_SCREENSAVER =
|
||||
"luna://com.webos.service.tvpower/power/registerScreenSaverRequest";
|
||||
constexpr const char* LUNA_RESPONSE_SCREENSAVER =
|
||||
"luna://com.webos.service.tvpower/power/responseScreenSaverRequest";
|
||||
} // namespace
|
||||
|
||||
namespace KODI::WINDOWING::WAYLAND
|
||||
{
|
||||
|
||||
COSScreenSaverWebOS::~COSScreenSaverWebOS()
|
||||
{
|
||||
if (m_requestContext)
|
||||
{
|
||||
// Luna helper functions return 0 on success
|
||||
if (HUnregisterServiceCallback(m_requestContext.get()))
|
||||
CLog::LogF(LOGWARNING, "Luna request unregister failed");
|
||||
m_requestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void COSScreenSaverWebOS::Inhibit()
|
||||
{
|
||||
CVariant request;
|
||||
request["subscribe"] = true;
|
||||
request["clientName"] = CCompileInfo::GetPackage();
|
||||
std::string payload;
|
||||
CJSONVariantWriter::Write(request, payload, true);
|
||||
|
||||
m_requestContext = std::make_unique<HContext>();
|
||||
m_requestContext->pub = true;
|
||||
m_requestContext->multiple = true;
|
||||
m_requestContext->callback = &OnScreenSaverAboutToStart;
|
||||
if (HLunaServiceCall(LUNA_REGISTER_SCREENSAVER, payload.c_str(), m_requestContext.get()))
|
||||
{
|
||||
CLog::LogF(LOGWARNING, "Luna request call failed");
|
||||
if (HUnregisterServiceCallback(m_requestContext.get()))
|
||||
CLog::LogF(LOGWARNING, "Luna request unregister failed");
|
||||
m_requestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void COSScreenSaverWebOS::Uninhibit()
|
||||
{
|
||||
if (m_requestContext)
|
||||
{
|
||||
if (HUnregisterServiceCallback(m_requestContext.get()))
|
||||
CLog::LogF(LOGWARNING, "Luna request unregister failed");
|
||||
m_requestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool COSScreenSaverWebOS::OnScreenSaverAboutToStart(LSHandle* sh, LSMessage* reply, void* ctx)
|
||||
{
|
||||
CVariant request;
|
||||
const char* msg = HLunaServiceMessage(reply);
|
||||
CJSONVariantParser::Parse(msg, request);
|
||||
|
||||
CLog::LogF(LOGDEBUG, "Responded {}", msg);
|
||||
|
||||
if (request["state"] != "Active")
|
||||
return true;
|
||||
|
||||
CVariant response;
|
||||
response["clientName"] = CCompileInfo::GetPackage();
|
||||
response["ack"] = false;
|
||||
response["timestamp"] = request["timestamp"];
|
||||
std::string payload;
|
||||
CJSONVariantWriter::Write(response, payload, true);
|
||||
|
||||
HContext response_ctx;
|
||||
response_ctx.multiple = false;
|
||||
response_ctx.pub = true;
|
||||
response_ctx.callback = nullptr;
|
||||
if (HLunaServiceCall(LUNA_RESPONSE_SCREENSAVER, payload.c_str(), &response_ctx))
|
||||
{
|
||||
CLog::LogF(LOGWARNING, "Luna response call failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace KODI::WINDOWING::WAYLAND
|
||||
/*
|
||||
* Copyright (C) 2023 Team Kodi
|
||||
* This file is part of Kodi - https://kodi.tv
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* See LICENSES/README.md for more information.
|
||||
*/
|
||||
|
||||
#include "OSScreenSaverWebOS.h"
|
||||
|
||||
#include "CompileInfo.h"
|
||||
#include "utils/JSONVariantParser.h"
|
||||
#include "utils/JSONVariantWriter.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const char* LUNA_REGISTER_SCREENSAVER =
|
||||
"luna://com.webos.service.tvpower/power/registerScreenSaverRequest";
|
||||
constexpr const char* LUNA_RESPONSE_SCREENSAVER =
|
||||
"luna://com.webos.service.tvpower/power/responseScreenSaverRequest";
|
||||
} // namespace
|
||||
|
||||
namespace KODI::WINDOWING::WAYLAND
|
||||
{
|
||||
|
||||
COSScreenSaverWebOS::~COSScreenSaverWebOS()
|
||||
{
|
||||
if (m_requestContext)
|
||||
{
|
||||
// Luna helper functions return 0 on success
|
||||
if (HUnregisterServiceCallback(m_requestContext.get()))
|
||||
CLog::LogF(LOGWARNING, "Luna request unregister failed");
|
||||
m_requestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void COSScreenSaverWebOS::Inhibit()
|
||||
{
|
||||
CVariant request;
|
||||
request["subscribe"] = true;
|
||||
request["clientName"] = CCompileInfo::GetPackage();
|
||||
std::string payload;
|
||||
CJSONVariantWriter::Write(request, payload, true);
|
||||
|
||||
m_requestContext = std::make_unique<HContext>();
|
||||
m_requestContext->pub = true;
|
||||
m_requestContext->multiple = true;
|
||||
m_requestContext->callback = &OnScreenSaverAboutToStart;
|
||||
if (HLunaServiceCall(LUNA_REGISTER_SCREENSAVER, payload.c_str(), m_requestContext.get()))
|
||||
{
|
||||
CLog::LogF(LOGWARNING, "Luna request call failed");
|
||||
if (HUnregisterServiceCallback(m_requestContext.get()))
|
||||
CLog::LogF(LOGWARNING, "Luna request unregister failed");
|
||||
m_requestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void COSScreenSaverWebOS::Uninhibit()
|
||||
{
|
||||
if (m_requestContext)
|
||||
{
|
||||
if (HUnregisterServiceCallback(m_requestContext.get()))
|
||||
CLog::LogF(LOGWARNING, "Luna request unregister failed");
|
||||
m_requestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool COSScreenSaverWebOS::OnScreenSaverAboutToStart(LSHandle* sh, LSMessage* reply, void* ctx)
|
||||
{
|
||||
CVariant request;
|
||||
const char* msg = HLunaServiceMessage(reply);
|
||||
CJSONVariantParser::Parse(msg, request);
|
||||
|
||||
CLog::LogF(LOGDEBUG, "Responded {}", msg);
|
||||
|
||||
if (request["state"] != "Active")
|
||||
return true;
|
||||
|
||||
CVariant response;
|
||||
response["clientName"] = CCompileInfo::GetPackage();
|
||||
response["ack"] = false;
|
||||
response["timestamp"] = request["timestamp"];
|
||||
std::string payload;
|
||||
CJSONVariantWriter::Write(response, payload, true);
|
||||
|
||||
HContext response_ctx;
|
||||
response_ctx.multiple = false;
|
||||
response_ctx.pub = true;
|
||||
response_ctx.callback = nullptr;
|
||||
if (HLunaServiceCall(LUNA_RESPONSE_SCREENSAVER, payload.c_str(), &response_ctx))
|
||||
{
|
||||
CLog::LogF(LOGWARNING, "Luna response call failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace KODI::WINDOWING::WAYLAND
|
||||
|
|
|
|||
|
|
@ -1,38 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Team Kodi
|
||||
* This file is part of Kodi - https://kodi.tv
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* See LICENSES/README.md for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xbmc/windowing/OSScreenSaver.h"
|
||||
|
||||
#include <webos-helpers/libhelpers.h>
|
||||
|
||||
namespace KODI::WINDOWING::WAYLAND
|
||||
{
|
||||
|
||||
class COSScreenSaverWebOS : public IOSScreenSaver
|
||||
{
|
||||
public:
|
||||
~COSScreenSaverWebOS() override;
|
||||
|
||||
/**
|
||||
* Screensaver inhibition on webOS works by subscribing to the tvpower service. The service will
|
||||
* respond every few minutes with a timestamp that needs to be confirmed if the screensaver
|
||||
* should still be inhibited. If those responses are not answered the screensaver will be
|
||||
* uninhibited again
|
||||
*/
|
||||
void Inhibit() override;
|
||||
void Uninhibit() override;
|
||||
|
||||
private:
|
||||
static bool OnScreenSaverAboutToStart(LSHandle* sh, LSMessage* reply, void* ctx);
|
||||
|
||||
std::unique_ptr<HContext> m_requestContext;
|
||||
};
|
||||
|
||||
} // namespace KODI::WINDOWING::WAYLAND
|
||||
/*
|
||||
* Copyright (C) 2023 Team Kodi
|
||||
* This file is part of Kodi - https://kodi.tv
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* See LICENSES/README.md for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xbmc/windowing/OSScreenSaver.h"
|
||||
|
||||
#include <webos-helpers/libhelpers.h>
|
||||
|
||||
namespace KODI::WINDOWING::WAYLAND
|
||||
{
|
||||
|
||||
class COSScreenSaverWebOS : public IOSScreenSaver
|
||||
{
|
||||
public:
|
||||
~COSScreenSaverWebOS() override;
|
||||
|
||||
/**
|
||||
* Screensaver inhibition on webOS works by subscribing to the tvpower service. The service will
|
||||
* respond every few minutes with a timestamp that needs to be confirmed if the screensaver
|
||||
* should still be inhibited. If those responses are not answered the screensaver will be
|
||||
* uninhibited again
|
||||
*/
|
||||
void Inhibit() override;
|
||||
void Uninhibit() override;
|
||||
|
||||
private:
|
||||
static bool OnScreenSaverAboutToStart(LSHandle* sh, LSMessage* reply, void* ctx);
|
||||
|
||||
std::unique_ptr<HContext> m_requestContext;
|
||||
};
|
||||
|
||||
} // namespace KODI::WINDOWING::WAYLAND
|
||||
|
|
|
|||