././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8783603 python-gammu-3.2.4/0000755000175000017500000000000000000000000013132 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/AUTHORS0000644000175000017500000000014600000000000014203 0ustar00nijelnijelMichal Čihař Marcin Wiącek ...and many other contributors. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1464094489.0 python-gammu-3.2.4/COPYING0000644000175000017500000004325400000000000014175 0ustar00nijelnijel GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1429000287.0 python-gammu-3.2.4/MANIFEST.in0000644000175000017500000000036000000000000014667 0ustar00nijelnijelinclude AUTHORS include COPYING include README.rst include NEWS.rst include include/*.h recursive-include examples *.py recursive-include test *.py recursive-include test/data/gammu-dummy * include test/data/*.* include examples/data/*.jpg ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134933.0 python-gammu-3.2.4/NEWS.rst0000644000175000017500000000331500000000000014442 0ustar00nijelnijel3.2.4 ===== * Compatibility with Python 3.10. 3.2.3 ===== * Fixed uninitalized memory usage in DeleteSMS. 3.2.2 ===== * Fixed metadata in published wheels. * Avoid using some of deprecated Python APIs. 3.2.1 ===== * Reintroduced 32-bit wheels for Windows. 3.2 === * Add support for polling on the async worker * Utilize CI on GitHub * Modernize codebase using pyupgrade, isort and black 3.1 === * Fix an issue where the gammu worker thread could be brought down if a callback throws an exception 3.0 === * Add support for asyncio in the gammu worker * Dropped support for Python 2. * Windows binaries built with Gammu 1.41.0. 2.12 ==== * Windows binaries built with Gammu 1.40.0. 2.11 ==== * Add support for the USSD in SMSD. * Python 2.7 binaries available for Windows. 2.10 ==== * Testsuite compatibility with Gammu 1.38.5. 2.9 === * Fixed compilation under Windows. 2.8 === * Make parameters to CancelCall and AnswerCall optional. * Added support for UTF-16 Unicode chars (emojis). 2.7 === * Needs Gammu >= 1.37.90 due to API changes. 2.6 === * Fixed error when creating new contact. * Fixed possible testsuite errors. 2.5 === * Compatibility with Gammu >= 1.36.7 2.4 === * Fixed possible crash when initializing SMSD with invalid parameters. * Fixed crash on handling diverts on certain architectures. 2.3 === * License changed tp GPL version 2 or later. * Documentation improvements. 2.2 === * Documentation improvements. * Code cleanups. 2.1 === * Include data required for tests in tarball. * Include NEWS.rst in tarball. * Fixed possible crash when changing debug file. * Fixed various errors found by coverity. 2.0 === * Separate Python module. * Compiles using distutils. * Support Python 3. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8783603 python-gammu-3.2.4/PKG-INFO0000644000175000017500000001072200000000000014231 0ustar00nijelnijelMetadata-Version: 2.1 Name: python-gammu Version: 3.2.4 Summary: Gammu bindings Home-page: https://wammu.eu/python-gammu/ Author: Michal Cihar Author-email: michal@cihar.com License: GPLv2+ Download-URL: https://wammu.eu/download/python-gammu/ Keywords: mobile,phone,SMS,contact,gammu,calendar,todo Platform: Linux Platform: Mac OSX Platform: Windows XP/2000/NT Platform: Windows 95/98/ME Classifier: Development Status :: 6 - Mature Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Telecommunications Industry Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+) Classifier: Operating System :: MacOS Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: Unix Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Communications :: Telephony Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Hardware Requires-Python: >=3.6 Description-Content-Type: text/x-rst License-File: COPYING License-File: AUTHORS python-gammu ============ Python bindings for the `Gammu library `_. .. image:: https://github.com/gammu/python-gammu/actions/workflows/test.yml/badge.svg :target: https://github.com/gammu/python-gammu/actions/workflows/test.yml .. image:: https://api.codacy.com/project/badge/Grade/c7e87df480fb4609aa48482873f5c46b :target: https://www.codacy.com/app/Gammu/python-gammu .. image:: https://coveralls.io/repos/gammu/python-gammu/badge.svg :target: https://coveralls.io/r/gammu/python-gammu .. image:: https://scan.coverity.com/projects/4837/badge.svg :target: https://scan.coverity.com/projects/4837 .. image:: https://img.shields.io/liberapay/receives/Gammu.svg :alt: Liberapay :target: https://liberapay.com/Gammu/donate .. image:: https://www.bountysource.com/badge/team?team_id=23177&style=bounties_received :alt: Bountysource :target: https://www.bountysource.com/teams/gammu/issues?utm_source=Gammu&utm_medium=shield&utm_campaign=bounties_received .. image:: https://img.shields.io/pypi/v/python-gammu.svg :alt: PyPI :target: https://pypi.python.org/pypi/python-gammu/ Homepage ======== License ======= Copyright (C) 2003 - 2018 Michal Cihar This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Installing ========== You can install in a usual way for Python modules using distutils, so use ``setup.py`` which is placed in the top level directory:: ./setup.py build sudo ./setup.py install You can also install it using pip installer:: pip install python-gammu Requirements ============ To compile python-gammu, you need Gammu development files (usually shipped as ``libgammu-dev`` or ``gammu-devel`` in Linux distributions). The location of the libraries is discovered using ``pkg-config``, ``GAMMU_PATH`` environment variable and falls back to generic locations. In case it does not work, either install ``pkg-config`` or set ``GAMMU_PATH``. On Linux something like this should work:: GAMMU_PATH=/opt/gammu python setup.py build On Windows:: SET GAMMU_PATH="C:\Gammu" python setup.py build Documentation ============= Please see included python documentation:: >>> import gammu >>> help(gammu) Alternatively you can use Sphinx to generate browsable version, which is also available on-line at . Feedback and bug reports ======================== Any feedback is welcome, see for information how to contact developers. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628838869.0 python-gammu-3.2.4/README.rst0000644000175000017500000000614400000000000014626 0ustar00nijelnijelpython-gammu ============ Python bindings for the `Gammu library `_. .. image:: https://github.com/gammu/python-gammu/actions/workflows/test.yml/badge.svg :target: https://github.com/gammu/python-gammu/actions/workflows/test.yml .. image:: https://api.codacy.com/project/badge/Grade/c7e87df480fb4609aa48482873f5c46b :target: https://www.codacy.com/app/Gammu/python-gammu .. image:: https://coveralls.io/repos/gammu/python-gammu/badge.svg :target: https://coveralls.io/r/gammu/python-gammu .. image:: https://scan.coverity.com/projects/4837/badge.svg :target: https://scan.coverity.com/projects/4837 .. image:: https://img.shields.io/liberapay/receives/Gammu.svg :alt: Liberapay :target: https://liberapay.com/Gammu/donate .. image:: https://www.bountysource.com/badge/team?team_id=23177&style=bounties_received :alt: Bountysource :target: https://www.bountysource.com/teams/gammu/issues?utm_source=Gammu&utm_medium=shield&utm_campaign=bounties_received .. image:: https://img.shields.io/pypi/v/python-gammu.svg :alt: PyPI :target: https://pypi.python.org/pypi/python-gammu/ Homepage ======== License ======= Copyright (C) 2003 - 2018 Michal Cihar This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Installing ========== You can install in a usual way for Python modules using distutils, so use ``setup.py`` which is placed in the top level directory:: ./setup.py build sudo ./setup.py install You can also install it using pip installer:: pip install python-gammu Requirements ============ To compile python-gammu, you need Gammu development files (usually shipped as ``libgammu-dev`` or ``gammu-devel`` in Linux distributions). The location of the libraries is discovered using ``pkg-config``, ``GAMMU_PATH`` environment variable and falls back to generic locations. In case it does not work, either install ``pkg-config`` or set ``GAMMU_PATH``. On Linux something like this should work:: GAMMU_PATH=/opt/gammu python setup.py build On Windows:: SET GAMMU_PATH="C:\Gammu" python setup.py build Documentation ============= Please see included python documentation:: >>> import gammu >>> help(gammu) Alternatively you can use Sphinx to generate browsable version, which is also available on-line at . Feedback and bug reports ======================== Any feedback is welcome, see for information how to contact developers. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8663602 python-gammu-3.2.4/examples/0000755000175000017500000000000000000000000014750 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534398.0 python-gammu-3.2.4/examples/__init__.py0000644000175000017500000000155400000000000017066 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534554.0 python-gammu-3.2.4/examples/addcontacts.py0000755000175000017500000000270600000000000017621 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu def main(): if len(sys.argv) != 3: print("This requires two parameters: memory_type and backup file (eg. vcard)!") sys.exit(1) state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() memory = sys.argv[1] filename = sys.argv[2] backup = gammu.ReadBackup(filename) for item in backup["PhonePhonebook"]: item["MemoryType"] = memory loc = state_machine.AddMemory(item) print(f"Added item to location {loc:d}") if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/addfile.py0000755000175000017500000000337300000000000016723 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import os import sys import gammu def main(): if len(sys.argv) != 3: print("This requires two parameters: file to upload and path!") sys.exit(1) with open(sys.argv[1], "rb") as handle: data = handle.read() state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() # Check AddFilePart print("\n\nExpection: Put specified file onto Memorycard on phone") file_f = { "ID_FullName": sys.argv[2], "Name": os.path.basename(sys.argv[1]), "Buffer": data, "Protected": 0, "ReadOnly": 0, "Hidden": 0, "System": 0, "Finished": 0, "Folder": 0, "Level": 0, "Type": "Other", "Pos": 0, } while not file_f["Finished"]: file_f = state_machine.AddFilePart(file_f) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/async.py0000644000175000017500000000706200000000000016444 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ python-gammu - Phone communication libary Gammu asynchronous wrapper example with asyncio. This allows your application to care only about handling received data and not about phone communication details. """ import asyncio import sys import gammu import gammu.asyncworker async def send_message_async(state_machine, number, message): smsinfo = { "Class": -1, "Unicode": False, "Entries": [{"ID": "ConcatenatedTextLong", "Buffer": message}], } # Encode messages encoded = gammu.EncodeSMS(smsinfo) # Send messages for message in encoded: # Fill in numbers message["SMSC"] = {"Location": 1} message["Number"] = number # Actually send the message await state_machine.send_sms_async(message) async def get_network_info(worker): info = await worker.get_network_info_async() print("NetworkName:", info["NetworkName"]) print(" State:", info["State"]) print(" NetworkCode:", info["NetworkCode"]) print(" CID:", info["CID"]) print(" LAC:", info["LAC"]) async def get_info(worker): print("Phone infomation:") manufacturer = await worker.get_manufacturer_async() print("{:<15}: {}".format("Manufacturer", manufacturer)) model = await worker.get_model_async() print("{:<15}: {} ({})".format("Model", model[0], model[1])) imei = await worker.get_imei_async() print("{:<15}: {}".format("IMEI", imei)) firmware = await worker.get_firmware_async() print("{:<15}: {}".format("Firmware", firmware[0])) async def main(): gammu.SetDebugFile(sys.stderr) gammu.SetDebugLevel("textall") config = dict(Device="/dev/ttyS6", Connection="at") worker = gammu.asyncworker.GammuAsyncWorker() worker.configure(config) try: await worker.init_async() await get_info(worker) await get_network_info(worker) await send_message_async(worker, "6700", "BAL") # Just a busy waiting for event # We need to keep communication with phone to get notifications print("Press Ctrl+C to interrupt") while 1: try: signal = await worker.get_signal_quality_async() print("Signal is at {:d}%".format(signal["SignalPercent"])) except Exception as e: print(f"Exception reading signal: {e}") await asyncio.sleep(10) except Exception as e: print("Exception:") print(e) print("Terminate Start") await worker.terminate_async() print("Terminate Done") if __name__ == "__main__": event_loop = asyncio.get_event_loop() try: event_loop.run_until_complete(main()) finally: event_loop.close() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/backup_convertor.py0000755000175000017500000000217500000000000020700 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu if len(sys.argv) != 3: print( "This requires two parameter with file names!" " First is input, second output." ) sys.exit(1) backup = gammu.ReadBackup(sys.argv[1]) gammu.SaveBackup(sys.argv[2], backup) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534398.0 python-gammu-3.2.4/examples/batteryinfo.py0000755000175000017500000000232500000000000017655 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu state_machine = gammu.StateMachine() if len(sys.argv) > 2: state_machine.ReadConfig(Filename=sys.argv[1]) del sys.argv[1] else: state_machine.ReadConfig() state_machine.Init() status = state_machine.GetBatteryCharge() for x in status: if status[x] != -1: print(f"{x:20}: {status[x]}") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8663602 python-gammu-3.2.4/examples/data/0000755000175000017500000000000000000000000015661 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/examples/data/cgi.jpg0000644000175000017500000002406600000000000017135 0ustar00nijelnijelJFIFHH    Z,"  # !"!%'$ '!!    }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? ? <%ywo \hr4T9 fb$I'k1MoQcH_t9?S KE>= (Oo'5G)O'k"(1MoQ c L|6}?[˜mD_&+9?S KE>= (Oo'5G)O|%k"(1MoQ c G˜mD_&(1MoWYEr>= ?L|6{/[Q@U/ zS]ZJϘ`OJOh?<Ie]jmjEi<28Z?g]KOGO/28Cѐryq\oZ i|!}SF[]2WpR vQP'OÛO+KϴOy܏ۻjxDŽ,>jϱf zuþ1 :k. nSY70^O9 eyb8  /l?~P%^e;lFq # ZӼ [Wm?_5+/惜|@$~3Υ4$keUu@R 9 Ï;=^_G[Rƥf pbHĥλ2=sU_AӦu_x"5Ηmqfeg | :E4Oٷmng瀈7sb|k~!H6>Qgz^fRoxB1y +мEk^ |1iIw_[ ؞n.& b d &W$F<mM'N坾4RF&0e8pAp^A]ZL|6{/[?o|Ym sy:/NX6ݸ#T˜mD_&(1MoWYEr>= ?L|6{/[Q@)O|%k"S KEuP' c ?m_ Yhj$R66 38P3}_~ޟWC __NW'cH_t ( ( ( (1Wo;zeɷ{z{Iլ56 KK7<.z+7F٧jwז3o5r<v1]ÿi <a*I䵲V 0.YU̓,׻c*MB(w~: %=G %.2u99 u5i:c)kEeF̈́i#%PP? 6Z3Ci#R:v X?%I};%'KH>lJF"A \xAw}s>]ONw}F@8_xFdi\gkrk,h(W*;I)m+C)\<,| $iApHqmğS\iEi Pi4vHT b cY;7zENɩ!m;H;"#)*pʌyS_Ӵ-*[0gxZB>epGёN 9 95;R)/o6%Rphu7UOC¾ SKu`6A%%ftB`tGyջV Bo%ei+B+G`A`-7u]O#J!ɷ,V0u16C|7/o~#ͮD#OխuK6}G -Lsn$O*@:[@czKZJ&*#w\ʬYpr s_إ힫q vq/(\[qY~A{AMUsijwSˮ_JmLJmpo,31a?ڧ\/焥ncv<xKTβ]/,SQ[{I-\'Hі(A[^%V5YDQ1m%ijHA!8՝ “W?<]<kz'4Ũ[Mi,JB)[ȆPO@_/57m2],1 btGh⍹TJ-j>_$gtSh܍6Sʐr8:_zsiq#,\G4t7_ݒFcri _no,+m^(7n2p&]9_Ězq&-ֈ@<ji0W*\ \ yj~8|%mW$Ieqy^58h(mY\97@<4ڵwQ]]L.N'M ?V4wRt嶸[oD $?J,I{6dbwAD"e޹e]9'}8hzV}ZΓ[s2UPɆN5tQEWğ+=}_cH_t?GbuQEl˥|"]lm38{*d޸ Cm&&A-ؠ0!]6q'8l-HIöĶ7ӿkA2:VkěZPoH<B~$<k1ohZʹ$R)nG9Uu xKwhzFs:Ko1 x,zr<{LuA%; /Fdpq_+~ދQIsxV''Ҝ-)+SF\܎Ǿ /_xJ}suk=BF_` Vao#ax#רĠ AwSԬ$J^D*7'UvN:cQ~kNYk3G$v cxkDzЮHe -H$ʪ-[XѦhKxhtB : x8^یʧ y ,iv%伵3}mWޢ9[Λ.C@5|2M6jO>W~}1t;y->,YӺ[VS:QѤ-܈o79m+_[.$KѦ3A{&Dh/=9due=#& xj]ɥIyGAb);=]|ѵ+eM W+^x^Cִ:8?E(/3U8cشgwNn=ZLGF@Or $n1xPel&Ǿ|_{bcv⯂^)riw^kvjzXEd_4mFacUӤhfѵFY{౷XRXݶΎer?˵X 5iשiױ; }TYy49,)$#bٷW=]S>2om$+@rs!鑀2$ *9[*ӛAET!EPJ:gMo{K{U2H7`yϔ9Yn|9ZnK_kXv<"Xx`"KgL|lf-;dc$HeШ|ciW@O.5;>}&my%A,b@}S?e 63ϒ6m~͜AybV +KMJk[Rr2J%W䉖&o$n@ʤk;^ b][ By)"cǁhgq9?m?#UkjYdG܀v M34;XF Wbn`fhqu  ,jt}3ᕯLG[nSEF"T88M J*MM]jЛo5db|LdAkoT𭖭ɈBbd${譖H<i@ᓮi[6u. Eэ@$Y lGR/'ŭZ~[neަ67+9*kJNkN}pWET(Uc?E=,>+u}_^nnk[ĩ4,H%$?^!>M\.Mpг-,|eߛ0G0k_*K ^·K ~M"1$@d"Nox4kYKWypn'獗arwɎփug-Ρ!,ͫmWOhã ߝ r|vѵk8n4ViotcWY/{3vklp!/^<:ǧwWdVf7h%bp9( .%0FtJ[M5i+*%M33K! ܳ;Al e<=^t'M G[0XA(aMn@+<?nV/G.:}ʰm,iY:|?NΚγwc:Fq$FO&6{c؍{?ŏ~ o.$)Qhe!L*U$J` xĚOTGԯ-m^bO.6 ;T=Mg-LS.#ҭirŧ]Ͳ|@/d;z1xCUԺ~%4 f`y ޷Zii1[M#iz!+1*d܄p H5W'o6>5 N[Tnmek$*GJcF8'($?_G_mğ+Gbu=+((o[[Y5OkF|g`Os^E4؉ӌդyZԮSԾ,xԌXBrEuco2ZoJslx⟉|S?j4FÈB'# ª+B6x>KǞ'uׅ)aNj'ӣPe-Ebㅌ _jviQTSF95{D#hyFWIJ#A^]kGt -ąA[ʕ$r68''*mqy"B:Q > jm&Ėdy-MٌQO*:K"D_RG݅r@# m_W.IGmpҠq)Pv jb</Os~$ɒ[+=B]>#.<͹m |+2o hnbi2o+8 ,1VܼVQEQE'%J?>zn$?_G@W=+]?Ϗk+?xC Z葢UC`8tEſ9'sq Oӊ+?ğ(>-G.?P|[.?N(\7]$Aon?81sItEſ9'sq Oӊ+?ğ(>-G.?P|[.?N(\7]$Aon?81sItEſ9'sq Oӊ+?ğ(>-G.?P|[.?N(\7]$Aon?81sItEſ9'sq Oӊ+?ğ(>-G.?P|[.?N(\7]$Aon?81sItEſ9'sq Oӊ=y.?P|[. # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu def main(): # Global debug level gammu.SetDebugFile(sys.stderr) gammu.SetDebugLevel("textall") state_machine = gammu.StateMachine() state_machine.ReadConfig() # Use global debug stub regardless configuration c = state_machine.GetConfig(0) c["UseGlobalDebugFile"] = True state_machine.SetConfig(0, c) state_machine.Init() manufacturer = state_machine.GetManufacturer() model = state_machine.GetModel() imei = state_machine.GetIMEI() firmware = state_machine.GetFirmware() print("Phone infomation:") print("{:<15}: {}".format("Manufacturer", manufacturer)) print("{:<15}: {} ({})".format("Model", model[0], model[1])) print("{:<15}: {}".format("IMEI", imei)) print("{:<15}: {}".format("Firmware", firmware[0])) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/dialvoice.py0000755000175000017500000000260400000000000017266 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu # Create object for talking with phone state_machine = gammu.StateMachine() # Read the configuration (~/.gammurc or from command line) if len(sys.argv) > 2: state_machine.ReadConfig(Filename=sys.argv[1]) del sys.argv[1] else: state_machine.ReadConfig() # Connect to the phone state_machine.Init() # Check whether we have a number to dial if len(sys.argv) != 2: print("Usage: dialvoice.py NUMBER") sys.exit(1) # Dial a number state_machine.DialVoice(sys.argv[1]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/doc-exceptions.py0000755000175000017500000000230700000000000020253 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import gammu.exception def main(): for exc in sorted(gammu.exception.__all__): print(f".. exception:: gammu.{exc}") print() doc = getattr(gammu.exception, exc).__doc__ for doc in doc.splitlines(): print(f" {doc}") print() if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/examples/dummy_phone.py0000755000175000017500000001445700000000000017664 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ python-gammu - Test script to test several Gammu operations (usually using dummy driver, but it depends on config) """ import sys import gammu def get_all_memory(state_machine, memory_type): status = state_machine.GetMemoryStatus(Type=memory_type) remain = status["Used"] start = True while remain > 0: if start: entry = state_machine.GetNextMemory(Start=True, Type=memory_type) start = False else: entry = state_machine.GetNextMemory( Location=entry["Location"], Type=memory_type ) remain = remain - 1 print() print("{:<15}: {:d}".format("Location", entry["Location"])) for v in entry["Entries"]: if v["Type"] in ("Photo"): print("{:<15}: {}...".format(v["Type"], repr(v["Value"])[:30])) else: print("{:<15}: {}".format(v["Type"], v["Value"])) def get_all_calendar(state_machine): status = state_machine.GetCalendarStatus() remain = status["Used"] start = True while remain > 0: if start: entry = state_machine.GetNextCalendar(Start=True) start = False else: entry = state_machine.GetNextCalendar(Location=entry["Location"]) remain = remain - 1 print() print("{:<20}: {:d}".format("Location", entry["Location"])) print("{:<20}: {}".format("Type", entry["Type"])) for v in entry["Entries"]: print("{:<20}: {}".format(v["Type"], v["Value"])) def get_battery_status(state_machine): status = state_machine.GetBatteryCharge() for x in status: if status[x] != -1: print(f"{x:20}: {status[x]}") def get_all_sms(state_machine): status = state_machine.GetSMSStatus() remain = status["SIMUsed"] + status["PhoneUsed"] + status["TemplatesUsed"] start = True while remain > 0: if start: sms = state_machine.GetNextSMS(Start=True, Folder=0) start = False else: sms = state_machine.GetNextSMS(Location=sms[0]["Location"], Folder=0) remain = remain - len(sms) return sms def print_sms_header(message, folders): print() print("{:<15}: {}".format("Number", message["Number"])) print("{:<15}: {}".format("Date", message["DateTime"])) print("{:<15}: {}".format("State", message["State"])) print( "{:<15}: {} {} ({:d})".format( "Folder", folders[message["Folder"]]["Name"], folders[message["Folder"]]["Memory"], message["Folder"], ) ) print("{:<15}: {}".format("Validity", message["SMSC"]["Validity"])) def print_all_sms(sms, folders): for m in sms: print_sms_header(m, folders) print("\n{}".format(m["Text"])) def link_all_sms(sms, folders): data = gammu.LinkSMS([[msg] for msg in sms]) for x in data: v = gammu.DecodeSMS(x) m = x[0] print_sms_header(m, folders) loc = [] for m in x: loc.append(m["Location"]) print("{:<15}: {}".format("Location(s)", ", ".join(loc))) if v is None: print("\n{}".format(m["Text"])) else: for e in v["Entries"]: print() print("{:<15}: {}".format("Type", e["ID"])) if e["Bitmap"] is not None: for bmp in e["Bitmap"]: print("Bitmap:") for row in bmp["XPM"][3:]: print(row) print() if e["Buffer"] is not None: print("Text:") print(e["Buffer"]) print() def get_all_todo(state_machine): status = state_machine.GetToDoStatus() remain = status["Used"] start = True while remain > 0: if start: entry = state_machine.GetNextToDo(Start=True) start = False else: entry = state_machine.GetNextToDo(Location=entry["Location"]) remain = remain - 1 print() print("{:<15}: {:d}".format("Location", entry["Location"])) print("{:<15}: {}".format("Priority", entry["Priority"])) for v in entry["Entries"]: print("{:<15}: {}".format(v["Type"], v["Value"])) def get_sms_folders(state_machine): folders = state_machine.GetSMSFolders() for i, folder in enumerate(folders): print("Folder {:d}: {} ({})".format(i, folder["Name"], folder["Memory"])) return folders def get_set_date_time(state_machine): dt = state_machine.GetDateTime() print(dt) state_machine.SetDateTime(dt) return dt def main(): if len(sys.argv) != 2: print("This requires one parameter with location of config file!") sys.exit(1) state_machine = gammu.StateMachine() state_machine.ReadConfig(Filename=sys.argv[1]) state_machine.Init() smsfolders = get_sms_folders(state_machine) get_all_memory(state_machine, "ME") get_all_memory(state_machine, "SM") get_all_memory(state_machine, "MC") get_all_memory(state_machine, "RC") get_all_memory(state_machine, "DC") get_battery_status(state_machine) get_all_calendar(state_machine) get_all_todo(state_machine) smslist = get_all_sms(state_machine) print_all_sms(smslist, smsfolders) link_all_sms(smslist, smsfolders) get_set_date_time(state_machine) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/examples/filesystem_test.py0000755000175000017500000002445300000000000020560 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Matthias Blaesing # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ This file should provide me with a test frame for the filesystem functions. It can't be run automatically, but you should be able to decide, wheather the output looks sensible BEWARE - the test WILL TOUCH AND WRITE FILESYSTEM!! I asume you call the script from the directory were it lays and have the grafic there and you have write permission there and that there is a file called cgi.jpg to be used as test file READY: - DeleteFile - AddFilePart - GetFilePart - GetNextRootFolder - GetNextFileFolder - GetFolderListing - SetFileAttributes - DeleteFolder - GetFileSystemStatus - AddFolder """ import argparse import datetime import os import sys import gammu def main(): parser = argparse.ArgumentParser(usage="usage: %(prog)s [options]") parser.add_argument( "-c", "--config", action="store", type=str, dest="config", default=None, help="Config file path", ) parser.add_argument( "-f", "--folder", action="store", type=str, dest="folder", default=None, help="Folder to be used for testing", ) parser.add_argument( "-t", "--test-file", action="store", type=str, dest="testfile", default="./data/cgi.jpg", help="Local file to be used for testing", ) args = parser.parse_args() if args.folder is None: print("You have to select folder where testing will be done!") print("And even better, you should read the script before you run it.") sys.exit(1) if not os.path.exists(args.testfile): print("You have to select file which will be used for testing!") sys.exit(1) state_machine = gammu.StateMachine() if args.config is not None: state_machine.ReadConfig(Filename=args.config) else: state_machine.ReadConfig() state_machine.Init() # Check GetFileSystemStatus print("Expection: Info about filesystem usage") try: fs_info = state_machine.GetFileSystemStatus() fs_info["Total"] = fs_info["Free"] + fs_info["Used"] print("Used: {Used:d}, Free: {Free:d}, Total: {Total:d}".format(**fs_info)) except gammu.ERR_NOTSUPPORTED: print("You will have to live without this knowledge") # Check DeleteFile print("\n\nExpection: Deleting cgi.jpg from memorycard") try: state_machine.DeleteFile(unicode(args.folder + "/cgi.jpg")) except gammu.ERR_FILENOTEXIST: print("Oh well - we copy it now ;-) (You SHOULD read this)") # Check AddFilePart print("\n\nExpection: Put cgi.jpg onto Memorycard on phone") file_handle = open(args.testfile, "rb") file_stat = os.stat(args.testfile) ttime = datetime.datetime.fromtimestamp(file_stat[8]) file_f = { "ID_FullName": args.folder, "Name": "cgi.jpg", "Modified": ttime, "Folder": 0, "Level": 1, "Used": file_stat[6], "Buffer": file_handle.read(), "Type": "Other", "Protected": 0, "ReadOnly": 0, "Hidden": 0, "System": 0, "Handle": 0, "Pos": 0, "Finished": 0, } while not file_f["Finished"]: file_f = state_machine.AddFilePart(file_f) # Check GetFilePart print("\n\nExpection: Get cgi.jpg from memorycard and write it as test.jpg") with open("./test.jpg", "wb") as handle: file_f = {"ID_FullName": args.folder + "/cgi.jpg", "Finished": 0} while not file_f["Finished"]: file_f = state_machine.GetFilePart(file_f) handle.write(file_f["Buffer"]) handle.flush() # Check correct transfer print("\n\nExpection: test.jpg and cgi.jpg to be the same") f1 = open(args.testfile, "rb") f2 = open("./test.jpg", "rb") if f1.read() == f2.read(): print("Same files") else: print("Files differ!") os.remove("./test.jpg") # Check GetNextRootFolder print("\n\nExpection: Root Folder List") try: file_obj = state_machine.GetNextRootFolder("") while 1: print(file_obj["ID_FullName"] + " - " + file_obj["Name"]) try: file_obj = state_machine.GetNextRootFolder(file_obj["ID_FullName"]) except gammu.ERR_EMPTY: break except gammu.ERR_NOTSUPPORTED: print("Not supported...") # Check GetNextFileFolder print("\n\nExpection: Info for a file of the phone (cgi.jpg)") file_f = state_machine.GetNextFileFolder(1) while 1: if file_f["Name"] != "cgi.jpg": file_f = state_machine.GetNextFileFolder(0) else: attribute = "" if file_f["Protected"]: attribute = attribute + "P" if file_f["ReadOnly"]: attribute = attribute + "R" if file_f["Hidden"]: attribute = attribute + "H" if file_f["System"]: attribute = attribute + "S" print( "ID: " + file_f["ID_FullName"] + "\n" + "Name: " + file_f["Name"] + "\n" + "Folder: " + str(file_f["Folder"]) + "\n" + "Used: " + str(file_f["Used"]) + "\n" + "Modified: " + file_f["Modified"].strftime("%x %X") + "\n" + "Type: " + file_f["Type"] + "\n" + "Level: " + str(file_f["Level"]) + "\n" + "Attribute: " + attribute ) break # Check SetFileAttributes # Protected is spared, as my mobile nokia 6230i says it's unsupported print( "\n\nExpection: Modifying attributes " "(readonly=1, protected=0, system=1, hidden=1)" ) state_machine.SetFileAttributes(unicode(args.folder + "/cgi.jpg"), 1, 0, 1, 1) # Check GetFolderListing print("\n\nExpection: Listing of cgi.jpg's properties") file_f = state_machine.GetFolderListing(unicode(args.folder), 1) while 1: if file_f["Name"] != "cgi.jpg": file_f = state_machine.GetFolderListing(unicode(args.folder), 0) else: attribute = "" if file_f["Protected"]: attribute = attribute + "P" if file_f["ReadOnly"]: attribute = attribute + "R" if file_f["Hidden"]: attribute = attribute + "H" if file_f["System"]: attribute = attribute + "S" print( "ID: " + file_f["ID_FullName"] + "\n" + "Name: " + file_f["Name"] + "\n" + "Folder: " + str(file_f["Folder"]) + "\n" + "Used: " + str(file_f["Used"]) + "\n" + "Modified: " + file_f["Modified"].strftime("%x %X") + "\n" + "Type: " + file_f["Type"] + "\n" + "Level: " + str(file_f["Level"]) + "\n" + "Attribute: " + attribute ) break # Check DeleteFile print("\n\nExpection: Deletion of cgi.jpg from memorycard") try: state_machine.DeleteFile(unicode(args.folder + "cgi.jpg")) print("Deleted") except gammu.ERR_FILENOTEXIST: print("Something is wrong ...") # Check AddFolder print('\n\nExpection: Creation of a folder on the memorycard "42alpha"') state_machine.AddFolder(unicode(args.folder), "42alpha") # Check GetFolderListing again *wired* print("\n\nExpection: Print properties of newly created folder") file_f = state_machine.GetFolderListing(unicode(args.folder), 1) while 1: if file_f["Name"] != "42alpha": file_f = state_machine.GetFolderListing(unicode(args.folder), 0) else: attribute = "" if file_f["Protected"]: attribute = attribute + "P" if file_f["ReadOnly"]: attribute = attribute + "R" if file_f["Hidden"]: attribute = attribute + "H" if file_f["System"]: attribute = attribute + "S" print( "ID: " + file_f["ID_FullName"] + "\n" + "Name: " + file_f["Name"] + "\n" + "Folder: " + str(file_f["Folder"]) + "\n" + "Used: " + str(file_f["Used"]) + "\n" + "Modified: " + file_f["Modified"].strftime("%x %X") + "\n" + "Type: " + file_f["Type"] + "\n" + "Level: " + str(file_f["Level"]) + "\n" + "Attribute: " + attribute ) break # Check DeleteFolder print('\n\nExpection: Deletion of previously created folder "42alpha"') state_machine.DeleteFolder(unicode(args.folder + "/42alpha")) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/getallcalendar.py0000755000175000017500000000332300000000000020270 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """Example for reading calendar from phone""" import gammu # Create object for talking with phone state_machine = gammu.StateMachine() # Read the configuration (~/.gammurc) state_machine.ReadConfig() # Connect to the phone state_machine.Init() # Get number of calendar entries status = state_machine.GetCalendarStatus() remain = status["Used"] start = True while remain > 0: # Read the entry if start: entry = state_machine.GetNextCalendar(Start=True) start = False else: entry = state_machine.GetNextCalendar(Location=entry["Location"]) remain = remain - 1 # Display it print() print("{:<20}: {:d}".format("Location", entry["Location"])) print("{:<20}: {}".format("Type", entry["Type"])) for v in entry["Entries"]: print("{:<20}: {}".format(v["Type"], str(v["Value"]))) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/getallmemory.py0000755000175000017500000000344100000000000020030 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu def main(): state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() if len(sys.argv) != 2: print("This requires one parameter with memory type!") sys.exit(1) memory_type = sys.argv[1] status = state_machine.GetMemoryStatus(Type=memory_type) remain = status["Used"] start = True while remain > 0: if start: entry = state_machine.GetNextMemory(Start=True, Type=memory_type) start = False else: entry = state_machine.GetNextMemory( Location=entry["Location"], Type=memory_type ) remain = remain - 1 print() print("{:<15}: {:d}".format("Location", entry["Location"])) for v in entry["Entries"]: print("{:<15}: {}".format(v["Type"], str(v["Value"]))) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/getallmemory_nonext.py0000755000175000017500000000333700000000000021427 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu def main(): state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() if len(sys.argv) != 2: print("This requires one parameter with memory type!") sys.exit(1) memory_type = sys.argv[1] status = state_machine.GetMemoryStatus(Type=memory_type) remain = status["Used"] location = 1 while remain > 0: try: entry = state_machine.GetMemory(Type=memory_type, Location=location) print() print("{:<15}: {:d}".format("Location", entry["Location"])) for v in entry["Entries"]: print("{:<15}: {}".format(v["Type"], str(v["Value"]))) remain = remain - 1 except gammu.ERR_EMPTY: pass location = location + 1 if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/getallsms.py0000755000175000017500000000373400000000000017327 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import gammu def main(): state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() status = state_machine.GetSMSStatus() remain = status["SIMUsed"] + status["PhoneUsed"] + status["TemplatesUsed"] start = True try: while remain > 0: if start: sms = state_machine.GetNextSMS(Start=True, Folder=0) start = False else: sms = state_machine.GetNextSMS(Location=sms[0]["Location"], Folder=0) remain = remain - len(sms) for m in sms: print() print("{:<15}: {}".format("Number", m["Number"])) print("{:<15}: {}".format("Date", str(m["DateTime"]))) print("{:<15}: {}".format("State", m["State"])) print("\n{}".format(m["Text"])) except gammu.ERR_EMPTY: # This error is raised when we've reached last entry # It can happen when reported status does not match real counts print("Failed to read all messages!") if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/getallsms_decode.py0000755000175000017500000000516200000000000020627 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import gammu state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() status = state_machine.GetSMSStatus() remain = status["SIMUsed"] + status["PhoneUsed"] + status["TemplatesUsed"] sms = [] start = True try: while remain > 0: if start: cursms = state_machine.GetNextSMS(Start=True, Folder=0) start = False else: cursms = state_machine.GetNextSMS(Location=cursms[0]["Location"], Folder=0) remain = remain - len(cursms) sms.append(cursms) except gammu.ERR_EMPTY: # This error is raised when we've reached last entry # It can happen when reported status does not match real counts print("Failed to read all messages!") data = gammu.LinkSMS(sms) for x in data: v = gammu.DecodeSMS(x) m = x[0] print() print("{:<15}: {}".format("Number", m["Number"])) print("{:<15}: {}".format("Date", str(m["DateTime"]))) print("{:<15}: {}".format("State", m["State"])) print("{:<15}: {}".format("Folder", m["Folder"])) print("{:<15}: {}".format("Validity", m["SMSC"]["Validity"])) loc = [] for m in x: loc.append(str(m["Location"])) print("{:<15}: {}".format("Location(s)", ", ".join(loc))) if v is None: print("\n{}".format(m["Text"])) else: for e in v["Entries"]: print() print("{:<15}: {}".format("Type", e["ID"])) if e["Bitmap"] is not None: for bmp in e["Bitmap"]: print("Bitmap:") for row in bmp["XPM"][3:]: print(row) print() if e["Buffer"] is not None: print("Text:") print(e["Buffer"]) print() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/getalltodo.py0000755000175000017500000000316100000000000017464 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import gammu def main(): state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() status = state_machine.GetToDoStatus() remain = status["Used"] start = True while remain > 0: if start: entry = state_machine.GetNextToDo(Start=True) start = False else: entry = state_machine.GetNextToDo(Location=entry["Location"]) remain = remain - 1 print() print("{:<15}: {:d}".format("Location", entry["Location"])) print("{:<15}: {}".format("Priority", entry["Priority"])) for v in entry["Entries"]: print("{:<15}: {}".format(v["Type"], str(v["Value"]))) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534398.0 python-gammu-3.2.4/examples/getdiverts.py0000755000175000017500000000224300000000000017506 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu state_machine = gammu.StateMachine() if len(sys.argv) > 2: state_machine.ReadConfig(Filename=sys.argv[1]) del sys.argv[1] else: state_machine.ReadConfig() state_machine.Init() diverts = state_machine.GetCallDivert() for x in diverts: print(x) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/incoming.py0000755000175000017500000000525200000000000017134 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import time import gammu def callback(state_machine, callback_type, data): """ This callback receives notification about incoming event. @param state_machine: state machine which invoked action @type state_machine: gammu.StateMachine @param callback_type: type of action, one of Call, SMS, CB, USSD @type callback_type: string @param data: event data @type data: hash """ print(f"Received incoming event type {callback_type}, data:") print(data) def try_enable(call, name): try: call() except gammu.ERR_NOTSUPPORTED: print(f"{name} notification is not supported.") except gammu.ERR_SOURCENOTAVAILABLE: print(f"{name} notification is not enabled in Gammu.") def main(): # Create state machine state_machine = gammu.StateMachine() # Read gammurc state_machine.ReadConfig() # Initialize state machine and connect to phone state_machine.Init() # Set callback handler for incoming notifications state_machine.SetIncomingCallback(callback) # Enable notifications from calls try_enable(state_machine.SetIncomingCall, "Incoming calls") # Enable notifications from cell broadcast try_enable(state_machine.SetIncomingCB, "Incoming cell broadcasts") # Enable notifications from incoming SMS try_enable(state_machine.SetIncomingSMS, "Incoming SMS") # Enable notifications for incoming USSD try_enable(state_machine.SetIncomingUSSD, "Incoming USSD") # Just a busy waiting for event # We need to keep communication with phone to get notifications print("Press Ctrl+C to interrupt") while 1: signal = state_machine.GetSignalQuality() print("Signal is at {:d}%".format(signal["SignalPercent"])) time.sleep(1) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/listfilesystem.py0000755000175000017500000001120100000000000020400 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Matthias Blaesing # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Example for usage of GetNextFileFolder, which is oriented at gammu --getfilesystem Without argument you get a hierarchical list, provide flat as argument and get somethink like (not exactly!) gammu --getfilesystem -flatall """ import argparse import locale import gammu parser = argparse.ArgumentParser(usage="usage: %(prog)s [options]") parser.add_argument( "-c", "--config", action="store", type=str, dest="config", default=None, help="Config file path", ) parser.add_argument( "-f", "--flat", action="store_true", dest="flat", default=False, help="Flat listing" ) parser.add_argument( "-l", "--level", action="store_true", dest="level", default=False, help="Level listing", ) args = parser.parse_args() # Init gammu module state_machine = gammu.StateMachine() if args.config is not None: state_machine.ReadConfig(Filename=args.config) else: state_machine.ReadConfig() state_machine.Init() # Get wished listing from commandline (if provided - else asume level) # On commandline level or flat can be provided as parameters if args.flat: mode = "flat" else: mode = "level" # Set locale to default locale (here relevant for printing of date) locale.setlocale(locale.LC_ALL, "") # Wrapper around GetNextFileFolder, catching gammu.ERR_EMPTY # for me, which should be after the last entry and returning "None" # # GetNextFileFolder gives us a dict with: # 'Name' => Symbolic Name of the file (String) # 'ID_FullName' => unique ID of the file (String) # 'Used' => space used in bytes (integer) # 'Modified' => Date of last change (datetime) # 'Type' => Filetype as reported by phone (String) # 'Folder' => Entry is a Folder (Bool) # 'Level' => On which level of FS (Integer) # 'Buffer' => ?? (String) # File Attributes (Bool): # 'Protected' # 'ReadOnly' # 'Hidden' # 'System' def NextFile(start=0): try: return state_machine.GetNextFileFolder(start) except gammu.ERR_EMPTY: return None # Format File Attributes as String as a shorted Version def FileToAttributeString(file_obj, filled=1): protected = readonly = hidden = system = "" if filled: protected = readonly = hidden = system = " " if file_obj["Protected"]: protected = "P" if file_obj["ReadOnly"]: readonly = "R" if file_obj["Hidden"]: hidden = "H" if file_obj["System"]: system = "S" return protected + readonly + hidden + system def Main(): # Make sure we reset the pointer of the current entry to the first file_obj = NextFile(1) # Iterate over Files and print the Info while file_obj: if mode == "flat": # Output: # ;;;;; # We have to catch the situations, where no Modification Time is # provided try: time = file_obj["Modified"].strftime("%x %X") + ";" except AttributeError: time = ";" print( file_obj["ID_FullName"] + ";" + file_obj["Name"] + ";" + file_obj["Type"] + ";" + time + str(file_obj["Used"]) + ";" + FileToAttributeString(file_obj, 0) ) elif mode == "level": attrib = FileToAttributeString(file_obj, 1) level = file_obj["Level"] spacer = " | " * (level - 2) if level > 1: spacer += " |-- " title = '"' + file_obj["Name"] + '"' if file_obj["Folder"]: title = "Folder " + title print(attrib + spacer + title) file_obj = NextFile() if __name__ == "__main__": Main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/mass_sms.py0000755000175000017500000000304100000000000017150 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """Sample script to show how to same SMS to multiple recipients""" import sys import gammu # Check parameters count if len(sys.argv) < 3 or sys.argv[1] in ["--help", "-h", "-?"]: print("Usage: mass-sms [number]...") sys.exit(1) # Configure Gammu state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() # Prepare SMS template message = {"Text": sys.argv[1], "SMSC": {"Location": 1}} # Send SMS to all recipients on command line for number in sys.argv[2:]: message["Number"] = number try: state_machine.SendSMS(message) except gammu.GSMError as exc: print(f"Sending to {number} failed: {exc}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/pdu_decoder.py0000755000175000017500000000222600000000000017604 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu if len(sys.argv) != 2: print("This requires parameter with hex encoded PDU data!") sys.exit(1) # Global debug level gammu.SetDebugFile(sys.stderr) gammu.SetDebugLevel("textall") sms = gammu.DecodePDU(sys.argv[1].decode("hex")) print(sms) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/read_sms_backup.py0000755000175000017500000000511100000000000020445 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import codecs import sys import gammu def main(): if len(sys.argv) != 2: print("This requires parameter: backup file!") sys.exit(1) charsetencoder = codecs.getencoder(sys.getdefaultencoding()) filename = sys.argv[1] backup = gammu.ReadSMSBackup(filename) # Make nested array messages = [[message] for message in backup] data = gammu.LinkSMS(messages) for message in data: decoded = gammu.DecodeSMS(message) part = message[0] print() print("{:<15}: {}".format("Number", part["Number"])) print("{:<15}: {}".format("Date", str(part["DateTime"]))) print("{:<15}: {}".format("State", part["State"])) print("{:<15}: {}".format("Folder", part["Folder"])) print("{:<15}: {}".format("Validity", part["SMSC"]["Validity"])) loc = [] for part in message: loc.append(str(part["Location"])) print("{:<15}: {}".format("Location(s)", ", ".join(loc))) if decoded is None: print("\n{}".format(charsetencoder(part["Text"], "replace")[0])) else: for entries in decoded["Entries"]: print() print("{:<15}: {}".format("Type", entries["ID"])) if entries["Bitmap"] is not None: for bmp in entries["Bitmap"]: print("Bitmap:") for row in bmp["XPM"][3:]: print(row) print() if entries["Buffer"] is not None: print("Text:") print(charsetencoder(entries["Buffer"], "replace")) print() if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/examples/savesmspercontact.py0000755000175000017500000001141000000000000021066 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import errno import os import re import gammu def createFolderIfNotExist(path): try: os.makedirs(path) except OSError as exception: if exception.errno != errno.EEXIST: raise def getInternationalizedNumber(number): if not number: return "Unknown" if number.startswith("0"): return number.replace("0", "+49", 1) else: return number def getFilename(mydir, mysms): if mysms[0]["DateTime"]: return mysms[0]["DateTime"].strftime("%Y-%m-%d-%Hh%Mm%Ss") # no date available so calculate unknown number myfiles = os.listdir(mydir) nextitem = 0 for i in myfiles: match = re.match("^Unknown-([0-9]*)", i) if match and int(match.group(1)) > nextitem: nextitem = int(match.group(1)) return "Unknown-" + str(nextitem + 1) def saveSMS(mysms, all_contacts): my_number = getInternationalizedNumber(mysms[0]["Number"]) try: mydir = all_contacts[my_number] except KeyError: mydir = my_number createFolderIfNotExist(mydir) myfile = getFilename(mydir, mysms) with open(os.path.join(mydir, myfile), "a") as handle: for i in mysms: handle.write(i["Text"].encode("UTF-8")) handle.write(b"\n") def getContacts(state_machine): # Get all contacts remaining = state_machine.GetMemoryStatus(Type="SM")["Used"] contacts = dict() start = True try: while remaining > 0: if start: entry = state_machine.GetNextMemory(Start=True, Type="SM") start = False else: entry = state_machine.GetNextMemory( Location=entry["Location"], Type="SM" ) remaining = remaining - 1 numbers = list() for entry in entry["Entries"]: if entry["Type"] == "Text_FirstName": name = entry["Value"] else: numbers.append(getInternationalizedNumber(entry["Value"])) for number in numbers: contacts[number] = name except gammu.ERR_EMPTY: # error is raised if memory is empty (this induces wrong reported # memory status) print("Failed to read contacts!") return contacts def getAndDeleteAllSMS(state_machine): # Read SMS memory status ... memory = state_machine.GetSMSStatus() # ... and calculate number of messages remaining = memory["SIMUsed"] + memory["PhoneUsed"] # Get all sms start = True entries = list() try: while remaining > 0: if start: entry = state_machine.GetNextSMS(Folder=0, Start=True) start = False else: entry = state_machine.GetNextSMS( Folder=0, Location=entry[0]["Location"] ) remaining = remaining - 1 entries.append(entry) # delete retrieved sms state_machine.DeleteSMS(Folder=0, Location=entry[0]["Location"]) except gammu.ERR_EMPTY: # error is raised if memory is empty (this induces wrong reported # memory status) print("Failed to read messages!") # Link all SMS when there are concatenated messages entries = gammu.LinkSMS(entries) return entries def main(): # Get all contacts state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() contacts = getContacts(state_machine) state_machine.Terminate() # Get all sms # why in two steps? ERR_TIMOUT is raised without closing the connection state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() messages = getAndDeleteAllSMS(state_machine) state_machine.Terminate() for message in messages: saveSMS(message, contacts) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/sendlongsms.py0000755000175000017500000000436500000000000017671 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """Sample script to show how to send long (multipart) SMS""" import sys import gammu # Create object for talking with phone state_machine = gammu.StateMachine() # Optionally load config file as defined by first parameter if len(sys.argv) > 2: # Read the configuration from given file state_machine.ReadConfig(Filename=sys.argv[1]) # Remove file name from args list del sys.argv[1] else: # Read the configuration (~/.gammurc) state_machine.ReadConfig() # Check parameters if len(sys.argv) != 2: print("Usage: sendlongsms.py [configfile] RECIPIENT_NUMBER") sys.exit(1) # Connect to the phone state_machine.Init() # Create SMS info structure smsinfo = { "Class": -1, "Unicode": False, "Entries": [ { "ID": "ConcatenatedTextLong", "Buffer": "Very long python-gammu testing message " "sent from example python script. " "Very long python-gammu testing message " "sent from example python script. " "Very long python-gammu testing message " "sent from example python script. ", } ], } # Encode messages encoded = gammu.EncodeSMS(smsinfo) # Send messages for message in encoded: # Fill in numbers message["SMSC"] = {"Location": 1} message["Number"] = sys.argv[1] # Actually send the message state_machine.SendSMS(message) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/sendsms.py0000755000175000017500000000340000000000000016776 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Sample script to show how to send SMS """ import sys import gammu # Create object for talking with phone state_machine = gammu.StateMachine() # Optionally load config file as defined by first parameter if len(sys.argv) >= 2: # Read the configuration from given file state_machine.ReadConfig(Filename=sys.argv[1]) # Remove file name from args list del sys.argv[1] else: # Read the configuration (~/.gammurc) state_machine.ReadConfig() # Check parameters if len(sys.argv) != 2: print("Usage: sendsms.py [configfile] RECIPIENT_NUMBER") sys.exit(1) # Connect to the phone state_machine.Init() # Prepare message data # We tell that we want to use first SMSC number stored in phone message = { "Text": "python-gammu testing message", "SMSC": {"Location": 1}, "Number": sys.argv[1], } # Actually send the message state_machine.SendSMS(message) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/service_numbers.py0000755000175000017500000000516400000000000020526 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Service numbers dialogue example. """ import sys import gammu REPLY = False def callback(state_machine, callback_type, data): """ Callback on USSD data. """ global REPLY if callback_type != "USSD": print(f"Unexpected event type: {callback_type}") sys.exit(1) REPLY = True print("Network reply:") print("Status: {}".format(data["Status"])) print(data["Text"]) if data["Status"] == "ActionNeeded": do_service(state_machine) def init(): """ Intializes gammu and callbacks. """ state_machine = gammu.StateMachine() if len(sys.argv) >= 2: state_machine.ReadConfig(Filename=sys.argv[1]) else: state_machine.ReadConfig() state_machine.Init() state_machine.SetIncomingCallback(callback) try: state_machine.SetIncomingUSSD() except gammu.ERR_NOTSUPPORTED: print("Incoming USSD notification is not supported.") sys.exit(1) return state_machine def do_service(state_machine): """ Main code to talk with worker. """ global REPLY if len(sys.argv) >= 3: code = sys.argv[2] del sys.argv[2] else: prompt = "Enter code (empty string to end): " try: code = raw_input(prompt) except NameError: code = input(prompt) if code != "": print("Talking to network...") REPLY = False state_machine.DialService(code) loops = 0 while not REPLY and loops < 10: state_machine.ReadDevice() loops += 1 def main(): state_machine = init() print("This example shows interaction with network using service codes") do_service(state_machine) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/setdiverts.py0000755000175000017500000000246100000000000017524 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu state_machine = gammu.StateMachine() if len(sys.argv) > 2: state_machine.ReadConfig(Filename=sys.argv[1]) del sys.argv[1] else: state_machine.ReadConfig() state_machine.Init() if len(sys.argv) != 2: print("Usage: setdiverts.py NUMBER") sys.exit(1) state_machine.SetCallDivert("AllTypes", "All", sys.argv[1]) diverts = state_machine.GetCallDivert() for x in diverts: print(x) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/examples/sms_replier.py0000755000175000017500000000602600000000000017655 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import collections import time import gammu # Whether be a bit more verbose VERBOSE = False def verbose_print(text): if VERBOSE: print(text) def reply_test(message): if message["Number"] == "999": # No reply to this number return None return "Reply to {}".format(message["Text"]) # Reply function, first element is matching string, second can be: # - string = fixed string will be sent as reply # - function = function will be called with SMS data and it's result will be # sent # - None = no reply REPLIES = [ ("1/1 www:", "This is test"), ("1/2 www:", reply_test), ("2/2 www:", None), ] def Callback(state_machine, callback_type, data): verbose_print(f"Received incoming event type {callback_type}, data:") if callback_type != "SMS": print("Unsupported event!") if "Number" not in data: data = state_machine.GetSMS(data["Folder"], data["Location"])[0] verbose_print(data) for reply in REPLIES: if data["Text"].startswith(reply[0]): if isinstance(reply[1], collections.Callable): response = reply[1](data) else: response = reply[1] if response is not None: message = { "Text": response, "SMSC": {"Location": 1}, "Number": data["Number"], } verbose_print(message) state_machine.SendSMS(message) else: verbose_print("No reply!") break def main(): state_machine = gammu.StateMachine() state_machine.ReadConfig() state_machine.Init() state_machine.SetIncomingCallback(Callback) try: state_machine.SetIncomingSMS() except gammu.ERR_NOTSUPPORTED: print("Your phone does not support incoming SMS notifications!") # We need to keep communication with phone to get notifications print("Press Ctrl+C to interrupt") while 1: time.sleep(1) status = state_machine.GetBatteryCharge() print("Battery is at {:d}%".format(status["BatteryPercent"])) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/smsbackup.py0000755000175000017500000000220300000000000017312 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import sys import gammu if len(sys.argv) != 3: print( "This requires two parameter with file names!" " First is input, second output." ) sys.exit(1) backup = gammu.ReadSMSBackup(sys.argv[1]) gammu.SaveSMSBackup(sys.argv[2], backup) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/smsd_inject.py0000755000175000017500000000236200000000000017632 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """Sample script to show how to send SMS through SMSD""" import sys import gammu.smsd smsd = gammu.smsd.SMSD("/etc/gammu-smsdrc") if len(sys.argv) != 2: print("Usage: smsd-inject.py RECIPIENT_NUMBER") sys.exit(1) message = { "Text": "python-gammu testing message", "SMSC": {"Location": 1}, "Number": sys.argv[1], } smsd.InjectSMS([message]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/smsd_state.py0000755000175000017500000000201700000000000017473 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """Sample script to show how to get SMSD status""" import gammu.smsd smsd = gammu.smsd.SMSD("/etc/gammu-smsdrc") print(smsd.GetStatus()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/examples/vcs.py0000755000175000017500000000416700000000000016130 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Example for reading data from phone and convering it to and from vCard, vTodo, vCalendar """ import sys import gammu def main(): state_machine = gammu.StateMachine() if len(sys.argv) == 2: state_machine.ReadConfig(Filename=sys.argv[1]) else: state_machine.ReadConfig() state_machine.Init() # For calendar entry # Read entry from phone entry = state_machine.GetNextCalendar(Start=True) # Convert it to vCard vc_entry = gammu.EncodeVCALENDAR(entry) ic_entry = gammu.EncodeICALENDAR(entry) # Convert it back to entry print(gammu.DecodeVCS(vc_entry)) print(gammu.DecodeICS(ic_entry)) # For todo entry # Read entry from phone entry = state_machine.GetNextToDo(Start=True) # Convert it to vCard vt_entry = gammu.EncodeVTODO(entry) it_entry = gammu.EncodeITODO(entry) # Convert it back to entry print(gammu.DecodeVCS(vt_entry)) print(gammu.DecodeICS(it_entry)) # For memory entry # Read entry from phone entry = state_machine.GetNextMemory(Start=True, Type="ME") # Convert it to vCard vc_entry = gammu.EncodeVCARD(entry) # Convert it back to entry print(gammu.DecodeVCARD(vc_entry)) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/examples/worker.py0000755000175000017500000000613600000000000016644 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ python-gammu - Phone communication libary Gammu asynchronous wrapper example. This allows your application to care only about handling received data and not about phone communication details. """ import sys import gammu import gammu.worker def callback(name, result, error, percents): """ Callback which is executed when something is done. Please remember this is called from different thread so it does not have to be save to work with GUI here. """ print( "-> {} completed {:d}% with error {} , return value:".format( name, percents, error ) ) print(result) def read_config(): """ Reads gammu configuration. """ state_machine = gammu.StateMachine() # This is hack and should be as parameter of this function if len(sys.argv) == 2: state_machine.ReadConfig(Filename=sys.argv[1]) else: state_machine.ReadConfig() return state_machine.GetConfig() def main(): """ Main code to talk with worker. """ worker = gammu.worker.GammuWorker(callback) worker.configure(read_config()) # We can directly invoke commands worker.enqueue("GetManufacturer") worker.enqueue("GetSIMIMSI") worker.enqueue("GetIMEI") worker.enqueue("GetOriginalIMEI") worker.enqueue("GetManufactureMonth") worker.enqueue("GetProductCode") worker.enqueue("GetHardware") worker.enqueue("GetDateTime") # We can create compound tasks worker.enqueue("CustomGetInfo", commands=["GetModel", "GetBatteryCharge"]) # We can pass parameters worker.enqueue("GetMemory", ("SM", 1)) # We can create compound tasks with parameters: worker.enqueue( "CustomGetAllMemory", commands=[ ("GetMemory", ("SM", 1)), ("GetMemory", ("SM", 2)), ("GetMemory", ("SM", 3)), ("GetMemory", ("SM", 4)), ("GetMemory", ("SM", 5)), ], ) print("All commands submitted") worker.initiate() print("Worker started") # We can also pass commands with named parameters worker.enqueue("GetSMSC", {"Location": 1}) print("Submitted additional command") worker.terminate() print("Worker done") if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8663602 python-gammu-3.2.4/gammu/0000755000175000017500000000000000000000000014240 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534539.0 python-gammu-3.2.4/gammu/__init__.py0000644000175000017500000000216300000000000016353 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Phone communication libary - python wrapper for Gammu library. """ from gammu._gammu import * __version__ = "Gammu {}, python-gammu {}".format(*Version()) # Submodules __all__ = [ "data", "worker", "asyncworker", "smsd", "exception", ] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/gammu/asyncworker.py0000644000175000017500000001253400000000000017166 0ustar00nijelnijel"""Async extensions for gammu.""" import asyncio import gammu import gammu.worker class GammuAsyncThread(gammu.worker.GammuThread): """Thread for phone communication.""" def __init__(self, queue, config, callback, pull_func): """Initialize thread.""" super().__init__(queue, config, callback, pull_func) def _do_command(self, future, cmd, params, percentage=100): """Execute single command on phone.""" func = getattr(self._sm, cmd) result = None try: if params is None: result = func() elif isinstance(params, dict): result = func(**params) else: result = func(*params) except gammu.GSMError as info: errcode = info.args[0]["Code"] error = gammu.ErrorNumbers[errcode] self._callback(future, result, error, percentage) except Exception as exception: # pylint: disable=broad-except self._callback(future, None, exception, percentage) else: self._callback(future, result, None, percentage) def gammu_pull_device(sm): sm.ReadDevice() class GammuAsyncWorker(gammu.worker.GammuWorker): """Extend gammu worker class for async operations.""" def worker_callback(self, name, result, error, percents): """Execute command from the thread worker.""" future = None if name == "Init" and self._init_future is not None: future = self._init_future elif name == "Terminate" and self._terminate_future is not None: # Set _kill to true on the base class to avoid waiting for termination self._thread._kill = True # pylint: disable=protected-access future = self._terminate_future elif hasattr(name, "set_result"): future = name if future is not None: if error is None: self._loop.call_soon_threadsafe(future.set_result, result) else: exception = error if not isinstance(error, Exception): exception = gammu.GSMError(error) self._loop.call_soon_threadsafe(future.set_exception, exception) def __init__(self, pull_func=gammu_pull_device): """Initialize the worker class. @param callback: See L{GammuThread.__init__} for description. """ super().__init__(self.worker_callback, pull_func) self._loop = asyncio.get_event_loop() self._init_future = None self._terminate_future = None self._thread = None self._pull_func = pull_func async def init_async(self): """Connect to phone.""" self._init_future = self._loop.create_future() self._thread = GammuAsyncThread( self._queue, self._config, self._callback, self._pull_func ) self._thread.start() await self._init_future self._init_future = None async def get_imei_async(self): """Get the IMEI of the device.""" future = self._loop.create_future() self.enqueue(future, commands=[("GetIMEI", ())]) return await future async def get_network_info_async(self): """Get the network info in the device.""" future = self._loop.create_future() self.enqueue(future, commands=[("GetNetworkInfo", ())]) return await future async def get_manufacturer_async(self): """Get the manufacturer of the device.""" future = self._loop.create_future() self.enqueue(future, commands=[("GetManufacturer", ())]) return await future async def get_model_async(self): """Get the model of the device.""" future = self._loop.create_future() self.enqueue(future, commands=[("GetModel", ())]) return await future async def get_firmware_async(self): """Get the firmware version of the device.""" future = self._loop.create_future() self.enqueue(future, commands=[("GetFirmware", ())]) return await future async def get_signal_quality_async(self): """Get signal quality from phone.""" future = self._loop.create_future() self.enqueue(future, commands=[("GetSignalQuality", ())]) result = await future return result async def send_sms_async(self, message): """Send sms message via the phone.""" future = self._loop.create_future() self.enqueue(future, commands=[("SendSMS", [message])]) result = await future return result async def set_incoming_callback_async(self, callback): """Set the callback to call from phone.""" future = self._loop.create_future() self.enqueue(future, commands=[("SetIncomingCallback", [callback])]) result = await future return result async def set_incoming_sms_async(self): """Activate SMS notifications from phone.""" future = self._loop.create_future() self.enqueue(future, commands=[("SetIncomingSMS", ())]) result = await future return result async def terminate_async(self): """Terminate phone communication.""" self._terminate_future = self._loop.create_future() self.enqueue("Terminate") await self._terminate_future while self._thread.is_alive(): await asyncio.sleep(5) self._thread = None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/gammu/data.py0000644000175000017500000001670700000000000015536 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Some static data. @var Connections: List of connection types. @var MemoryValueTypes: Types of memory entry values. @var CalendarTypes: Types of calendar entries. @var CalendarValueTypes: Types of calendar entry values. @var TodoPriorities: Todo priorities. @var TodoValueTypes: Types of todo entry values. @var InternationalPrefixes: List of known internaltional prefixes. """ from gammu import ErrorNumbers, Errors Connections = [ "at", "at19200", "at115200", "fbus", "dlr3", "dku2", "dku5", "fbuspl2303", "mbus", "irdaphonet", "irdaat", "irdaobex", "irdagnapbus", "bluerffbus", "bluefbus", "bluerfphonet", "bluephonet", "blueat", "bluerfat", "blueobex", "bluerfobex", "fbusblue", "fbusirda", "phonetblue", "bluerfgnapbus", ] MemoryValueTypes = [ "Number_General", "Number_Mobile", "Number_Work", "Number_Fax", "Number_Home", "Number_Pager", "Number_Other", "Text_Note", "Text_Postal", "Text_WorkPostal", "Text_Email", "Text_Email2", "Text_URL", "Date", "Caller_Group", "Text_Name", "Text_LastName", "Text_FirstName", "Text_Company", "Text_JobTitle", "Category", "Private", "Text_StreetAddress", "Text_City", "Text_State", "Text_Zip", "Text_Country", "Text_WorkStreetAddress", "Text_WorkCity", "Text_WorkState", "Text_WorkZip", "Text_WorkCountry", "Text_Custom1", "Text_Custom2", "Text_Custom3", "Text_Custom4", "RingtoneID", "PictureID", "Text_UserID", "CallLength", "Text_LUID", "LastModified", "Text_NickName", "Text_FormalName", "PushToTalkID", "Photo", "Number_Mobile_Home", "Number_Mobile_Work", "Text_SecondName", "Text_VOIP", "Text_SIP", "Text_DTMF", "Number_Video", "Text_SWIS", "Text_WVID", "Text_NamePrefix", "Text_NameSuffix", ] CalendarTypes = [ "REMINDER", "CALL", "MEETING", "BIRTHDAY", "MEMO", "TRAVEL", "VACATION", "T_ATHL", "T_BALL", "T_CYCL", "T_BUDO", "T_DANC", "T_EXTR", "T_FOOT", "T_GOLF", "T_GYM", "T_HORS", "T_HOCK", "T_RACE", "T_RUGB", "T_SAIL", "T_STRE", "T_SWIM", "T_TENN", "T_TRAV", "T_WINT", "ALARM", "DAILY_ALARM", "SHOPPING", ] CalendarValueTypes = [ "START_DATETIME", "END_DATETIME", "TONE_ALARM_DATETIME", "SILENT_ALARM_DATETIME", "RECURRANCE", "TEXT", "DESCRIPTION", "LOCATION", "PHONE", "PRIVATE", "CONTACTID", "REPEAT_DAYOFWEEK", "REPEAT_DAY", "REPEAT_WEEKOFMONTH", "REPEAT_MONTH", "REPEAT_FREQUENCY", "REPEAT_STARTDATE", "REPEAT_STOPDATE", "LUID", "LAST_MODIFIED", ] TodoPriorities = [ "High", "Medium", "Low", "None", ] TodoValueTypes = [ "END_DATETIME", "START_DATETIME", "COMPLETED_DATETIME", "COMPLETED", "ALARM_DATETIME", "SILENT_ALARM_DATETIME", "TEXT", "DESCRIPTION", "LOCATION", "LUID", "PRIVATE", "CATEGORY", "CONTACTID", "PHONE", "LAST_MODIFIED", ] InternationalPrefixes = [ "+1", "+20", "+210", "+211", "+212", "+213", "+214", "+215", "+216", "+217", "+218", "+219", "+220", "+221", "+222", "+223", "+224", "+225", "+226", "+227", "+228", "+229", "+230", "+231", "+232", "+233", "+234", "+235", "+236", "+237", "+238", "+239", "+240", "+241", "+242", "+243", "+244", "+245", "+246", "+247", "+248", "+249", "+250", "+251", "+252", "+253", "+254", "+255", "+256", "+257", "+258", "+259", "+260", "+261", "+262", "+263", "+264", "+265", "+266", "+267", "+268", "+269", "+27", "+28", "+290", "+291", "+292", "+293", "+294", "+295", "+296", "+297", "+298", "+299", "+30", "+31", "+32", "+33", "+34", "+350", "+351", "+352", "+353", "+354", "+355", "+356", "+357", "+358", "+359", "+36", "+370", "+371", "+372", "+373", "+374", "+375", "+376", "+377", "+378", "+379", "+380", "+381", "+382", "+383", "+384", "+385", "+386", "+387", "+388", "+389", "+39", "+40", "+41", "+420", "+421", "+422", "+423", "+424", "+425", "+426", "+427", "+428", "+429", "+43", "+44", "+45", "+46", "+47", "+48", "+49", "+500", "+501", "+502", "+503", "+504", "+505", "+506", "+507", "+508", "+509", "+51", "+52", "+53", "+54", "+55", "+56", "+57", "+58", "+590", "+591", "+592", "+593", "+594", "+595", "+596", "+597", "+598", "+599", "+60", "+61", "+62", "+63", "+64", "+65", "+66", "+670", "+671", "+672", "+673", "+674", "+675", "+676", "+677", "+678", "+679", "+680", "+681", "+682", "+683", "+684", "+685", "+686", "+687", "+688", "+689", "+690", "+691", "+692", "+693", "+694", "+695", "+696", "+697", "+698", "+699", "+7", "+800", "+801", "+802", "+803", "+804", "+805", "+806", "+807", "+808", "+809", "+81", "+82", "+83", "+84", "+850", "+851", "+852", "+853", "+854", "+855", "+856", "+857", "+858", "+859", "+86", "+870", "+871", "+872", "+873", "+874", "+875", "+876", "+877", "+878", "+879", "+880", "+881", "+882", "+883", "+884", "+885", "+886", "+887", "+888", "+889", "+89", "+90", "+91", "+92", "+93", "+94", "+95", "+960", "+961", "+962", "+963", "+964", "+965", "+966", "+967", "+968", "+969", "+970", "+971", "+972", "+973", "+974", "+975", "+976", "+977", "+978", "+979", "+98", "+990", "+991", "+992", "+993", "+994", "+995", "+996", "+997", "+998", "+999", ] __all__ = [ "Errors", "ErrorNumbers", "Connections", "MemoryValueTypes", "CalendarTypes", "CalendarValueTypes", "TodoPriorities", "TodoValueTypes", "InternationalPrefixes", ] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534566.0 python-gammu-3.2.4/gammu/exception.py0000644000175000017500000000237300000000000016615 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Gammu exceptions. """ import gammu._gammu from gammu import GSMError __all__ = [ "GSMError", ] # Import all exceptions for _name in dir(gammu._gammu): if not _name.startswith("ERR_"): continue _temp = __import__("gammu._gammu", globals(), locals(), [_name], 0) locals()[_name] = getattr(_temp, _name) __all__.append(_name) # Cleanup del _name del _temp del gammu ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/gammu/smsd.py0000644000175000017500000000166300000000000015566 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ SMSD wrapper layer. """ from gammu import SMSD __all__ = ["SMSD"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8703601 python-gammu-3.2.4/gammu/src/0000755000175000017500000000000000000000000015027 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8703601 python-gammu-3.2.4/gammu/src/convertors/0000755000175000017500000000000000000000000017233 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/backup.c0000644000175000017500000001430000000000000020642 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Backup related conversions */ #include "convertors.h" #include "misc.h" #ifdef GSM_ENABLE_BACKUP /* FIXME: should better check for errors and support all backup features */ PyObject *BackupToPython(GSM_Backup * backup) { PyObject *phone; PyObject *sim; PyObject *calendar; PyObject *todo; PyObject *o; PyObject *dt; int i; phone = PyList_New(0); for (i = 0; backup->PhonePhonebook[i] != NULL; i++) { o = MemoryEntryToPython(backup->PhonePhonebook[i]); if (o == NULL) { Py_DECREF(phone); return NULL; } PyList_Append(phone, o); Py_DECREF(o); } sim = PyList_New(0); for (i = 0; backup->SIMPhonebook[i] != NULL; i++) { o = MemoryEntryToPython(backup->SIMPhonebook[i]); if (o == NULL) { Py_DECREF(sim); return NULL; } PyList_Append(sim, o); Py_DECREF(o); } todo = PyList_New(0); for (i = 0; backup->ToDo[i] != NULL; i++) { o = TodoToPython(backup->ToDo[i]); if (o == NULL) { Py_DECREF(todo); return NULL; } PyList_Append(todo, o); Py_DECREF(o); } calendar = PyList_New(0); for (i = 0; backup->Calendar[i] != NULL; i++) { o = CalendarToPython(backup->Calendar[i]); if (o == NULL) { Py_DECREF(calendar); return NULL; } PyList_Append(calendar, o); Py_DECREF(o); } if (backup->DateTimeAvailable) { dt = BuildPythonDateTime(&backup->DateTime); if (dt == NULL) { PyErr_Clear(); Py_INCREF(Py_None); dt = Py_None; } } else { Py_INCREF(Py_None); dt = Py_None; } o = Py_BuildValue( "{s:s,s:s,s:s,s:O,s:O,s:O,s:O,s:O}", "IMEI", backup->IMEI, "Model", backup->Model, "Creator", backup->Creator, "PhonePhonebook", phone, "SIMPhonebook", sim, "Calendar", calendar, "ToDo", todo, "DateTime", dt ); Py_DECREF(phone); Py_DECREF(sim); Py_DECREF(calendar); Py_DECREF(todo); Py_DECREF(dt); return o; } #define GET_ONE(key, data, maxlen, type, conv)\ o = PyDict_GetItemString(dict, key);\ if (o == NULL) {\ backup->data[0] = NULL;\ } else if (o == Py_None) {\ backup->data[0] = NULL;\ } else if (!PyList_Check(o)) {\ PyErr_Format(PyExc_ValueError, "%s not a list!", key);\ return 0;\ } else {\ len = PyList_Size(o);\ if (len > maxlen) {\ pyg_warning("Too many entries in %s, truncating to %d from %" PY_FORMAT_SIZE_T "d!\n", key, maxlen, len);\ len = maxlen;\ }\ for (i = 0; i < len; i++) {\ backup->data[i] = (type *)malloc(sizeof(type));\ if (backup->data[i] == NULL) { \ PyErr_Format(PyExc_MemoryError, "Failed to allocate memory!"); \ return 0;\ }\ x = PyList_GetItem(o, i);\ if (x == NULL) {\ PyErr_Format(PyExc_ValueError, "Failed to get item %ld from list %s!", (long)i, key);\ return 0;\ }\ if (!conv) {\ return 0;\ }\ }\ backup->data[len] = NULL;\ } int BackupFromPython(PyObject * dict, GSM_Backup * backup) { PyObject *o; PyObject *x; Py_ssize_t len; Py_ssize_t i; char *s; if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_ValueError, "Backup is not a dictionary!"); return 0; } GSM_ClearBackup(backup); backup->IMEI[0] = 0; s = GetCharFromDict(dict, "IMEI"); if (s == 0) { PyErr_Clear(); } else { len = strlen(s); if (len > GSM_MAX_IMEI_LENGTH - 1) { len = GSM_MAX_IMEI_LENGTH - 1; } strncat(backup->IMEI, s, len); free(s); } backup->Model[0] = 0; s = GetCharFromDict(dict, "Model"); if (s == 0) { PyErr_Clear(); } else { len = strlen(s); if (len > GSM_MAX_MODEL_LENGTH + GSM_MAX_VERSION_LENGTH - 1) { len = GSM_MAX_MODEL_LENGTH + GSM_MAX_VERSION_LENGTH - 1; } strncat(backup->Model, s, len); free(s); } backup->Creator[0] = 0; s = GetCharFromDict(dict, "Creator"); if (s == 0) { PyErr_Clear(); strcpy(backup->Creator, "python-gammu " GAMMU_VERSION); } else { len = strlen(s); if (len > 50 - 1) len = 50 - 1; mystrncpy(backup->Creator, s, len); free(s); } GET_ONE("PhonePhonebook", PhonePhonebook, GSM_BACKUP_MAX_PHONEPHONEBOOK, GSM_MemoryEntry, MemoryEntryFromPython(x, backup->PhonePhonebook[i], 1)); GET_ONE("SIMPhonebook", SIMPhonebook, GSM_BACKUP_MAX_SIMPHONEBOOK, GSM_MemoryEntry, MemoryEntryFromPython(x, backup->SIMPhonebook[i], 1)); GET_ONE("ToDo", ToDo, GSM_MAXCALENDARTODONOTES, GSM_ToDoEntry, TodoFromPython(x, backup->ToDo[i], 1)); GET_ONE("Calendar", Calendar, GSM_MAXCALENDARTODONOTES, GSM_CalendarEntry, CalendarFromPython(x, backup->Calendar[i], 1)); return 1; } int BackupFormatFromString(const char *s, GSM_BackupFormat * format) { if (strcmp(s, "LMB") == 0) { *format = GSM_Backup_LMB; } else if (strcmp(s, "VCalendar") == 0) { *format = GSM_Backup_VCalendar; } else if (strcmp(s, "VCard") == 0) { *format = GSM_Backup_VCard; } else if (strcmp(s, "LDIF") == 0) { *format = GSM_Backup_LDIF; } else if (strcmp(s, "ICS") == 0) { *format = GSM_Backup_ICS; } else if (strcmp(s, "Gammu") == 0) { *format = GSM_Backup_Gammu; } else if (strcmp(s, "GammuUCS2") == 0) { *format = GSM_Backup_GammuUCS2; } else if (strcmp(s, "Auto") == 0) { *format = GSM_Backup_Auto; } else if (strcmp(s, "AutoUnicode") == 0) { *format = GSM_Backup_AutoUnicode; } else { PyErr_Format(PyExc_ValueError, "Bad value for format: '%s'", s); return 0; } return 1; } #endif /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134736.0 python-gammu-3.2.4/gammu/src/convertors/base.c0000644000175000017500000001525600000000000020322 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Basic getters from Python objects */ #include "convertors.h" #include "misc.h" /* Strings */ #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include gboolean BoolFromPython(PyObject * o, const char *key) { char *s; int i; PyObject *o2; if (o == Py_None) { return FALSE; } if (!PyBool_Check(o)) { if (PyLong_Check(o)) { i = PyLong_AsLong(o); if (i == 0) return FALSE; else return TRUE; } if (PyUnicode_Check(o)) { o2 = PyUnicode_AsASCIIString(o); if (o2 == NULL) { return BOOL_INVALID; } s = PyBytes_AsString(o2); if (isdigit((int)s[0])) { i = atoi(s); Py_DECREF(o2); if (i == 0) return FALSE; else return TRUE; } else if (strcasecmp(s, "yes") == 0) { Py_DECREF(o2); return TRUE; } else if (strcasecmp(s, "true") == 0) { Py_DECREF(o2); return TRUE; } else if (strcasecmp(s, "no") == 0) { Py_DECREF(o2); return FALSE; } else if (strcasecmp(s, "false") == 0) { Py_DECREF(o2); return FALSE; } else { Py_DECREF(o2); PyErr_Format(PyExc_ValueError, "String value of '%s' doesn't seem to be boolean", key); return BOOL_INVALID; } } PyErr_Format(PyExc_ValueError, "Value of '%s' doesn't seem to be boolean", key); return BOOL_INVALID; } if (Py_False == o) return FALSE; else if (Py_True == o) return TRUE; PyErr_Format(PyExc_ValueError, "Bool value of '%s' doesn't seem to be boolean", key); return BOOL_INVALID; } gboolean GetBoolFromDict(PyObject * dict, const char *key) { PyObject *o; o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); return BOOL_INVALID; } return BoolFromPython(o, key); } int GetIntFromDict(PyObject * dict, const char *key) { PyObject *o; PyObject *o2; char *s; int i; o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); return INT_INVALID; } if (PyLong_Check(o)) { /* Well we loose here something, but it is intentional :-) */ return (int)PyLong_AsLongLong(o); } if (PyUnicode_Check(o)) { o2 = PyUnicode_AsASCIIString(o); if (o2 == NULL) { return INT_INVALID; } s = PyBytes_AsString(o2); if (isdigit((int)s[0])) { i = atoi(s); Py_DECREF(o2); return i; } else { Py_DECREF(o2); PyErr_Format(PyExc_ValueError, "Value of '%s' doesn't seem to be integer", key); return INT_INVALID; } } PyErr_Format(PyExc_ValueError, "Value of '%s' doesn't seem to be integer", key); return INT_INVALID; } unsigned char *GetStringFromDict(PyObject * dict, const char *key) { PyObject *o; o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); return NULL; } return StringPythonToGammu(o); } int CopyStringFromDict(PyObject * dict, const char *key, size_t len, unsigned char *dest) { unsigned char *s; s = GetStringFromDict(dict, key); if (s == NULL) return 0; if (UnicodeLength(s) > len) { pyg_warning("Truncating text %s to %ld chars!\n", key, (long)len); s[2 * len] = 0; s[(2 * len) + 1] = 0; } CopyUnicodeString(dest, s); free(s); return 1; } GSM_DateTime GetDateTimeFromDict(PyObject * dict, const char *key) { PyObject *o; GSM_DateTime dt; memset(&dt, 0, sizeof(GSM_DateTime)); o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); dt.Year = -1; return dt; } if (!BuildGSMDateTime(o, &dt)) { dt.Year = -1; } else { /* We use this as an error value */ if (dt.Year == -1) { dt.Year = 0; } } return dt; } GSM_DateTime GetDateFromDict(PyObject * dict, const char *key) { PyObject *o; GSM_DateTime dt; memset(&dt, 0, sizeof(GSM_DateTime)); o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); dt.Year = -1; return dt; } if (!BuildGSMDate(o, &dt)) { dt.Year = -1; } return dt; } char *GetCharFromDict(PyObject * dict, const char *key) { PyObject *o, *o2 = NULL; char *ps = NULL, *result = NULL; size_t length; o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); return NULL; } if (PyUnicode_Check(o)) { o2 = PyUnicode_AsASCIIString(o); if (o2 == NULL) { return NULL; } ps = PyBytes_AsString(o2); } if (ps == NULL) { PyErr_Format(PyExc_ValueError, "Can not get string value for key %s", key); goto out; } length = strlen(ps) + 1; result = (char *)malloc(length); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Failed to allocate memory!"); goto out; } memcpy(result, ps, length); out: if (o2 != NULL) { Py_DECREF(o2); } return result; } char *GetDataFromDict(PyObject * dict, const char *key, Py_ssize_t * len) { PyObject *o; char *ps; o = PyDict_GetItemString(dict, key); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing key in dictionary: %s", key); return NULL; } if (!PyBytes_Check(o)) { PyErr_Format(PyExc_ValueError, "Not a bytes string: %s", key); return NULL; } if (PyBytes_AsStringAndSize(o, &ps, len) != 0) { PyErr_Format(PyExc_ValueError, "Can not get string value for key %s", key); return NULL; } return ps; } char *GetCStringLengthFromDict(PyObject * dict, const char *key, Py_ssize_t * length) { char *result, *data; data = GetDataFromDict(dict, key, length); result = (char *)malloc(*length); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Failed to allocate memory!"); return NULL; } memcpy(result, data, *length); return result; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/bitmap.c0000644000175000017500000002534200000000000020661 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Bitmaps related conversions */ #include "convertors.h" #include "misc.h" #include char *BitmapTypeToString(GSM_Bitmap_Types type) { char *s = NULL; switch (type) { case GSM_None: s = strdup("None"); break; case GSM_ColourStartupLogo_ID: s = strdup("ColourStartupLogo_ID"); break; case GSM_StartupLogo: s = strdup("StartupLogo"); break; case GSM_ColourOperatorLogo_ID: s = strdup("ColourOperatorLogo_ID"); break; case GSM_OperatorLogo: s = strdup("OperatorLogo"); break; case GSM_ColourWallPaper_ID: s = strdup("ColourWallPaper_ID"); break; case GSM_CallerGroupLogo: s = strdup("CallerGroupLogo"); break; case GSM_DealerNote_Text: s = strdup("DealerNote_Text"); break; case GSM_WelcomeNote_Text: s = strdup("WelcomeNote_Text"); break; case GSM_PictureImage: s = strdup("PictureImage"); break; case GSM_PictureBinary: s = strdup("PictureBinary"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for BitmapType from Gammu: '%d'", type); return NULL; } return s; } GSM_Bitmap_Types StringToBitmapType(char *s) { if (strcmp("None", s) == 0) return GSM_None; else if (strcmp("ColourStartupLogo_ID", s) == 0) return GSM_ColourStartupLogo_ID; else if (strcmp("StartupLogo", s) == 0) return GSM_StartupLogo; else if (strcmp("ColourOperatorLogo_ID", s) == 0) return GSM_ColourOperatorLogo_ID; else if (strcmp("OperatorLogo", s) == 0) return GSM_OperatorLogo; else if (strcmp("ColourWallPaper_ID", s) == 0) return GSM_ColourWallPaper_ID; else if (strcmp("CallerGroupLogo", s) == 0) return GSM_CallerGroupLogo; else if (strcmp("DealerNote_Text", s) == 0) return GSM_DealerNote_Text; else if (strcmp("WelcomeNote_Text", s) == 0) return GSM_WelcomeNote_Text; else if (strcmp("PictureImage", s) == 0) return GSM_PictureImage; else if (strcmp("PictureBinary", s) == 0) return GSM_PictureBinary; PyErr_Format(PyExc_MemoryError, "Bad value for MultiPartSMSID '%s'", s); return 0; } int BitmapFromPython(PyObject * dict, GSM_Bitmap * entry) { char *s; int i, j; int w, h, cols, chars; char c, black = 0, transp = 0; char buffer[1000]; int x, y; PyObject *o; PyObject *item; int len; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "Bitmap is not a dictionary"); return 0; } memset(entry, 0, sizeof(GSM_Bitmap)); s = GetCharFromDict(dict, "Type"); if (s == NULL) return 0; entry->Type = StringToBitmapType(s); free(s); if (entry->Type == 0) return 0; s = GetCharFromDict(dict, "NetworkCode"); if (s == NULL) { PyErr_Clear(); entry->NetworkCode[0] = 0; } else { mystrncpy(entry->NetworkCode, s, 6); free(s); } i = GetIntFromDict(dict, "Location"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->Location = i; } i = GetIntFromDict(dict, "BitmapEnabled"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->BitmapEnabled = i; } i = GetIntFromDict(dict, "DefaultName"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->DefaultName = i; } i = GetIntFromDict(dict, "DefaultBitmap"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->DefaultBitmap = i; } i = GetIntFromDict(dict, "DefaultRingtone"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->DefaultRingtone = i; } i = GetIntFromDict(dict, "RingtoneID"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->RingtoneID = i; } i = GetIntFromDict(dict, "ID"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->ID = i; } if (!CopyStringFromDict (dict, "Text", GSM_BITMAP_TEXT_LENGTH, entry->Text)) { PyErr_Clear(); entry->Text[0] = 0; entry->Text[1] = 0; } if (!CopyStringFromDict (dict, "Sender", GSM_MAX_NUMBER_LENGTH, entry->Sender)) { PyErr_Clear(); entry->Text[0] = 0; entry->Text[1] = 0; } o = PyDict_GetItemString(dict, "XPM"); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Could not get XPM for bitmap!"); return 0; } if (!PyList_Check(o)) { PyErr_Format(PyExc_ValueError, "XPM isn't list!"); return 0; } len = PyList_Size(o); if (len < 3) { PyErr_Format(PyExc_ValueError, "XPM list too small!"); return 0; } #define GetString(s, x) \ item = PyList_GetItem(o, x);\ if (!PyBytes_Check(item)) {\ PyErr_Format(PyExc_ValueError, "XPM contains something different than byte string!");\ return 0;\ }\ \ s = PyBytes_AsString(item);\ if (s == NULL) {\ PyErr_Format(PyExc_ValueError, "XPM contains something different than byte string!");\ return 0;\ } GetString(s, 0); if (sscanf(s, "%d %d %d %d", &w, &h, &cols, &chars) != 4) { PyErr_Format(PyExc_ValueError, "Bad first XPM row"); return 0; } if (chars != 1 || cols != 2) { PyErr_Format(PyExc_ValueError, "Only two color XPM with one char per pixel supported"); return 0; } if (w > 255 || h > 255 || w < 0 || h < 0 || w * h / 8 > GSM_BITMAP_SIZE) { PyErr_Format(PyExc_ValueError, "Bad size of bitmap"); return 0; } entry->BitmapWidth = w; entry->BitmapHeight = h; for (i = 1; i < 3; i++) { GetString(s, i); if (sscanf(s, "%c c %999s", &c, buffer) != 2) { PyErr_Format(PyExc_ValueError, "Can not parse XPM line: '%s'", s); return 0; } j = 0; while (buffer[j] != 0) { buffer[j] = tolower((int)buffer[j]); j++; } if (strcmp(buffer, "none") == 0 || strcmp(buffer, "#fff") == 0 || strcmp(buffer, "#ffffff") == 0 || strcmp(buffer, "white") == 0) transp = c; else if (strcmp(buffer, "#000") == 0 || strcmp(buffer, "#000000") == 0 || strcmp(buffer, "black") == 0) black = c; else { PyErr_Format(PyExc_ValueError, "Only black and write are supported (guven was %s)", buffer); return 0; } } if (black == 0 || transp == 0) { PyErr_Format(PyExc_ValueError, "At least one XPM color was not found"); return 0; } for (y = 0; y < h; y++) { GetString(s, y + 3); if ((ssize_t) strlen(s) != w) { PyErr_Format(PyExc_ValueError, "XPM line has bad length: '%s'", s); return 0; } for (x = 0; x < w; x++) { if (s[x] == black) GSM_SetPointBitmap(entry, x, y); else if (s[x] == transp) GSM_ClearPointBitmap(entry, x, y); else { PyErr_Format(PyExc_ValueError, "Bad character in XPM data: '%c'", s[x]); return 0; } } } return 1; } PyObject *BitmapToPython(GSM_Bitmap * bitmap) { char buffer[1000]; size_t x, y; PyObject *xpmval; PyObject *s; char *t; Py_UNICODE *txt; Py_UNICODE *sendr; PyObject *val; xpmval = PyList_New(0); if (xpmval == NULL) return NULL; #if 0 /* Not needed as BitmapWidth is char */ if (bitmap->BitmapWidth > 999) { PyErr_SetString(PyExc_MemoryError, "Maximal supported bitmap width is 999 for now!"); return NULL; } #endif snprintf(buffer, 99, "%i %i 2 1", (int)bitmap->BitmapWidth, (int)bitmap->BitmapHeight); s = PyBytes_FromString(buffer); if (s == NULL) return NULL; if (PyList_Append(xpmval, s) != 0) { Py_DECREF(xpmval); Py_DECREF(s); return NULL; } Py_DECREF(s); s = PyBytes_FromString("# c Black"); if (s == NULL) return NULL; if (PyList_Append(xpmval, s) != 0) { Py_DECREF(xpmval); Py_DECREF(s); return NULL; } Py_DECREF(s); s = PyBytes_FromString(" c None"); if (s == NULL) return NULL; if (PyList_Append(xpmval, s) != 0) { Py_DECREF(xpmval); Py_DECREF(s); return NULL; } Py_DECREF(s); buffer[bitmap->BitmapWidth] = 0; for (y = 0; y < bitmap->BitmapHeight; y++) { for (x = 0; x < bitmap->BitmapWidth; x++) { buffer[x] = GSM_IsPointBitmap(bitmap, x, y) ? '#' : ' '; } s = PyBytes_FromString(buffer); if (s == NULL) return NULL; if (PyList_Append(xpmval, s) != 0) { Py_DECREF(xpmval); Py_DECREF(s); return NULL; } Py_DECREF(s); } t = BitmapTypeToString(bitmap->Type); if (t == NULL) { Py_DECREF(xpmval); return NULL; } txt = strGammuToPython(bitmap->Text); if (txt == NULL) { Py_DECREF(xpmval); free(t); return NULL; } sendr = strGammuToPython(bitmap->Sender); if (sendr == NULL) { Py_DECREF(xpmval); free(t); free(txt); return NULL; } val = Py_BuildValue("{s:s,s:i,s:u,s:i,s:i,s:i,s:i,s:i,s:i,s:O,s:u,s:s}", "Type", t, "Location", (int)bitmap->Location, "Text", txt, "Enabled", (int)bitmap->BitmapEnabled, "DefaultName", (int)bitmap->DefaultName, "DefaultBitmap", (int)bitmap->DefaultBitmap, "DefaultRingtone", (int)bitmap->DefaultRingtone, "RingtoneID", (int)bitmap->RingtoneID, "ID", (int)bitmap->ID, "XPM", xpmval, "Sender", sendr, "NetworkCode", bitmap->NetworkCode); Py_DECREF(xpmval); free(t); free(txt); free(sendr); return val; } int MultiBitmapFromPython(PyObject * list, GSM_MultiBitmap * bmp) { PyObject *item; Py_ssize_t len; Py_ssize_t i; if (!PyList_Check(list)) { PyErr_Format(PyExc_ValueError, "Multi bitmap is not a list"); return 0; } len = PyList_Size(list); if (len > GSM_MAX_MULTI_BITMAP) { pyg_warning ("Truncating Multi Bitmap entries to %d entries! (from %" PY_FORMAT_SIZE_T "d))\n", GSM_MAX_MULTI_BITMAP, len); len = GSM_MAX_MULTI_BITMAP; } bmp->Number = len; for (i = 0; i < len; i++) { item = PyList_GetItem(list, i); if (item == NULL) return 0; if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Bitmaps is not dictionary", i); return 0; } if (!BitmapFromPython(item, &(bmp->Bitmap[i]))) return 0; } return 1; } PyObject *MultiBitmapToPython(GSM_MultiBitmap * bmp) { PyObject *val; PyObject *item; int i; val = PyList_New(0); if (val == NULL) return NULL; for (i = 0; i < bmp->Number; i++) { item = BitmapToPython(&(bmp->Bitmap[i])); if (item == NULL) { Py_DECREF(val); return NULL; } if (PyList_Append(val, item) != 0) { Py_DECREF(item); Py_DECREF(val); return NULL; } Py_DECREF(item); } return val; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/calendar.c0000644000175000017500000004150400000000000021154 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Calendar related conversions */ #include "convertors.h" #include "misc.h" char *CalendarTypeToString(GSM_CalendarNoteType p) { char *s = NULL; switch (p) { case GSM_CAL_REMINDER: s = strdup("REMINDER"); break; case GSM_CAL_CALL: s = strdup("CALL"); break; case GSM_CAL_MEETING: s = strdup("MEETING"); break; case GSM_CAL_BIRTHDAY: s = strdup("BIRTHDAY"); break; case GSM_CAL_MEMO: s = strdup("MEMO"); break; case GSM_CAL_SHOPPING: s = strdup("SHOPPING"); break; case GSM_CAL_TRAVEL: s = strdup("TRAVEL"); break; case GSM_CAL_VACATION: s = strdup("VACATION"); break; case GSM_CAL_T_ATHL: s = strdup("T_ATHL"); break; case GSM_CAL_T_BALL: s = strdup("T_BALL"); break; case GSM_CAL_T_CYCL: s = strdup("T_CYCL"); break; case GSM_CAL_T_BUDO: s = strdup("T_BUDO"); break; case GSM_CAL_T_DANC: s = strdup("T_DANC"); break; case GSM_CAL_T_EXTR: s = strdup("T_EXTR"); break; case GSM_CAL_T_FOOT: s = strdup("T_FOOT"); break; case GSM_CAL_T_GOLF: s = strdup("T_GOLF"); break; case GSM_CAL_T_GYM: s = strdup("T_GYM"); break; case GSM_CAL_T_HORS: s = strdup("T_HORS"); break; case GSM_CAL_T_HOCK: s = strdup("T_HOCK"); break; case GSM_CAL_T_RACE: s = strdup("T_RACE"); break; case GSM_CAL_T_RUGB: s = strdup("T_RUGB"); break; case GSM_CAL_T_SAIL: s = strdup("T_SAIL"); break; case GSM_CAL_T_STRE: s = strdup("T_STRE"); break; case GSM_CAL_T_SWIM: s = strdup("T_SWIM"); break; case GSM_CAL_T_TENN: s = strdup("T_TENN"); break; case GSM_CAL_T_TRAV: s = strdup("T_TRAV"); break; case GSM_CAL_T_WINT: s = strdup("T_WINT"); break; case GSM_CAL_ALARM: s = strdup("ALARM"); break; case GSM_CAL_DAILY_ALARM: s = strdup("DAILY_ALARM"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for CalendarType from Gammu: '%d'", p); return NULL; } return s; } GSM_CalendarNoteType StringToCalendarType(const char *s) { if (strcmp("REMINDER", s) == 0) return GSM_CAL_REMINDER; else if (strcmp("CALL", s) == 0) return GSM_CAL_CALL; else if (strcmp("MEETING", s) == 0) return GSM_CAL_MEETING; else if (strcmp("BIRTHDAY", s) == 0) return GSM_CAL_BIRTHDAY; else if (strcmp("SHOPPING", s) == 0) return GSM_CAL_SHOPPING; else if (strcmp("MEMO", s) == 0) return GSM_CAL_MEMO; else if (strcmp("TRAVEL", s) == 0) return GSM_CAL_TRAVEL; else if (strcmp("VACATION", s) == 0) return GSM_CAL_VACATION; else if (strcmp("T_ATHL", s) == 0) return GSM_CAL_T_ATHL; else if (strcmp("T_BALL", s) == 0) return GSM_CAL_T_BALL; else if (strcmp("T_CYCL", s) == 0) return GSM_CAL_T_CYCL; else if (strcmp("T_BUDO", s) == 0) return GSM_CAL_T_BUDO; else if (strcmp("T_DANC", s) == 0) return GSM_CAL_T_DANC; else if (strcmp("T_EXTR", s) == 0) return GSM_CAL_T_EXTR; else if (strcmp("T_FOOT", s) == 0) return GSM_CAL_T_FOOT; else if (strcmp("T_GOLF", s) == 0) return GSM_CAL_T_GOLF; else if (strcmp("T_GYM", s) == 0) return GSM_CAL_T_GYM; else if (strcmp("T_HORS", s) == 0) return GSM_CAL_T_HORS; else if (strcmp("T_HOCK", s) == 0) return GSM_CAL_T_HOCK; else if (strcmp("T_RACE", s) == 0) return GSM_CAL_T_RACE; else if (strcmp("T_RUGB", s) == 0) return GSM_CAL_T_RUGB; else if (strcmp("T_SAIL", s) == 0) return GSM_CAL_T_SAIL; else if (strcmp("T_STRE", s) == 0) return GSM_CAL_T_STRE; else if (strcmp("T_SWIM", s) == 0) return GSM_CAL_T_SWIM; else if (strcmp("T_TENN", s) == 0) return GSM_CAL_T_TENN; else if (strcmp("T_TRAV", s) == 0) return GSM_CAL_T_TRAV; else if (strcmp("T_WINT", s) == 0) return GSM_CAL_T_WINT; else if (strcmp("ALARM", s) == 0) return GSM_CAL_ALARM; else if (strcmp("DAILY_ALARM", s) == 0) return GSM_CAL_DAILY_ALARM; PyErr_Format(PyExc_MemoryError, "Bad value for Calendar Type '%s'", s); return 0; } PyObject *CalendarToPython(const GSM_CalendarEntry * entry) { PyObject *v; PyObject *f; PyObject *r; PyObject *d; int i; Py_UNICODE *s; char *t; GSM_DateTime dt; int ignore; v = PyList_New(0); if (v == NULL) return NULL; for (i = 0; i < entry->EntriesNum; i++) { f = Py_None; ignore = 0; switch (entry->Entries[i].EntryType) { case CAL_START_DATETIME: /* Fixup date */ dt = entry->Entries[i].Date; if (dt.Hour == 255) { dt.Hour = 0; } if (dt.Minute == 255) { dt.Minute = 0; } if (dt.Second == 255) { dt.Second = 0; } d = BuildPythonDateTime(&dt); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "START_DATETIME", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_END_DATETIME: /* Fixup date */ dt = entry->Entries[i].Date; if (dt.Year == 0) { /* Ignore, there can be none end date. */ ignore = 1; break; } if (dt.Hour == 255) { dt.Hour = 23; } if (dt.Minute == 255) { dt.Minute = 59; } if (dt.Second == 255) { dt.Second = 59; } d = BuildPythonDateTime(&dt); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "END_DATETIME", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_TONE_ALARM_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "TONE_ALARM_DATETIME", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_SILENT_ALARM_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "SILENT_ALARM_DATETIME", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_LAST_MODIFIED: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "LAST_MODIFIED", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_REPEAT_STARTDATE: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "REPEAT_STARTDATE", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_REPEAT_STOPDATE: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O,s:i}", "Type", "REPEAT_STOPDATE", "Value", d, "AddError", (int)entry->Entries[i]. AddError); Py_DECREF(d); break; case CAL_TEXT: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u,s:i}", "Type", "TEXT", "Value", s, "AddError", (int)entry->Entries[i]. AddError); free(s); break; case CAL_DESCRIPTION: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u,s:i}", "Type", "DESCRIPTION", "Value", s, "AddError", (int)entry->Entries[i]. AddError); free(s); break; case CAL_LUID: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u,s:i}", "Type", "LUID", "Value", s, "AddError", (int)entry->Entries[i]. AddError); free(s); break; case CAL_LOCATION: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u,s:i}", "Type", "LOCATION", "Value", s, "AddError", (int)entry->Entries[i]. AddError); free(s); break; case CAL_PHONE: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u,s:i}", "Type", "PHONE", "Value", s, "AddError", (int)entry->Entries[i]. AddError); free(s); break; case CAL_PRIVATE: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "PRIVATE", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_CONTACTID: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "CONTACTID", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_DAYOFWEEK: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_DAYOFWEEK", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_DAY: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_DAY", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_WEEKOFMONTH: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_WEEKOFMONTH", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_MONTH: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_MONTH", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_FREQUENCY: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_FREQUENCY", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_COUNT: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_COUNT", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; case CAL_REPEAT_DAYOFYEAR: f = Py_BuildValue("{s:s,s:i,s:i}", "Type", "REPEAT_DAYOFYEAR", "Value", entry->Entries[i].Number, "AddError", (int)entry->Entries[i]. AddError); break; } if (ignore) { continue; } if (f == Py_None) { Py_DECREF(v); PyErr_Format(PyExc_ValueError, "Bad Calendar item type from gammu: %d", entry->Entries[i].EntryType); return NULL; } if (f == NULL) { Py_DECREF(v); return NULL; } if (PyList_Append(v, f) != 0) { Py_DECREF(f); Py_DECREF(v); return NULL; } Py_DECREF(f); } t = CalendarTypeToString(entry->Type); if (t == NULL) { Py_DECREF(v); return NULL; } r = Py_BuildValue("{s:i,s:s,s:O}", "Location", entry->Location, "Type", t, "Entries", v); free(t); Py_DECREF(v); return r; } int CalendarFromPython(PyObject * dict, GSM_CalendarEntry * entry, int needs_location) { PyObject *o; PyObject *item; Py_ssize_t len; Py_ssize_t i; char *t; char *type; char valuetype; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "Calendar entry is not a dictionary"); return 0; } memset(entry, 0, sizeof(GSM_CalendarEntry)); if (needs_location) { entry->Location = GetIntFromDict(dict, "Location"); if (entry->Location == INT_INVALID) return 0; } t = GetCharFromDict(dict, "Type"); if (t == NULL) return 0; entry->Type = StringToCalendarType(t); free(t); if (entry->Type == 0) return 0; o = PyDict_GetItemString(dict, "Entries"); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Can not get string value for key Values"); return 0; } if (!PyList_Check(o)) { PyErr_Format(PyExc_ValueError, "Key Values doesn't contain list"); return 0; } len = PyList_Size(o); if (len > GSM_CALENDAR_ENTRIES) { pyg_warning("Using just %i entries from list!", GSM_CALENDAR_ENTRIES); len = GSM_CALENDAR_ENTRIES; } entry->EntriesNum = len; for (i = 0; i < len; i++) { item = PyList_GetItem(o, i); if (item == NULL) return 0; if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Values is not dictionary", i); return 0; } type = GetCharFromDict(item, "Type"); if (type == NULL) return 0; if (strcmp("START_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = CAL_START_DATETIME; } else if (strcmp("END_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = CAL_END_DATETIME; } else if (strcmp("TONE_ALARM_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = CAL_TONE_ALARM_DATETIME; } else if (strcmp("SILENT_ALARM_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = CAL_SILENT_ALARM_DATETIME; } else if (strcmp("LAST_MODIFIED", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = CAL_LAST_MODIFIED; } else if (strcmp("REPEAT_STARTDATE", type) == 0) { valuetype = 'D'; entry->Entries[i].EntryType = CAL_REPEAT_STARTDATE; } else if (strcmp("REPEAT_STOPDATE", type) == 0) { valuetype = 'D'; entry->Entries[i].EntryType = CAL_REPEAT_STOPDATE; } else if (strcmp("TEXT", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = CAL_TEXT; } else if (strcmp("DESCRIPTION", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = CAL_DESCRIPTION; } else if (strcmp("LUID", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = CAL_LUID; } else if (strcmp("LOCATION", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = CAL_LOCATION; } else if (strcmp("PHONE", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = CAL_PHONE; } else if (strcmp("PRIVATE", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_PRIVATE; } else if (strcmp("CONTACTID", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_CONTACTID; } else if (strcmp("REPEAT_DAYOFWEEK", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_DAYOFWEEK; } else if (strcmp("REPEAT_DAY", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_DAY; } else if (strcmp("REPEAT_WEEKOFMONTH", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_WEEKOFMONTH; } else if (strcmp("REPEAT_MONTH", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_MONTH; } else if (strcmp("REPEAT_FREQUENCY", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_FREQUENCY; } else if (strcmp("REPEAT_COUNT", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_COUNT; } else if (strcmp("REPEAT_DAYOFYEAR", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = CAL_REPEAT_DAYOFYEAR; } else { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Values has bad type: %s", i, type); free(type); return 0; } free(type); switch (valuetype) { case 'n': entry->Entries[i].Number = GetIntFromDict(item, "Value"); if (entry->Entries[i].Number == INT_INVALID) return 0; break; case 't': if (!CopyStringFromDict (item, "Value", GSM_PHONEBOOK_TEXT_LENGTH, entry->Entries[i].Text)) return 0; break; case 'D': entry->Entries[i].Date = GetDateFromDict(item, "Value"); if (entry->Entries[i].Date.Year == -1) return 0; break; case 'd': entry->Entries[i].Date = GetDateTimeFromDict(item, "Value"); if (entry->Entries[i].Date.Year == -1) return 0; break; } /* Clear AddError flag */ entry->Entries[i].AddError = ERR_NONE; } /* end for */ return 1; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/call.c0000644000175000017500000000504200000000000020313 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Call related conversions */ #include "convertors.h" char *CallStatusToString(GSM_CallStatus ct) { char *s = NULL; switch (ct) { case GSM_CALL_IncomingCall: s = strdup("IncomingCall"); break; case GSM_CALL_OutgoingCall: s = strdup("OutgoingCall"); break; case GSM_CALL_CallStart: s = strdup("CallStart"); break; case GSM_CALL_CallEnd: s = strdup("CallEnd"); break; case GSM_CALL_CallRemoteEnd: s = strdup("CallRemoteEnd"); break; case GSM_CALL_CallLocalEnd: s = strdup("CallLocalEnd"); break; case GSM_CALL_CallEstablished: s = strdup("CallEstablished"); break; case GSM_CALL_CallHeld: s = strdup("CallHeld"); break; case GSM_CALL_CallResumed: s = strdup("CallResumed"); break; case GSM_CALL_CallSwitched: s = strdup("CallSwitched"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for CallStatus from Gammu: '%d'", ct); return NULL; } return s; } PyObject *CallToPython(GSM_Call * call) { PyObject *number; PyObject *result; char *status; number = UnicodeStringToPython(call->PhoneNumber); if (number == NULL) { return NULL; } status = CallStatusToString(call->Status); if (status == NULL) { Py_DECREF(number); return NULL; } if (call->CallIDAvailable) { result = Py_BuildValue("{s:s,s:O,s:i,s:i}", "Status", status, "Number", number, "CallID", call->CallID, "StatusCode", call->StatusCode); } else { result = Py_BuildValue("{s:s,s:O,s:i}", "Status", status, "Number", number, "StatusCode", call->StatusCode); } Py_DECREF(number); free(status); return result; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/diverts.c0000644000175000017500000001063700000000000021066 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Call diverts related conversions */ #include "convertors.h" GSM_Divert_CallTypes DivertCallTypeFromString(const char *str) { if (strcasecmp(str, "Voice") == 0) { return GSM_DIVERT_VoiceCalls; } else if (strcasecmp(str, "Fax") == 0) { return GSM_DIVERT_FaxCalls; } else if (strcasecmp(str, "Data") == 0) { return GSM_DIVERT_DataCalls; } else if (strcasecmp(str, "All") == 0) { return GSM_DIVERT_AllCalls; } else { PyErr_Format(PyExc_ValueError, "Bad value for GSM_Divert_CallTypes: %s", str); return 0; } } char *DivertCallTypeToString(GSM_Divert_CallTypes ct) { char *s = NULL; switch (ct) { case GSM_DIVERT_VoiceCalls: s = strdup("Voice"); break; case GSM_DIVERT_FaxCalls: s = strdup("Fax"); break; case GSM_DIVERT_DataCalls: s = strdup("Data"); break; case GSM_DIVERT_AllCalls: s = strdup("All"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_Divert_CallTypes from Gammu: '%d'", ct); return NULL; } return s; } GSM_Divert_DivertTypes DivertTypeFromString(const char *str) { if (strcasecmp(str, "Busy") == 0) { return GSM_DIVERT_Busy; } else if (strcasecmp(str, "NoAnswer") == 0) { return GSM_DIVERT_NoAnswer; } else if (strcasecmp(str, "OutOfReach") == 0) { return GSM_DIVERT_OutOfReach; } else if (strcasecmp(str, "AllTypes") == 0) { return GSM_DIVERT_AllTypes; } else { PyErr_Format(PyExc_ValueError, "Bad value for GSM_Divert_DivertTypes: %s", str); return 0; } } char *DivertTypeToString(GSM_Divert_DivertTypes ct) { char *s = NULL; switch (ct) { case GSM_DIVERT_Busy: s = strdup("Busy"); break; case GSM_DIVERT_NoAnswer: s = strdup("NoAnswer"); break; case GSM_DIVERT_OutOfReach: s = strdup("OutOfReach"); break; case GSM_DIVERT_AllTypes: s = strdup("AllTypes"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_Divert_DivertTypes from Gammu: '%d'", ct); return NULL; } return s; } PyObject *CallDivertsToPython(GSM_MultiCallDivert *cd) { int i; PyObject *ret, *num, *entry; char *dt, *ct; ret = PyList_New(0); for (i = 0; i < cd->EntriesNum; i++) { num = UnicodeStringToPython(cd->Entries[i].Number); if (num == NULL) { Py_DECREF(ret); return NULL; } dt = DivertTypeToString(cd->Entries[i].DivertType); if (dt == NULL) { Py_DECREF(ret); Py_DECREF(num); return NULL; } ct = DivertCallTypeToString(cd->Entries[i].CallType); if (ct == NULL) { Py_DECREF(ret); Py_DECREF(num); free(dt); return NULL; } entry = Py_BuildValue("{s:s,s:s,s:O,s:i}", "DivertType", dt, "CallType", ct, "Number", num, "Timeout", cd->Entries[i].Timeout); Py_DECREF(num); free(dt); free(ct); if (entry == NULL) { Py_DECREF(ret); return NULL; } if (PyList_Append(ret, entry) != 0) { Py_DECREF(ret); Py_DECREF(entry); return NULL; } Py_DECREF(entry); } return ret; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/file.c0000644000175000017500000001667700000000000020337 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* File related conversions */ #include "convertors.h" #include "misc.h" #include char *FileTypeToString(GSM_FileType type) { char *s = NULL; if (type == 0) { /* 0 can be valid for folders? If handled inside switch, gcc complains */ s = strdup(""); } else { switch (type) { case GSM_File_Java_JAR: s = strdup("Java_JAR"); break; case GSM_File_Image_JPG: s = strdup("Image_JPG"); break; case GSM_File_Image_BMP: s = strdup("Image_BMP"); break; case GSM_File_Image_GIF: s = strdup("Image_GIF"); break; case GSM_File_Image_PNG: s = strdup("Image_PNG"); break; case GSM_File_Image_WBMP: s = strdup("Image_WBMP"); break; case GSM_File_Video_3GP: s = strdup("Video_3GP"); break; case GSM_File_Sound_AMR: s = strdup("Sound_AMR"); break; case GSM_File_Sound_NRT: s = strdup("Sound_NRT"); break; case GSM_File_Sound_MIDI: s = strdup("Sound_MIDI"); break; case GSM_File_MMS: s = strdup("MMS"); break; case GSM_File_Other: s = strdup("Other"); break; case GSM_File_INVALID: s = strdup(""); break; } } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_FileType from Gammu: '%d'", type); return NULL; } return s; } GSM_FileType StringToFileType(char *s) { if (strcmp("Java_JAR", s) == 0) return GSM_File_Java_JAR; else if (strcmp("Image_JPG", s) == 0) return GSM_File_Image_JPG; else if (strcmp("Image_BMP", s) == 0) return GSM_File_Image_BMP; else if (strcmp("Image_GIF", s) == 0) return GSM_File_Image_GIF; else if (strcmp("Image_PNG", s) == 0) return GSM_File_Image_PNG; else if (strcmp("Image_WBMP", s) == 0) return GSM_File_Image_WBMP; else if (strcmp("Video_3GP", s) == 0) return GSM_File_Video_3GP; else if (strcmp("Sound_AMR", s) == 0) return GSM_File_Sound_AMR; else if (strcmp("Sound_NRT", s) == 0) return GSM_File_Sound_NRT; else if (strcmp("Sound_MIDI", s) == 0) return GSM_File_Sound_MIDI; else if (strcmp("MMS", s) == 0) return GSM_File_MMS; else if (strcmp("Other", s) == 0) return GSM_File_Other; else if (strlen(s) == 0) return 0; PyErr_Format(PyExc_ValueError, "Bad value for GSM_FileType '%s'", s); return GSM_File_INVALID; } PyObject *FileToPython(GSM_File * file) { PyObject *name; PyObject *fullname; PyObject *buffer; PyObject *dt; char *type; PyObject *val; name = UnicodeStringToPython(file->Name); if (name == NULL) { return NULL; } type = FileTypeToString(file->Type); if (type == NULL) { Py_DECREF(name); return NULL; } fullname = UnicodeStringToPython(file->ID_FullName); if (fullname == NULL) { Py_DECREF(name); free(type); return NULL; } buffer = PyBytes_FromStringAndSize((char *)file->Buffer, file->Used); if (buffer == NULL) { Py_DECREF(name); free(type); Py_DECREF(fullname); return NULL; } if (file->ModifiedEmpty) { file->Modified.Year = 0; } dt = BuildPythonDateTime(&(file->Modified)); if (dt == NULL) { Py_DECREF(name); free(type); Py_DECREF(fullname); Py_DECREF(buffer); return NULL; } val = Py_BuildValue("{s:i,s:O,s:i,s:i,s:s,s:O,s:O,s:O,s:i,s:i,s:i,s:i}", "Used", file->Used, "Name", name, "Folder", (int)file->Folder, "Level", file->Level, "Type", type, "ID_FullName", fullname, "Buffer", buffer, "Modified", dt, "Protected", (int)file->Protected, "ReadOnly", (int)file->ReadOnly, "Hidden", (int)file->Hidden, "System", (int)file->System); Py_DECREF(name); free(type); Py_DECREF(fullname); Py_DECREF(buffer); Py_DECREF(dt); return val; } int FileFromPython(PyObject * dict, GSM_File * file, gboolean check) { char *s; GSM_DateTime nulldt = { 0, 0, 0, 0, 0, 0, 0 }; Py_ssize_t i; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "File is not a dictionary"); return 0; } memset(file, 0, sizeof(GSM_File)); if ((file->Used = GetIntFromDict(dict, "Used")) == INT_INVALID) { // We don't need Used in all cases, we can get size from buffer PyErr_Clear(); } if (!CopyStringFromDict(dict, "Name", 300, file->Name)) { if (check) { return 0; } else { PyErr_Clear(); } } if ((i = GetIntFromDict(dict, "Folder")) == INT_INVALID) { if (check) { return 0; } else { PyErr_Clear(); } } else { file->Folder = i; } if ((file->Level = GetIntFromDict(dict, "Level")) == INT_INVALID) { if (check) { return 0; } else { PyErr_Clear(); } } s = GetCharFromDict(dict, "Type"); if (s == NULL) { file->Type = 0; if (check) { return 0; } else { PyErr_Clear(); } } else { file->Type = StringToFileType(s); free(s); if (file->Type == GSM_File_INVALID) { return 0; } } if (!CopyStringFromDict(dict, "ID_FullName", 800, file->ID_FullName)) { if (check) { return 0; } else { PyErr_Clear(); } } s = GetDataFromDict(dict, "Buffer", &i); if (s == NULL) { file->Buffer = NULL; file->Used = 0; if (check) { return 0; } else { PyErr_Clear(); } } else { if (file->Used == INT_INVALID) { file->Used = i; } else if (file->Used != (size_t) i) { PyErr_Format(PyExc_ValueError, "Used and Buffer size mismatch in File (%li != %" PY_FORMAT_SIZE_T "i)!", (long)file->Used, i); return 0; } file->Buffer = (unsigned char *)malloc(i * sizeof(unsigned char)); if (file->Buffer == NULL) { PyErr_Format(PyExc_MemoryError, "Not enough memory to allocate buffer (wanted %li bytes)", (long)(i * sizeof(unsigned char))); return 0; } memcpy(file->Buffer, s, i); } file->Modified = GetDateTimeFromDict(dict, "Modified"); if (file->Modified.Year == -1) { file->Modified = nulldt; file->ModifiedEmpty = TRUE; PyErr_Clear(); } else { file->ModifiedEmpty = FALSE; } if ((i = GetIntFromDict(dict, "Protected")) == INT_INVALID) { if (check) { free(file->Buffer); file->Buffer = NULL; return 0; } else { PyErr_Clear(); } } else { file->Protected = i; } if ((i = GetIntFromDict(dict, "ReadOnly")) == INT_INVALID) { if (check) { free(file->Buffer); file->Buffer = NULL; return 0; } else { PyErr_Clear(); } } else { file->ReadOnly = i; } if ((i = GetIntFromDict(dict, "Hidden")) == INT_INVALID) { if (check) { free(file->Buffer); file->Buffer = NULL; return 0; } else { PyErr_Clear(); } } else { file->Hidden = i; } if ((i = GetIntFromDict(dict, "System")) == INT_INVALID) { if (check) { free(file->Buffer); file->Buffer = NULL; return 0; } else { PyErr_Clear(); } } else { file->System = i; } return 1; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/memory.c0000644000175000017500000005030300000000000020710 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* MemoryEntry conversions */ #undef USE_PREF_UNICODE #include "convertors.h" #include "misc.h" #include const char *LocationToString(GSM_EntryLocation location) { switch (location) { case PBK_Location_Home: return "Home"; case PBK_Location_Work: return "Work"; case PBK_Location_Unknown: return "Unknown"; } return "Unknown"; } #define convert_text(name) \ s = strGammuToPython(entry->Entries[i].Text); \ if (s == NULL) { \ Py_DECREF(v); \ return NULL; \ } \ f = Py_BuildValue("{s:s,s:u,s:i,s:s}", "Type", name, "Value", s, "AddError", (int)entry->Entries[i].AddError, "Location", LocationToString(entry->Entries[i].Location)); \ free(s); #define convert_number(name) \ convert_text("Number_" name); \ /* VoiceTag */ \ PyDict_SetItemString(f, "VoiceTag", PyLong_FromLong((int)entry->Entries[i].VoiceTag)); \ /* SMSList */ \ l = PyList_New(0); \ j = 0; \ while (entry->Entries[i].SMSList[j] != 0) { \ PyList_Append(l, PyLong_FromLong((int)entry->Entries[i].SMSList[j])); \ j++; \ } \ PyDict_SetItemString(f, "SMSList", l); \ Py_DECREF(l); PyObject *MemoryEntryToPython(const GSM_MemoryEntry * entry) { PyObject *v; PyObject *f; PyObject *r; PyObject *d; PyObject *l; int i; int j; Py_UNICODE *s; char *t; const GSM_BinaryPicture *bitmap; const char *bmptype; v = PyList_New(0); if (v == NULL) return NULL; for (i = 0; i < entry->EntriesNum; i++) { f = Py_None; switch (entry->Entries[i].EntryType) { case PBK_Number_General: convert_number("General"); break; case PBK_Number_Mobile: convert_number("Mobile"); break; case PBK_Number_Fax: convert_number("Fax"); break; case PBK_Number_Pager: convert_number("Pager"); break; case PBK_Number_Other: convert_number("Other"); break; case PBK_Text_Note: convert_text("Text_Note"); break; case PBK_Text_Postal: convert_text("Text_Postal"); break; case PBK_Text_Email: convert_text("Text_Email"); break; case PBK_Text_Email2: convert_text("Text_Email2"); break; case PBK_Text_URL: convert_text("Text_URL"); break; case PBK_Date: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "Date", "Value", d); Py_DECREF(d); break; case PBK_LastModified: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "LastModified", "Value", d); Py_DECREF(d); break; case PBK_Caller_Group: f = Py_BuildValue("{s:s,s:i}", "Type", "Caller_Group", "Value", entry->Entries[i].Number); break; case PBK_Text_Name: convert_text("Text_Name"); break; case PBK_Text_LastName: convert_text("Text_LastName"); break; case PBK_Text_FirstName: convert_text("Text_FirstName"); break; case PBK_Text_SecondName: convert_text("Text_SecondName"); break; case PBK_Text_NickName: convert_text("Text_NickName"); break; case PBK_Text_FormalName: convert_text("Text_FormalName"); break; case PBK_Text_NamePrefix: convert_text("Text_NamePrefix"); break; case PBK_Text_NameSuffix: convert_text("Text_NameSuffix"); break; case PBK_Text_Company: convert_text("Text_Company"); break; case PBK_Text_JobTitle: convert_text("Text_JobTitle"); break; case PBK_Category: if (entry->Entries[i].Number == -1) { convert_text("Category"); } else { f = Py_BuildValue("{s:s,s:i}", "Type", "Category", "Value", entry->Entries[i]. Number); } break; case PBK_Private: f = Py_BuildValue("{s:s,s:i}", "Type", "Private", "Value", entry->Entries[i].Number); break; case PBK_Text_StreetAddress: convert_text("Text_StreetAddress"); break; case PBK_Text_City: convert_text("Text_City"); break; case PBK_Text_State: convert_text("Text_State"); break; case PBK_Text_Zip: convert_text("Text_Zip"); break; case PBK_Text_Country: convert_text("Text_Country"); break; case PBK_Text_Custom1: convert_text("Text_Custom1"); break; case PBK_Text_Custom2: convert_text("Text_Custom2"); break; case PBK_Text_Custom3: convert_text("Text_Custom3"); break; case PBK_Text_Custom4: convert_text("Text_Custom4"); break; case PBK_Text_LUID: convert_text("Text_LUID"); break; case PBK_Text_VOIP: convert_text("Text_VOIP"); break; case PBK_Text_SWIS: convert_text("Text_SWIS"); break; case PBK_Text_WVID: convert_text("Text_WVID"); break; case PBK_Text_SIP: convert_text("Text_SIP"); break; case PBK_Text_DTMF: convert_text("Text_DTMF"); break; case PBK_Text_UserID: convert_text("Text_UserID"); break; case PBK_Text_PictureName: convert_text("Text_PictureName"); break; case PBK_RingtoneID: f = Py_BuildValue("{s:s,s:O}", "Type", "RingtoneID", "Value", PyLong_FromUnsignedLong (entry->Entries[i].Number)); break; case PBK_PictureID: f = Py_BuildValue("{s:s,s:O}", "Type", "PictureID", "Value", PyLong_FromUnsignedLong (entry->Entries[i].Number)); break; case PBK_CallLength: f = Py_BuildValue("{s:s,s:i}", "Type", "CallLength", "Value", entry->Entries[i].CallLength); break; case PBK_Number_Messaging: convert_number("Messaging"); break; case PBK_Number_Video: convert_number("Video"); break; case PBK_PushToTalkID: convert_text("PushToTalkID"); break; case PBK_Photo: bitmap = &(entry->Entries[i].Picture); d = PyBytes_FromStringAndSize((char *)bitmap-> Buffer, bitmap->Length); if (d == NULL) { Py_DECREF(v); return NULL; } bmptype = ""; switch (bitmap->Type) { case PICTURE_BMP: bmptype = "BMP"; break; case PICTURE_GIF: bmptype = "GIF"; break; case PICTURE_JPG: bmptype = "JPG"; break; case PICTURE_ICN: bmptype = "ICN"; break; case PICTURE_PNG: bmptype = "PNG"; break; } f = Py_BuildValue("{s:s,s:O,s:s}", "Type", "Photo", "Value", d, "PictureType", bmptype); Py_DECREF(d); break; } if (f == Py_None) { Py_DECREF(v); PyErr_Format(PyExc_ValueError, "Bad MemoryEntry item type from gammu: %d", entry->Entries[i].EntryType); return NULL; } if (f == NULL) { Py_DECREF(v); return NULL; } if (PyList_Append(v, f) != 0) { Py_DECREF(f); Py_DECREF(v); return NULL; } Py_DECREF(f); } t = MemoryTypeToString(entry->MemoryType); if (t == NULL) { Py_DECREF(v); return NULL; } r = Py_BuildValue("{s:i,s:s,s:O}", "Location", entry->Location, "MemoryType", t, "Entries", v); free(t); Py_DECREF(v); return r; } int MemoryEntryFromPython(PyObject * dict, GSM_MemoryEntry * entry, int needs_location) { PyObject *o; PyObject *item; Py_ssize_t len, data_len; Py_ssize_t i; char *type, *location; char valuetype; char *bmptype; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "Memory entry is not a dictionary"); return 0; } memset(entry, 0, sizeof(GSM_MemoryEntry)); entry->Location = GetIntFromDict(dict, "Location"); if (entry->Location == INT_INVALID) { if (needs_location) { return 0; } PyErr_Clear(); } entry->MemoryType = GetMemoryTypeFromDict(dict, "MemoryType"); if (entry->MemoryType == MEM_INVALID) { if (needs_location) { return 0; } PyErr_Clear(); } o = PyDict_GetItemString(dict, "Entries"); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Can not get string value for key Entries"); return 0; } if (!PyList_Check(o)) { PyErr_Format(PyExc_ValueError, "Key Entries doesn't contain list"); return 0; } len = PyList_Size(o); if (len > GSM_PHONEBOOK_ENTRIES) { pyg_warning("Using just %i entries from list!", GSM_PHONEBOOK_ENTRIES); len = GSM_PHONEBOOK_ENTRIES; } entry->EntriesNum = len; for (i = 0; i < len; i++) { item = PyList_GetItem(o, i); if (item == NULL) return 0; if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Entries is not dictionary", i); return 0; } type = GetCharFromDict(item, "Type"); if (type == NULL) return 0; location = GetCharFromDict(item, "Location"); if (location == NULL) { PyErr_Clear(); entry->Entries[i].Location = PBK_Location_Unknown; } else { if (strcmp(location, "Home") == 0) { entry->Entries[i].Location = PBK_Location_Home; } else if (strcmp(location, "Work") == 0) { entry->Entries[i].Location = PBK_Location_Work; } else { entry->Entries[i].Location = PBK_Location_Unknown; } free(location); } /* Zero everything, just to be sure */ entry->Entries[i].Text[0] = 0; entry->Entries[i].Text[1] = 0; entry->Entries[i].SMSList[0] = 0; entry->Entries[i].Number = 0; /* Get VoiceTag flag */ entry->Entries[i].VoiceTag = GetIntFromDict(item, "VoiceTag"); if (entry->Entries[i].VoiceTag == INT_INVALID) { entry->Entries[i].VoiceTag = 0; PyErr_Clear(); } /* Clear AddError flag */ entry->Entries[i].AddError = ERR_NONE; if (strcmp("Number_General", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_General; } else if (strcmp("Number_Mobile_Work", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Mobile; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Number_Mobile_Home", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Mobile; entry->Entries[i].Location = PBK_Location_Home; } else if (strcmp("Number_Mobile", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Mobile; } else if (strcmp("Number_Work", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_General; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Number_Fax", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Fax; } else if (strcmp("Number_Home", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_General; entry->Entries[i].Location = PBK_Location_Home; } else if (strcmp("Number_Pager", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Pager; } else if (strcmp("Number_Other", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Other; } else if (strcmp("Number_Messaging", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Messaging; } else if (strcmp("Number_Video", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Number_Video; } else if (strcmp("Text_Note", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Note; } else if (strcmp("Text_Postal", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Postal; } else if (strcmp("Text_WorkPostal", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Postal; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Text_Email", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Email; } else if (strcmp("Text_Email2", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Email2; } else if (strcmp("Text_URL", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_URL; } else if (strcmp("Date", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = PBK_Date; } else if (strcmp("LastModified", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = PBK_LastModified; } else if (strcmp("Caller_Group", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = PBK_Caller_Group; } else if (strcmp("Text_Name", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Name; } else if (strcmp("Text_LastName", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_LastName; } else if (strcmp("Text_FirstName", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_FirstName; } else if (strcmp("Text_SecondName", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_SecondName; } else if (strcmp("Text_NickName", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_NickName; } else if (strcmp("Text_FormalName", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_FormalName; } else if (strcmp("Text_NameSuffix", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_NameSuffix; } else if (strcmp("Text_NamePrefix", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_NamePrefix; } else if (strcmp("Text_Company", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Company; } else if (strcmp("Text_JobTitle", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_JobTitle; } else if (strcmp("Category", type) == 0) { valuetype = 'o'; entry->Entries[i].EntryType = PBK_Category; } else if (strcmp("Private", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = PBK_Private; } else if (strcmp("Text_StreetAddress", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_StreetAddress; } else if (strcmp("Text_City", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_City; } else if (strcmp("Text_State", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_State; } else if (strcmp("Text_Zip", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Zip; } else if (strcmp("Text_Country", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Country; } else if (strcmp("Text_WorkStreetAddress", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_StreetAddress; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Text_WorkCity", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_City; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Text_WorkState", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_State; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Text_WorkZip", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Zip; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Text_WorkCountry", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Country; entry->Entries[i].Location = PBK_Location_Work; } else if (strcmp("Text_Custom1", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Custom1; } else if (strcmp("Text_Custom2", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Custom2; } else if (strcmp("Text_Custom3", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Custom3; } else if (strcmp("Text_Custom4", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_Custom4; } else if (strcmp("Text_LUID", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_LUID; } else if (strcmp("Text_VOIP", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_VOIP; } else if (strcmp("Text_SWIS", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_SWIS; } else if (strcmp("Text_WVID", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_WVID; } else if (strcmp("Text_SIP", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_SIP; } else if (strcmp("Text_DTMF", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_DTMF; } else if (strcmp("Text_UserID", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_UserID; } else if (strcmp("Text_PictureName", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_Text_PictureName; } else if (strcmp("RingtoneID", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = PBK_RingtoneID; } else if (strcmp("PictureID", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = PBK_PictureID; } else if (strcmp("CallLength", type) == 0) { valuetype = 'c'; entry->Entries[i].EntryType = PBK_CallLength; } else if (strcmp("PushToTalkID", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = PBK_PushToTalkID; } else if (strcmp("Photo", type) == 0) { valuetype = 'p'; entry->Entries[i].EntryType = PBK_Photo; } else { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Entries has bad type: %s", i, type); free(type); return 0; } free(type); switch (valuetype) { case 'o': entry->Entries[i].Number = GetIntFromDict(item, "Value"); if (entry->Entries[i].Number == INT_INVALID) { PyErr_Clear(); if (!CopyStringFromDict (item, "Value", GSM_PHONEBOOK_TEXT_LENGTH, entry->Entries[i].Text)) return 0; } break; case 'n': entry->Entries[i].Number = GetIntFromDict(item, "Value"); if (entry->Entries[i].Number == INT_INVALID) return 0; break; case 'c': entry->Entries[i].CallLength = GetIntFromDict(item, "Value"); if (entry->Entries[i].CallLength == INT_INVALID) return 0; break; case 't': if (!CopyStringFromDict (item, "Value", GSM_PHONEBOOK_TEXT_LENGTH, entry->Entries[i].Text)) return 0; break; case 'd': entry->Entries[i].Date = GetDateTimeFromDict(item, "Value"); if (entry->Entries[i].Date.Year == -1) return 0; break; case 'p': entry->Entries[i].Picture.Buffer = (unsigned char *) GetCStringLengthFromDict(item, "Value", &data_len); entry->Entries[i].Picture.Length = data_len; if (entry->Entries[i].Picture.Buffer == NULL) { return 0; } bmptype = GetCharFromDict(item, "PictureType"); if (bmptype == NULL) { entry->Entries[i].Picture.Type = 0; } else if (strcmp(bmptype, "BMP") == 0) { entry->Entries[i].Picture.Type = PICTURE_BMP; } else if (strcmp(bmptype, "GIF") == 0) { entry->Entries[i].Picture.Type = PICTURE_GIF; } else if (strcmp(bmptype, "JPG") == 0) { entry->Entries[i].Picture.Type = PICTURE_JPG; } else if (strcmp(bmptype, "ICN") == 0) { entry->Entries[i].Picture.Type = PICTURE_ICN; } else if (strcmp(bmptype, "PNG") == 0) { entry->Entries[i].Picture.Type = PICTURE_PNG; } else { entry->Entries[i].Picture.Type = 0; } free(bmptype); break; } } /* end for */ return 1; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/misc.c0000644000175000017500000000757700000000000020352 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Miscellaneous conversions, that didn't fit elsewhere */ #include "convertors.h" GSM_CategoryType StringToCategoryType(const char *s) { if (strcmp(s, "ToDo") == 0) return Category_ToDo; else if (strcmp(s, "Phonebook") == 0) return Category_Phonebook; else { PyErr_Format(PyExc_ValueError, "Bad value for category type: '%s'", s); return 0; } } GSM_MemoryType StringToMemoryType(const char *s) { GSM_MemoryType type; type = GSM_StringToMemoryType(s); if (type == 0) { PyErr_Format(PyExc_ValueError, "Bad value for memory type: '%s'", s); return ENUM_INVALID; } return type; } char *MemoryTypeToString(GSM_MemoryType t) { char *s; s = strdup(GSM_MemoryTypeToString(t)); if (s == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate string"); return NULL; } if (strcmp("XX", s) == 0) { PyErr_Format(PyExc_ValueError, "Bad value for MemoryType from Gammu: '%02x'", t); free(s); s = NULL; } return s; } GSM_MemoryType GetMemoryTypeFromDict(PyObject * dict, const char *key) { char *s; GSM_MemoryType result; s = GetCharFromDict(dict, key); if (s == NULL) return MEM_INVALID; result = StringToMemoryType(s); free(s); return result; } PyObject *CBToPython(GSM_CBMessage * cb) { return Py_BuildValue("{s:i,s:s}", "Channel", cb->Channel, "Text", cb->Text); } GSM_USSDStatus StringToUSSDStatus(const char *s) { if (strcmp(s, "Unknown") == 0) return USSD_Unknown; else if (strcmp(s, "NoActionNeeded") == 0) return USSD_NoActionNeeded; else if (strcmp(s, "ActionNeeded") == 0) return USSD_ActionNeeded; else if (strcmp(s, "Terminated") == 0) return USSD_Terminated; else if (strcmp(s, "AnotherClient") == 0) return USSD_AnotherClient; else if (strcmp(s, "NotSupported") == 0) return USSD_NotSupported; else if (strcmp(s, "Timeout") == 0) return USSD_Timeout; PyErr_Format(PyExc_ValueError, "Bad value for USSD Status '%s'", s); return 0; } char *USSDStatusToString(GSM_USSDStatus type) { char *s = NULL; switch (type) { case USSD_Unknown: s = strdup("Unknown"); break; case USSD_NoActionNeeded: s = strdup("NoActionNeeded"); break; case USSD_ActionNeeded: s = strdup("ActionNeeded"); break; case USSD_Terminated: s = strdup("Terminated"); break; case USSD_AnotherClient: s = strdup("AnotherClient"); break; case USSD_NotSupported: s = strdup("NotSupported"); break; case USSD_Timeout: s = strdup("Timeout"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for USSD Status from Gammu: '%d'", type); return NULL; } return s; } PyObject *USSDToPython(GSM_USSDMessage * ussd) { PyObject *text; PyObject *result; char *status; status = USSDStatusToString(ussd->Status); if (status == NULL) return NULL; text = UnicodeStringToPython(ussd->Text); if (text == NULL) { free(status); return NULL; } result = Py_BuildValue("{s:s,s:O}", "Status", status, "Text", text); Py_DECREF(text); free(status); return result; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/ringtone.c0000644000175000017500000003126700000000000021235 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Ringtones related conversions */ #include "convertors.h" #include "misc.h" char *RingNoteDurationToString(GSM_RingNoteDuration type) { char *s = NULL; switch (type) { case Duration_Full: s = strdup("Full"); break; case Duration_1_2: s = strdup("1_2"); break; case Duration_1_4: s = strdup("1_4"); break; case Duration_1_8: s = strdup("1_8"); break; case Duration_1_16: s = strdup("1_16"); break; case Duration_1_32: s = strdup("1_32"); break; case Duration_INVALID: s = strdup(""); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteDuration from Gammu: '%d'", type); return NULL; } return s; } GSM_RingNoteDuration StringToRingNoteDuration(char *s) { if (strcmp("Full", s) == 0) return Duration_Full; else if (strcmp("1_2", s) == 0) return Duration_1_2; else if (strcmp("1_4", s) == 0) return Duration_1_4; else if (strcmp("1_8", s) == 0) return Duration_1_8; else if (strcmp("1_16", s) == 0) return Duration_1_16; else if (strcmp("1_32", s) == 0) return Duration_1_32; PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteDuration '%s'", s); return Duration_INVALID; } char *RingNoteDurationSpecToString(GSM_RingNoteDurationSpec type) { char *s = NULL; switch (type) { case NoSpecialDuration: s = strdup("NoSpecialDuration"); break; case DottedNote: s = strdup("DottedNote"); break; case DoubleDottedNote: s = strdup("DoubleDottedNote"); break; case Length_2_3: s = strdup("Length_2_3"); break; case DurationSpec_INVALID: s = strdup(""); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteDurationSpec from Gammu: '%d'", type); return NULL; } return s; } GSM_RingNoteDurationSpec StringToRingNoteDurationSpec(char *s) { if (strcmp("NoSpecialDuration", s) == 0) return NoSpecialDuration; else if (strcmp("DottedNote", s) == 0) return DottedNote; else if (strcmp("DoubleDottedNote", s) == 0) return DoubleDottedNote; else if (strcmp("Length_2_3", s) == 0) return Length_2_3; PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteDurationSpec '%s'", s); return DurationSpec_INVALID; } char *RingNoteNoteToString(GSM_RingNoteNote type) { char *s = NULL; switch (type) { case Note_Pause: s = strdup("Pause"); break; case Note_C: s = strdup("C"); break; case Note_Cis: s = strdup("Cis"); break; case Note_D: s = strdup("D"); break; case Note_Dis: s = strdup("Dis"); break; case Note_E: s = strdup("E"); break; case Note_F: s = strdup("F"); break; case Note_Fis: s = strdup("Fis"); break; case Note_G: s = strdup("G"); break; case Note_Gis: s = strdup("Gis"); break; case Note_A: s = strdup("A"); break; case Note_Ais: s = strdup("Ais"); break; case Note_H: s = strdup("H"); break; case Note_INVALID: s = strdup(""); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteNote from Gammu: '%d'", type); return NULL; } return s; } GSM_RingNoteNote StringToRingNoteNote(char *s) { if (strcmp("Pause", s) == 0) return Note_Pause; else if (strcmp("C", s) == 0) return Note_C; else if (strcmp("Cis", s) == 0) return Note_Cis; else if (strcmp("D", s) == 0) return Note_D; else if (strcmp("Dis", s) == 0) return Note_Dis; else if (strcmp("E", s) == 0) return Note_E; else if (strcmp("F", s) == 0) return Note_F; else if (strcmp("Fis", s) == 0) return Note_Fis; else if (strcmp("G", s) == 0) return Note_G; else if (strcmp("Gis", s) == 0) return Note_Gis; else if (strcmp("A", s) == 0) return Note_A; else if (strcmp("Ais", s) == 0) return Note_Ais; else if (strcmp("H", s) == 0) return Note_H; PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteNote '%s'", s); return Note_INVALID; } char *RingNoteStyleToString(GSM_RingNoteStyle type) { char *s = NULL; switch (type) { case NaturalStyle: s = strdup("Natural"); break; case ContinuousStyle: s = strdup("Continuous"); break; case StaccatoStyle: s = strdup("Staccato"); break; case INVALIDStyle: s = strdup(""); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteStyle from Gammu: '%d'", type); return NULL; } return s; } GSM_RingNoteStyle StringToRingNoteStyle(char *s) { if (strcmp("Natural", s) == 0) return NaturalStyle; else if (strcmp("Continuous", s) == 0) return ContinuousStyle; else if (strcmp("Staccato", s) == 0) return StaccatoStyle; PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteStyle '%s'", s); return INVALIDStyle; } char *RingCommandTypeToString(GSM_RingCommandType type) { char *s = NULL; switch (type) { case RING_Note: s = strdup("Note"); break; case RING_EnableVibra: s = strdup("EnableVibra"); break; case RING_DisableVibra: s = strdup("DisableVibra"); break; case RING_EnableLight: s = strdup("EnableLight"); break; case RING_DisableLight: s = strdup("DisableLight"); break; case RING_EnableLED: s = strdup("EnableLED"); break; case RING_DisableLED: s = strdup("DisableLED"); break; case RING_Repeat: s = strdup("Repeat"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingCommandType from Gammu: '%d'", type); return NULL; } return s; } GSM_RingCommandType StringToRingCommandType(char *s) { if (strcmp("Note", s) == 0) return RING_Note; else if (strcmp("EnableVibra", s) == 0) return RING_EnableVibra; else if (strcmp("DisableVibra", s) == 0) return RING_DisableVibra; else if (strcmp("EnableLight", s) == 0) return RING_EnableLight; else if (strcmp("DisableLight", s) == 0) return RING_DisableLight; else if (strcmp("EnableLED", s) == 0) return RING_EnableLED; else if (strcmp("DisableLED", s) == 0) return RING_DisableLED; else if (strcmp("Repeat", s) == 0) return RING_Repeat; PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingCommandType '%s'", s); return 0; } GSM_RingNoteScale IntToRingNoteScale(int v) { if (v == 55) return Scale_55; else if (v == 110) return Scale_110; else if (v == 220) return Scale_220; else if (v == 440) return Scale_440; else if (v == 880) return Scale_880; else if (v == 1760) return Scale_1760; else if (v == 3520) return Scale_3520; else if (v == 7040) return Scale_7040; else if (v == 14080) return Scale_14080; PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteScale %d", v); return 0; } int RingNoteScaleToInt(GSM_RingNoteScale type) { int v = -1; switch (type) { case Scale_55: v = 55; break; case Scale_110: v = 110; break; case Scale_220: v = 220; break; case Scale_440: v = 440; break; case Scale_880: v = 880; break; case Scale_1760: v = 1760; break; case Scale_3520: v = 3520; break; case Scale_7040: v = 7040; break; case Scale_14080: v = 14080; break; } if (v == -1) { PyErr_Format(PyExc_ValueError, "Bad value for GSM_RingNoteScale from Gammu: '%d'", type); return -1; } return v; } PyObject *RingCommadToPython(GSM_RingCommand * cmd) { PyObject *result; char *type, *style, *note, *durspec, *duration; int scale; type = RingCommandTypeToString(cmd->Type); if (type == NULL) return NULL; scale = RingNoteScaleToInt(cmd->Note.Scale); if (scale == -1) { free(type); return NULL; } style = RingNoteStyleToString(cmd->Note.Style); if (style == NULL) { free(type); return NULL; } note = RingNoteNoteToString(cmd->Note.Note); if (note == NULL) { free(style); free(type); return NULL; } durspec = RingNoteDurationSpecToString(cmd->Note.DurationSpec); if (durspec == NULL) { free(style); free(type); free(note); return NULL; } duration = RingNoteDurationToString(cmd->Note.Duration); if (duration == NULL) { free(durspec); free(style); free(type); free(note); return NULL; } result = Py_BuildValue("{s:i,s:s,s:i,s:i,s:s,s:s,s:s,s:s}", "Value", (int)cmd->Value, "Type", type, "Tempo", cmd->Note.Tempo, "Scale", scale, "Style", style, "Note", note, "DurationSpec", durspec, "Duration", duration); free(duration); free(durspec); free(style); free(type); free(note); return result; } int RingCommadFromPython(PyObject * dict, GSM_RingCommand * cmd) { int i; char *s; i = GetIntFromDict(dict, "Value"); if (i == INT_INVALID) return 0; cmd->Value = i; s = GetCharFromDict(dict, "Type"); if (s == NULL) return 0; cmd->Type = StringToRingCommandType(s); free(s); if (cmd->Type == 0) return 0; i = GetIntFromDict(dict, "Tempo"); if (i == INT_INVALID) return 0; cmd->Note.Tempo = i; i = GetIntFromDict(dict, "Scale"); if (i == INT_INVALID) return 0; cmd->Note.Scale = IntToRingNoteScale(i); if (cmd->Note.Scale == 0) return 0; s = GetCharFromDict(dict, "Style"); if (s == NULL) return 0; cmd->Note.Style = StringToRingNoteStyle(s); free(s); if (cmd->Note.Style == INVALIDStyle) return 0; s = GetCharFromDict(dict, "Note"); if (s == NULL) return 0; cmd->Note.Note = StringToRingNoteNote(s); free(s); if (cmd->Note.Note == Note_INVALID) return 0; s = GetCharFromDict(dict, "DurationSpec"); if (s == NULL) return 0; cmd->Note.DurationSpec = StringToRingNoteDurationSpec(s); free(s); if (cmd->Note.DurationSpec == DurationSpec_INVALID) return 0; s = GetCharFromDict(dict, "Duration"); if (s == NULL) return 0; cmd->Note.Duration = StringToRingNoteDuration(s); free(s); if (cmd->Note.Duration == Duration_INVALID) return 0; return 1; } PyObject *RingtoneToPython(GSM_Ringtone * inring) { GSM_Ringtone ring; PyObject *name; PyObject *v; PyObject *f; PyObject *result; int i; if (inring->Format != RING_NOTETONE) { if (GSM_RingtoneConvert(&ring, inring, RING_NOTETONE) != ERR_NONE) { pyg_warning ("Ringtone can not be converted to RING_NOTETONE, ignoring!\n"); Py_RETURN_NONE; } } else { ring = *inring; } v = PyList_New(0); if (v == NULL) return NULL; for (i = 0; i < ring.NoteTone.NrCommands; i++) { f = RingCommadToPython(&(ring.NoteTone.Commands[i])); if (f == NULL) { Py_DECREF(v); return NULL; } if (PyList_Append(v, f) != 0) { Py_DECREF(f); Py_DECREF(v); return NULL; } Py_DECREF(f); } name = UnicodeStringToPython(ring.Name); if (name == NULL) { Py_DECREF(v); return NULL; } result = Py_BuildValue("{s:i,s:O,s:O}", "AllNotesScale", (int)ring.NoteTone.AllNotesScale, "Name", name, "Notes", v); Py_DECREF(v); Py_DECREF(name); return result; } int RingtoneFromPython(PyObject * dict, GSM_Ringtone * ring) { Py_ssize_t i; Py_ssize_t len; PyObject *list; PyObject *item; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "Ringtone is not a dictionary"); return 0; } memset(ring, 0, sizeof(GSM_Ringtone)); /* FIXME: change constant to some define */ if (!CopyStringFromDict(dict, "Name", 19, ring->Name)) { return 0; } list = PyDict_GetItemString(dict, "Notes"); if (!PyList_Check(list)) { PyErr_Format(PyExc_ValueError, "Notes are not a list"); return 0; } len = PyList_Size(list); if (len > GSM_MAX_RINGTONE_NOTES) { pyg_warning("Truncating Notes entries to %d entries! (from %" PY_FORMAT_SIZE_T "d))\n", GSM_MAX_RINGTONE_NOTES, len); len = GSM_MAX_RINGTONE_NOTES; } ring->NoteTone.NrCommands = len; for (i = 0; i < len; i++) { item = PyList_GetItem(list, i); if (item == NULL) return 0; if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Notes is not a dictionary", i); return 0; } if (!RingCommadFromPython(item, &(ring->NoteTone.Commands[i]))) return 0; } return 1; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134745.0 python-gammu-3.2.4/gammu/src/convertors/sms.c0000644000175000017500000013370500000000000020212 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* SMS related conversions */ #define PY_SSIZE_T_CLEAN #include "convertors.h" #include "misc.h" #include char *SMSValidityToString(GSM_SMSValidity Validity) { char s[100] = ""; char *p; switch (Validity.Format) { case SMS_Validity_NotAvailable: #if 0 case 0: #endif strcpy(s, "NA"); break; case SMS_Validity_RelativeFormat: if (Validity.Relative > 255) { PyErr_Format(PyExc_ValueError, "Bad value for RelativeValidity from Gammu: '%d'", Validity.Relative); return NULL; } if (Validity.Relative == SMS_VALID_Max_Time) { strcpy(s, "Max"); } else if (Validity.Relative <= 143) { snprintf(s, 99, "%dM", 5 * (1 + Validity.Relative)); } else if (Validity.Relative <= 167) { snprintf(s, 99, "%dM", 12 * 60 + 30 * (Validity.Relative - 143)); } else if (Validity.Relative <= 196) { snprintf(s, 99, "%dD", Validity.Relative - 166); } else { snprintf(s, 99, "%dW", Validity.Relative - 192); } break; default: PyErr_Format(PyExc_ValueError, "Bad value for ValidityPeriodFormat from Gammu: '%d'", Validity.Format); return NULL; } p = strdup(s); if (p == NULL) PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate string"); return p; } GSM_SMSValidity StringToSMSValidity(char *s) { GSM_SMSValidity Validity = { 0, 0 }; int len; int val; char type; if (strcmp(s, "NA") == 0) { Validity.Format = SMS_Validity_NotAvailable; return Validity; } Validity.Format = SMS_Validity_RelativeFormat; if (strcmp(s, "Max") == 0) { Validity.Relative = SMS_VALID_Max_Time; return Validity; } len = strlen(s); type = s[len - 1]; if (isdigit((int)type)) type = 'M'; val = atoi(s); if (val <= 0) { PyErr_Format(PyExc_ValueError, "Bad relative validity: '%s'", s); Validity.Format = 0; return Validity; } switch (type) { case 'M': if (val <= 720) { Validity.Relative = (val / 5) - 1; } else if (val <= 1440) { Validity.Relative = ((val - 12 * 60) / 30) + 143; } else if (val <= 30 * 24 * 60) { Validity.Relative = (val / (60 * 24)) + 166; } else if (val <= 63 * 7 * 24 * 60) { Validity.Relative = (val / (7 * 60 * 24)) + 166; } else { PyErr_Format(PyExc_ValueError, "Bad relative validity in minutes: '%d'", val); Validity.Format = 0; } break; case 'H': if (val <= 12) { Validity.Relative = (val * 60 / 5) - 1; } else if (val <= 24) { Validity.Relative = ((val * 60 - 12 * 60) / 30) + 143; } else if (val <= 30 * 24) { Validity.Relative = (val / 24) + 166; } else if (val <= 63 * 7 * 24) { Validity.Relative = (val / (7 * 24)) + 166; } else { PyErr_Format(PyExc_ValueError, "Bad relative validity in hours: '%d'", val); Validity.Format = 0; } break; case 'D': if (val <= 1) { Validity.Relative = ((val * 60 * 24 - 12 * 60) / 30) + 143; } else if (val <= 30) { Validity.Relative = val + 166; } else if (val <= 63 * 7) { Validity.Relative = (val / 7) + 166; } else { PyErr_Format(PyExc_ValueError, "Bad relative validity in days: '%d'", val); Validity.Format = 0; } break; case 'W': if (val <= 4) { Validity.Relative = val * 7 + 166; } else if (val <= 63) { Validity.Relative = val + 166; } else { PyErr_Format(PyExc_ValueError, "Bad relative validity in weeks: '%d'", val); Validity.Format = 0; } break; default: PyErr_Format(PyExc_ValueError, "Bad relative validity type: '%c'", type); Validity.Format = 0; } return Validity; } char *SMSFormatToString(GSM_SMSFormat f) { char *s = NULL; switch (f) { case SMS_FORMAT_Pager: s = strdup("Pager"); break; case SMS_FORMAT_Fax: s = strdup("Fax"); break; case SMS_FORMAT_Email: s = strdup("Email"); break; case SMS_FORMAT_Text: s = strdup("Text"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for SMSFormat from Gammu: '%d'", f); return NULL; } return s; } GSM_SMSFormat StringToSMSFormat(char *s) { if (strcmp("Text", s) == 0) return SMS_FORMAT_Text; else if (strcmp("Pager", s) == 0) return SMS_FORMAT_Pager; else if (strcmp("Fax", s) == 0) return SMS_FORMAT_Fax; else if (strcmp("Email", s) == 0) return SMS_FORMAT_Email; else { PyErr_Format(PyExc_MemoryError, "Bad value for SMS Format '%s'", s); return 0; } } PyObject *SMSCToPython(GSM_SMSC * smsc) { PyObject *ret; Py_UNICODE *name, *number, *defaultn; char *val, *fmt; name = strGammuToPython(smsc->Name); if (name == NULL) { return NULL; } number = strGammuToPython(smsc->Number); if (number == NULL) { free(name); return NULL; } defaultn = strGammuToPython(smsc->DefaultNumber); if (defaultn == NULL) { free(name); free(number); return NULL; } val = SMSValidityToString(smsc->Validity); if (val == NULL) { free(name); free(number); free(defaultn); return NULL; } fmt = SMSFormatToString(smsc->Format); if (fmt == NULL) { free(name); free(number); free(defaultn); free(val); return NULL; } ret = Py_BuildValue("{s:i,s:u,s:s,s:s,s:u,s:u}", "Location", smsc->Location, "Name", name, "Format", fmt, "Validity", val, "Number", number, "DefaultNumber", defaultn); free(val); free(fmt); free(name); free(number); free(defaultn); return ret; } int SMSCFromPython(PyObject * dict, GSM_SMSC * smsc, gboolean complete) { char *s; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "SMSC is not a dictionary"); return 0; } memset(smsc, 0, sizeof(GSM_SMSC)); if (!complete) { smsc->Location = GetIntFromDict(dict, "Location"); if (smsc->Location == INT_INVALID) { smsc->Location = 0; PyErr_Clear(); if (!CopyStringFromDict (dict, "Number", GSM_MAX_NUMBER_LENGTH, smsc->Number)) return 0; } else { if (!CopyStringFromDict (dict, "Number", GSM_MAX_NUMBER_LENGTH, smsc->Number)) PyErr_Clear(); } if (!CopyStringFromDict (dict, "Name", GSM_MAX_SMSC_NAME_LENGTH, smsc->Name)) PyErr_Clear(); if (!CopyStringFromDict (dict, "DefaultNumber", GSM_MAX_NUMBER_LENGTH, smsc->DefaultNumber)) PyErr_Clear(); s = GetCharFromDict(dict, "Format"); if (s == NULL) { PyErr_Clear(); } else { smsc->Format = StringToSMSFormat(s); free(s); if (smsc->Format == 0) return 0; } s = GetCharFromDict(dict, "Validity"); if (s == NULL) { PyErr_Clear(); } else { smsc->Validity = StringToSMSValidity(s); free(s); if (smsc->Validity.Format == 0) return 0; } } else { smsc->Location = GetIntFromDict(dict, "Location"); if (smsc->Location == INT_INVALID) return 0; if (!CopyStringFromDict (dict, "Number", GSM_MAX_NUMBER_LENGTH, smsc->Number)) return 0; if (!CopyStringFromDict (dict, "Name", GSM_MAX_SMSC_NAME_LENGTH, smsc->Name)) return 0; if (!CopyStringFromDict (dict, "DefaultNumber", GSM_MAX_NUMBER_LENGTH, smsc->DefaultNumber)) return 0; s = GetCharFromDict(dict, "Format"); if (s == NULL) return 0; smsc->Format = StringToSMSFormat(s); free(s); if (smsc->Format == 0) return 0; s = GetCharFromDict(dict, "Validity"); if (s == NULL) return 0; smsc->Validity = StringToSMSValidity(s); free(s); if (smsc->Validity.Format == 0) return 0; } return 1; } GSM_UDH StringToUDHType(const char *s) { if (strcmp("NoUDH", s) == 0) return UDH_NoUDH; else if (strcmp("ConcatenatedMessages", s) == 0) return UDH_ConcatenatedMessages; else if (strcmp("ConcatenatedMessages16bit", s) == 0) return UDH_ConcatenatedMessages16bit; else if (strcmp("DisableVoice", s) == 0) return UDH_DisableVoice; else if (strcmp("DisableFax", s) == 0) return UDH_DisableFax; else if (strcmp("DisableEmail", s) == 0) return UDH_DisableEmail; else if (strcmp("EnableVoice", s) == 0) return UDH_EnableVoice; else if (strcmp("EnableFax", s) == 0) return UDH_EnableFax; else if (strcmp("EnableEmail", s) == 0) return UDH_EnableEmail; else if (strcmp("VoidSMS", s) == 0) return UDH_VoidSMS; else if (strcmp("NokiaRingtone", s) == 0) return UDH_NokiaRingtone; else if (strcmp("NokiaRingtoneLong", s) == 0) return UDH_NokiaRingtoneLong; else if (strcmp("NokiaOperatorLogo", s) == 0) return UDH_NokiaOperatorLogo; else if (strcmp("NokiaOperatorLogoLong", s) == 0) return UDH_NokiaOperatorLogoLong; else if (strcmp("NokiaCallerLogo", s) == 0) return UDH_NokiaCallerLogo; else if (strcmp("NokiaWAP", s) == 0) return UDH_NokiaWAP; else if (strcmp("NokiaWAPLong", s) == 0) return UDH_NokiaWAPLong; else if (strcmp("NokiaCalendarLong", s) == 0) return UDH_NokiaCalendarLong; else if (strcmp("NokiaProfileLong", s) == 0) return UDH_NokiaProfileLong; else if (strcmp("NokiaPhonebookLong", s) == 0) return UDH_NokiaPhonebookLong; else if (strcmp("UserUDH", s) == 0) return UDH_UserUDH; else if (strcmp("MMSIndicatorLong", s) == 0) return UDH_MMSIndicatorLong; PyErr_Format(PyExc_ValueError, "Bad value for UDH Type '%s'", s); return 0; } char *UDHTypeToString(GSM_UDH type) { char *s = NULL; switch (type) { case UDH_NoUDH: s = strdup("NoUDH"); break; case UDH_ConcatenatedMessages: s = strdup("ConcatenatedMessages"); break; case UDH_ConcatenatedMessages16bit: s = strdup("ConcatenatedMessages16bit"); break; case UDH_DisableVoice: s = strdup("DisableVoice"); break; case UDH_DisableFax: s = strdup("DisableFax"); break; case UDH_DisableEmail: s = strdup("DisableEmail"); break; case UDH_EnableVoice: s = strdup("EnableVoice"); break; case UDH_EnableFax: s = strdup("EnableFax"); break; case UDH_EnableEmail: s = strdup("EnableEmail"); break; case UDH_VoidSMS: s = strdup("VoidSMS"); break; case UDH_NokiaRingtone: s = strdup("NokiaRingtone"); break; case UDH_NokiaRingtoneLong: s = strdup("NokiaRingtoneLong"); break; case UDH_NokiaOperatorLogo: s = strdup("NokiaOperatorLogo"); break; case UDH_NokiaOperatorLogoLong: s = strdup("NokiaOperatorLogoLong"); break; case UDH_NokiaCallerLogo: s = strdup("NokiaCallerLogo"); break; case UDH_NokiaWAP: s = strdup("NokiaWAP"); break; case UDH_NokiaWAPLong: s = strdup("NokiaWAPLong"); break; case UDH_NokiaCalendarLong: s = strdup("NokiaCalendarLong"); break; case UDH_NokiaProfileLong: s = strdup("NokiaProfileLong"); break; case UDH_NokiaPhonebookLong: s = strdup("NokiaPhonebookLong"); break; case UDH_UserUDH: s = strdup("UserUDH"); break; case UDH_MMSIndicatorLong: s = strdup("MMSIndicatorLong"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for UDHType from Gammu: '%d'", type); free(s); return NULL; } return s; } GSM_SMSMessageType StringToSMSType(const char *s) { if (strcmp("Deliver", s) == 0) return SMS_Deliver; else if (strcmp("Status_Report", s) == 0) return SMS_Status_Report; else if (strcmp("Submit", s) == 0) return SMS_Submit; PyErr_Format(PyExc_ValueError, "Bad value for SMSType: '%s'", s); return 0; } char *SMSTypeToString(GSM_SMSMessageType type) { char *s = NULL; switch (type) { case SMS_Deliver: s = strdup("Deliver"); break; case SMS_Status_Report: s = strdup("Status_Report"); break; case SMS_Submit: s = strdup("Submit"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for SMSMessageType from Gammu: '%d'", type); return NULL; } return s; } GSM_Coding_Type StringToSMSCoding(const char *s) { GSM_Coding_Type t; t = GSM_StringToSMSCoding(s); if (t == 0) { PyErr_Format(PyExc_ValueError, "Bad value for SMSCoding: '%s'", s); } return t; } char *SMSCodingToString(GSM_Coding_Type type) { const char *s; s = GSM_SMSCodingToString(type); if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for Coding_Type from Gammu: '%d'", type); return NULL; } return strdup(s); } GSM_SMS_State StringToSMSState(const char *s) { if (strcmp("Sent", s) == 0) return SMS_Sent; else if (strcmp("UnSent", s) == 0) return SMS_UnSent; else if (strcmp("Read", s) == 0) return SMS_Read; else if (strcmp("UnRead", s) == 0) return SMS_UnRead; PyErr_Format(PyExc_ValueError, "Bad value for SMS_State: '%s'", s); return 0; } char *SMSStateToString(GSM_SMS_State type) { char *s = NULL; switch (type) { case SMS_Sent: s = strdup("Sent"); break; case SMS_UnSent: s = strdup("UnSent"); break; case SMS_Read: s = strdup("Read"); break; case SMS_UnRead: s = strdup("UnRead"); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for SMS_State from Gammu: '%d'", type); return NULL; } return s; } int UDHFromPython(PyObject * dict, GSM_UDHHeader * udh) { char *s; Py_ssize_t len; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "UDH is not a dictionary"); return 0; } memset(udh, 0, sizeof(GSM_UDHHeader)); udh->ID8bit = GetIntFromDict(dict, "ID8bit"); if (udh->ID8bit == INT_INVALID) { udh->ID8bit = -1; PyErr_Clear(); } udh->ID16bit = GetIntFromDict(dict, "ID16bit"); if (udh->ID16bit == INT_INVALID) { udh->ID16bit = -1; PyErr_Clear(); } udh->PartNumber = GetIntFromDict(dict, "PartNumber"); if (udh->PartNumber == INT_INVALID) { udh->PartNumber = -1; PyErr_Clear(); } udh->AllParts = GetIntFromDict(dict, "AllParts"); if (udh->AllParts == INT_INVALID) { udh->AllParts = -1; PyErr_Clear(); } s = GetCharFromDict(dict, "Type"); if (s == NULL) return 0; udh->Type = StringToUDHType(s); free(s); if (udh->Type == 0) return 0; s = GetDataFromDict(dict, "Text", &len); if (s == NULL) return 0; udh->Length = len; if (udh->Length > GSM_MAX_UDH_LENGTH) { pyg_warning("UDH too large, truncating!"); udh->Length = GSM_MAX_UDH_LENGTH; } memcpy(udh->Text, s, udh->Length); return 1; } PyObject *UDHToPython(GSM_UDHHeader * udh) { char *type; PyObject *val; type = UDHTypeToString(udh->Type); if (type == NULL) return NULL; val = Py_BuildValue( "{s:s,s:y#,s:i,s:i,s:i,s:i}", "Type", type, "Text", udh->Text, (Py_ssize_t)udh->Length, "ID8bit", udh->ID8bit, "ID16bit", udh->ID16bit, "PartNumber", udh->PartNumber, "AllParts", udh->AllParts ); free(type); return val; } int SMSFromPython(PyObject * dict, GSM_SMSMessage * sms, int needslocation, int needsfolder, int needsnumber) { PyObject *o; char *s; GSM_DateTime nulldt = { 0, 0, 0, 0, 0, 0, 0 }; int i; Py_ssize_t len; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "SMS is not a dictionary"); return 0; } memset(sms, 0, sizeof(GSM_SMSMessage)); GSM_SetDefaultSMSData(sms); o = PyDict_GetItemString(dict, "SMSC"); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Missing SMSC attribute!"); return 0; } if (!PyDict_Check(o)) { PyErr_Format(PyExc_ValueError, "SMSC should be dictionary!"); return 0; } if (!SMSCFromPython(o, &(sms->SMSC), FALSE)) { return 0; } if (!CopyStringFromDict (dict, "Number", GSM_MAX_NUMBER_LENGTH, sms->Number)) { if (needsnumber) { return 0; } else { EncodeUnicode(sms->Number, "Gammu", 5); PyErr_Clear(); } } if (!CopyStringFromDict (dict, "Name", GSM_MAX_SMS_NAME_LENGTH, sms->Name)) { PyErr_Clear(); sms->Name[0] = 0; sms->Name[1] = 0; } o = PyDict_GetItemString(dict, "UDH"); if (o == NULL) { sms->UDH.Type = UDH_NoUDH; } else { if (!PyDict_Check(o)) { if (o == Py_None) { sms->UDH.Type = UDH_NoUDH; } else { PyErr_Format(PyExc_ValueError, "UDH is not a dictionary!"); return 0; } } else { if (!UDHFromPython(o, &(sms->UDH))) return 0; } } s = GetCharFromDict(dict, "Coding"); if (s == NULL) { sms->Coding = SMS_Coding_Default_No_Compression; PyErr_Clear(); } else { sms->Coding = StringToSMSCoding(s); free(s); if (sms->Coding == 0) return 0; } if (sms->Coding != SMS_Coding_8bit) { /* No UDH/UserUDH => copy as text */ if (!CopyStringFromDict (dict, "Text", GSM_MAX_SMS_LENGTH, sms->Text)) return 0; sms->Length = UnicodeLength(sms->Text); } else { /* Some UDH => copy as data */ s = GetDataFromDict(dict, "Text", &len); if (s == NULL) return 0; sms->Length = len; if (sms->Length > GSM_MAX_SMS_LENGTH) { pyg_warning("SMS text too large, truncating!\n"); sms->Length = GSM_MAX_SMS_LENGTH; } memcpy(sms->Text, s, sms->Length); } if ((sms->Folder = GetIntFromDict(dict, "Folder")) == INT_INVALID) { if (needsfolder) { return 0; } else { PyErr_Clear(); } } if ((sms->Location = GetIntFromDict(dict, "Location")) == INT_INVALID) { if (needslocation) { return 0; } else { PyErr_Clear(); } } if ((sms->InboxFolder = GetBoolFromDict(dict, "InboxFolder")) == BOOL_INVALID) { sms->InboxFolder = FALSE; PyErr_Clear(); } if ((i = GetIntFromDict(dict, "DeliveryStatus")) == INT_INVALID) { sms->DeliveryStatus = 0; PyErr_Clear(); } else { sms->DeliveryStatus = i; } if ((i = GetIntFromDict(dict, "ReplyViaSameSMSC")) == INT_INVALID) { sms->ReplyViaSameSMSC = FALSE; PyErr_Clear(); } else { sms->ReplyViaSameSMSC = i; } if ((i = GetIntFromDict(dict, "Class")) == INT_INVALID) { sms->Class = -1; PyErr_Clear(); } else { sms->Class = i; } if ((i = GetIntFromDict(dict, "MessageReference")) == INT_INVALID) { sms->MessageReference = 0; PyErr_Clear(); } else { sms->MessageReference = i; } if ((i = GetIntFromDict(dict, "ReplaceMessage")) == INT_INVALID) { sms->ReplaceMessage = 0; PyErr_Clear(); } else { sms->ReplaceMessage = i; } if ((sms->RejectDuplicates = GetBoolFromDict(dict, "RejectDuplicates")) == BOOL_INVALID) { sms->RejectDuplicates = FALSE; PyErr_Clear(); } s = GetCharFromDict(dict, "Memory"); if (s == NULL || strcmp(s, "") == 0) { sms->Memory = 0; PyErr_Clear(); if (s != NULL) { free(s); } } else { sms->Memory = StringToMemoryType(s); free(s); if (sms->Memory == 0) return 0; } s = GetCharFromDict(dict, "Type"); if (s == NULL) { sms->PDU = SMS_Submit; PyErr_Clear(); } else { sms->PDU = StringToSMSType(s); free(s); if (sms->PDU == 0) return 0; } sms->DateTime = GetDateTimeFromDict(dict, "DateTime"); if (sms->DateTime.Year == -1) { sms->DateTime = nulldt; PyErr_Clear(); } sms->SMSCTime = GetDateTimeFromDict(dict, "SMSCDateTime"); if (sms->SMSCTime.Year == -1) { sms->SMSCTime = nulldt; PyErr_Clear(); } s = GetCharFromDict(dict, "State"); if (s == NULL) { PyErr_Clear(); sms->State = SMS_UnSent; } else { sms->State = StringToSMSState(s); free(s); if (sms->State == 0) return 0; } return 1; } PyObject *SMSToPython(GSM_SMSMessage * sms) { PyObject *udh; PyObject *smsc; char *mt; Py_UNICODE *name; Py_UNICODE *number; PyObject *text; char *type; char *coding; char *state; PyObject *dt; PyObject *smscdt; PyObject *val; smsc = SMSCToPython(&(sms->SMSC)); if (smsc == NULL) return NULL; udh = UDHToPython(&(sms->UDH)); if (udh == NULL) { Py_DECREF(smsc); return NULL; } if (sms->Memory == 0) { mt = strdup(""); } else { mt = MemoryTypeToString(sms->Memory); if (mt == NULL) { Py_DECREF(smsc); Py_DECREF(udh); return NULL; } } name = strGammuToPython(sms->Name); if (name == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); return NULL; } number = strGammuToPython(sms->Number); if (number == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); return NULL; } if (sms->Coding != SMS_Coding_8bit) { /* No UDH/User UDH => copy as text */ text = UnicodeStringToPythonL(sms->Text, sms->Length); } else { /* Some UDH => copy as data */ text = PyBytes_FromStringAndSize((char *)sms->Text, sms->Length); } if (text == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); return NULL; } type = SMSTypeToString(sms->PDU); if (type == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); Py_DECREF(text); return NULL; } coding = SMSCodingToString(sms->Coding); if (coding == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); Py_DECREF(text); free(type); return NULL; } state = SMSStateToString(sms->State); if (state == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); Py_DECREF(text); free(type); free(coding); return NULL; } dt = BuildPythonDateTime(&(sms->DateTime)); if (dt == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); Py_DECREF(text); free(type); free(coding); free(state); return NULL; } smscdt = BuildPythonDateTime(&(sms->SMSCTime)); if (smscdt == NULL) { Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); Py_DECREF(text); free(type); free(coding); free(state); Py_DECREF(dt); return NULL; } val = Py_BuildValue( "{s:O,s:O,s:i,s:i,s:s,s:i,s:u,s:u,s:O,s:s,s:s,s:O,s:O,s:i,s:i,s:s,s:i,s:i,s:i,s:i,s:i}", "SMSC", smsc, "UDH", udh, "Folder", (int)sms->Folder, "InboxFolder", (int)sms->InboxFolder, "Memory", mt, "Location", (int)sms->Location, "Name", name, "Number", number, "Text", text, "Type", type, "Coding", coding, "DateTime", dt, "SMSCDateTime", smscdt, "DeliveryStatus", (int)sms->DeliveryStatus, "ReplyViaSameSMSC", (int)sms->ReplyViaSameSMSC, "State", state, "Class", (int)sms->Class, "MessageReference", (int)sms->MessageReference, "ReplaceMessage", (int)sms->ReplaceMessage, "RejectDuplicates", (int)sms->RejectDuplicates, "Length", sms->Length ); Py_DECREF(smsc); Py_DECREF(udh); free(mt); free(name); free(number); Py_DECREF(text); free(type); free(coding); free(state); Py_DECREF(dt); Py_DECREF(smscdt); return val; } PyObject *MultiSMSToPython(GSM_MultiSMSMessage * sms) { PyObject *val; PyObject *item; int i; val = PyList_New(0); if (val == NULL) return NULL; for (i = 0; i < sms->Number; i++) { item = SMSToPython(&(sms->SMS[i])); if (item == NULL) { Py_DECREF(val); return NULL; } if (PyList_Append(val, item) != 0) { Py_DECREF(item); Py_DECREF(val); return NULL; } Py_DECREF(item); } return val; } int MultiSMSFromPython(PyObject * list, GSM_MultiSMSMessage * sms) { PyObject *item; Py_ssize_t len; Py_ssize_t i; if (!PyList_Check(list)) { PyErr_Format(PyExc_ValueError, "Multi SMS is not a list"); return 0; } len = PyList_Size(list); if (len > GSM_MAX_MULTI_SMS) { pyg_warning("Truncating MultiSMS entries to %d entries! (from %" PY_FORMAT_SIZE_T "d))\n", GSM_MAX_MULTI_SMS, len); len = GSM_MAX_MULTI_SMS; } sms->Number = len; for (i = 0; i < len; i++) { item = PyList_GetItem(list, i); if (item == NULL) return 0; if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Messages is not dictionary", i); return 0; } if (!SMSFromPython(item, &(sms->SMS[i]), 0, 0, 0)) return 0; } return 1; } int MultiSMSListFromPython(PyObject * list, GSM_MultiSMSMessage *** sms) { PyObject *item; Py_ssize_t len; Py_ssize_t i; int j; if (!PyList_Check(list)) { PyErr_Format(PyExc_ValueError, "Multi SMS list is not a list"); return 0; } len = PyList_Size(list); *sms = (GSM_MultiSMSMessage **) malloc((len + 1) * sizeof(GSM_MultiSMSMessage *)); if (*sms == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } for (i = 0; i < len; i++) { item = PyList_GetItem(list, i); if (item == NULL) { for (j = 0; j < i; j++) free((*sms)[j]); free((*sms)); return 0; } if (!PyList_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Messages is not list", i); for (j = 0; j < i; j++) free((*sms)[j]); free((*sms)); return 0; } (*sms)[i] = (GSM_MultiSMSMessage *) malloc(sizeof(GSM_MultiSMSMessage)); if ((*sms)[i] == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); for (j = 0; j < i; j++) free((*sms)[j]); free((*sms)); return 0; } if (!MultiSMSFromPython(item, (*sms)[i])) { for (j = 0; j <= i; j++) free((*sms)[j]); free((*sms)); return 0; } } (*sms)[len] = NULL; return 1; } PyObject *MultiSMSListToPython(GSM_MultiSMSMessage ** sms) { PyObject *val; PyObject *item; int i = 0; val = PyList_New(0); if (val == NULL) return NULL; while (sms[i] != NULL) { item = MultiSMSToPython(sms[i]); if (item == NULL) { Py_DECREF(val); return NULL; } if (PyList_Append(val, item) != 0) { Py_DECREF(val); Py_DECREF(item); return NULL; } Py_DECREF(item); i++; } return val; } char *MultiPartSMSIDToString(EncodeMultiPartSMSID type) { char *s = NULL; switch (type) { case SMS_Text: s = strdup("Text"); break; case SMS_ConcatenatedTextLong: s = strdup("ConcatenatedTextLong"); break; case SMS_ConcatenatedAutoTextLong: s = strdup("ConcatenatedAutoTextLong"); break; case SMS_ConcatenatedTextLong16bit: s = strdup("ConcatenatedTextLong16bit"); break; case SMS_ConcatenatedAutoTextLong16bit: s = strdup("ConcatenatedAutoTextLong16bit"); break; case SMS_NokiaProfileLong: s = strdup("NokiaProfileLong"); break; case SMS_NokiaPictureImageLong: s = strdup("NokiaPictureImageLong"); break; case SMS_NokiaScreenSaverLong: s = strdup("NokiaScreenSaverLong"); break; case SMS_NokiaRingtone: s = strdup("NokiaRingtone"); break; case SMS_NokiaRingtoneLong: s = strdup("NokiaRingtoneLong"); break; case SMS_NokiaOperatorLogo: s = strdup("NokiaOperatorLogo"); break; case SMS_NokiaOperatorLogoLong: s = strdup("NokiaOperatorLogoLong"); break; case SMS_NokiaCallerLogo: s = strdup("NokiaCallerLogo"); break; case SMS_NokiaWAPBookmarkLong: s = strdup("NokiaWAPBookmarkLong"); break; case SMS_NokiaWAPSettingsLong: s = strdup("NokiaWAPSettingsLong"); break; case SMS_NokiaMMSSettingsLong: s = strdup("NokiaMMSSettingsLong"); break; case SMS_NokiaVCARD10Long: s = strdup("NokiaVCARD10Long"); break; case SMS_NokiaVCARD21Long: s = strdup("NokiaVCARD21Long"); break; case SMS_NokiaVCALENDAR10Long: s = strdup("NokiaVCALENDAR10Long"); break; case SMS_NokiaVTODOLong: s = strdup("NokiaVTODOLong"); break; case SMS_VCARD10Long: s = strdup("VCARD10Long"); break; case SMS_VCARD21Long: s = strdup("VCARD21Long"); break; case SMS_DisableVoice: s = strdup("DisableVoice"); break; case SMS_DisableFax: s = strdup("DisableFax"); break; case SMS_DisableEmail: s = strdup("DisableEmail"); break; case SMS_EnableVoice: s = strdup("EnableVoice"); break; case SMS_EnableFax: s = strdup("EnableFax"); break; case SMS_EnableEmail: s = strdup("EnableEmail"); break; case SMS_VoidSMS: s = strdup("VoidSMS"); break; case SMS_EMSSound10: s = strdup("EMSSound10"); break; case SMS_EMSSound12: s = strdup("EMSSound12"); break; case SMS_EMSSonyEricssonSound: s = strdup("EMSSonyEricssonSound"); break; case SMS_EMSSound10Long: s = strdup("EMSSound10Long"); break; case SMS_EMSSound12Long: s = strdup("EMSSound12Long"); break; case SMS_EMSSonyEricssonSoundLong: s = strdup("EMSSonyEricssonSoundLong"); break; case SMS_EMSPredefinedSound: s = strdup("EMSPredefinedSound"); break; case SMS_EMSPredefinedAnimation: s = strdup("EMSPredefinedAnimation"); break; case SMS_EMSAnimation: s = strdup("EMSAnimation"); break; case SMS_EMSFixedBitmap: s = strdup("EMSFixedBitmap"); break; case SMS_EMSVariableBitmap: s = strdup("EMSVariableBitmap"); break; case SMS_EMSVariableBitmapLong: s = strdup("EMSVariableBitmapLong"); break; case SMS_MMSIndicatorLong: s = strdup("MMSIndicatorLong"); break; case SMS_AlcatelMonoBitmapLong: s = strdup("AlcatelMonoBitmapLong"); break; case SMS_AlcatelMonoAnimationLong: s = strdup("AlcatelMonoAnimationLong"); break; case SMS_AlcatelSMSTemplateName: s = strdup("AlcatelSMSTemplateName"); break; case SMS_WAPIndicatorLong: s = strdup("WAPIndicatorLong"); break; case SMS_SiemensFile: s = strdup("SiemensFile"); break; #if GAMMU_VERSION_NUM >= 13805 case SMS_USSD: s = strdup("USSD"); break; #endif } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for MultiPartSMSID from Gammu: '%d'", type); return NULL; } return s; } EncodeMultiPartSMSID StringToMultiPartSMSID(char *s) { if (strcmp("Text", s) == 0) return SMS_Text; else if (strcmp("ConcatenatedTextLong", s) == 0) return SMS_ConcatenatedTextLong; else if (strcmp("ConcatenatedAutoTextLong", s) == 0) return SMS_ConcatenatedAutoTextLong; else if (strcmp("ConcatenatedTextLong16bit", s) == 0) return SMS_ConcatenatedTextLong16bit; else if (strcmp("ConcatenatedAutoTextLong16bit", s) == 0) return SMS_ConcatenatedAutoTextLong16bit; else if (strcmp("NokiaProfileLong", s) == 0) return SMS_NokiaProfileLong; else if (strcmp("NokiaPictureImageLong", s) == 0) return SMS_NokiaPictureImageLong; else if (strcmp("NokiaScreenSaverLong", s) == 0) return SMS_NokiaScreenSaverLong; else if (strcmp("NokiaRingtone", s) == 0) return SMS_NokiaRingtone; else if (strcmp("NokiaRingtoneLong", s) == 0) return SMS_NokiaRingtoneLong; else if (strcmp("NokiaOperatorLogo", s) == 0) return SMS_NokiaOperatorLogo; else if (strcmp("NokiaOperatorLogoLong", s) == 0) return SMS_NokiaOperatorLogoLong; else if (strcmp("NokiaCallerLogo", s) == 0) return SMS_NokiaCallerLogo; else if (strcmp("NokiaWAPBookmarkLong", s) == 0) return SMS_NokiaWAPBookmarkLong; else if (strcmp("NokiaWAPSettingsLong", s) == 0) return SMS_NokiaWAPSettingsLong; else if (strcmp("NokiaMMSSettingsLong", s) == 0) return SMS_NokiaMMSSettingsLong; else if (strcmp("NokiaVCARD10Long", s) == 0) return SMS_NokiaVCARD10Long; else if (strcmp("NokiaVCARD21Long", s) == 0) return SMS_NokiaVCARD21Long; else if (strcmp("NokiaVCALENDAR10Long", s) == 0) return SMS_NokiaVCALENDAR10Long; else if (strcmp("NokiaVTODOLong", s) == 0) return SMS_NokiaVTODOLong; else if (strcmp("VCARD10Long", s) == 0) return SMS_VCARD10Long; else if (strcmp("VCARD21Long", s) == 0) return SMS_VCARD21Long; else if (strcmp("DisableVoice", s) == 0) return SMS_DisableVoice; else if (strcmp("DisableFax", s) == 0) return SMS_DisableFax; else if (strcmp("DisableEmail", s) == 0) return SMS_DisableEmail; else if (strcmp("EnableVoice", s) == 0) return SMS_EnableVoice; else if (strcmp("EnableFax", s) == 0) return SMS_EnableFax; else if (strcmp("EnableEmail", s) == 0) return SMS_EnableEmail; else if (strcmp("VoidSMS", s) == 0) return SMS_VoidSMS; else if (strcmp("EMSSound10", s) == 0) return SMS_EMSSound10; else if (strcmp("EMSSound12", s) == 0) return SMS_EMSSound12; else if (strcmp("EMSSonyEricssonSound", s) == 0) return SMS_EMSSonyEricssonSound; else if (strcmp("EMSSound10Long", s) == 0) return SMS_EMSSound10Long; else if (strcmp("EMSSound12Long", s) == 0) return SMS_EMSSound12Long; else if (strcmp("EMSSonyEricssonSoundLong", s) == 0) return SMS_EMSSonyEricssonSoundLong; else if (strcmp("EMSPredefinedSound", s) == 0) return SMS_EMSPredefinedSound; else if (strcmp("EMSPredefinedAnimation", s) == 0) return SMS_EMSPredefinedAnimation; else if (strcmp("EMSAnimation", s) == 0) return SMS_EMSAnimation; else if (strcmp("EMSFixedBitmap", s) == 0) return SMS_EMSFixedBitmap; else if (strcmp("EMSVariableBitmap", s) == 0) return SMS_EMSVariableBitmap; else if (strcmp("EMSVariableBitmapLong", s) == 0) return SMS_EMSVariableBitmapLong; else if (strcmp("MMSIndicatorLong", s) == 0) return SMS_MMSIndicatorLong; else if (strcmp("AlcatelMonoBitmapLong", s) == 0) return SMS_AlcatelMonoBitmapLong; else if (strcmp("AlcatelMonoAnimationLong", s) == 0) return SMS_AlcatelMonoAnimationLong; else if (strcmp("AlcatelSMSTemplateName", s) == 0) return SMS_AlcatelSMSTemplateName; else if (strcmp("WAPIndicatorLong", s) == 0) return SMS_WAPIndicatorLong; else if (strcmp("SiemensFile", s) == 0) return SMS_SiemensFile; PyErr_Format(PyExc_ValueError, "Bad value for MultiPartSMSID '%s'", s); return 0; } PyObject *SMSPartToPython(GSM_MultiPartSMSEntry * entry) { char *t; PyObject *r; PyObject *v; t = MultiPartSMSIDToString(entry->ID); r = Py_BuildValue ("{s:s,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i}", "ID", t, "Left", (int)entry->Left, "Right", (int)entry->Right, "Center", (int)entry->Center, "Large", (int)entry->Large, "Small", (int)entry->Small, "Bold", (int)entry->Bold, "Italic", (int)entry->Italic, "Underlined", (int)entry->Underlined, "Strikethrough", (int)entry->Strikethrough, "RingtoneNotes", (int)entry->RingtoneNotes, "Protected", (int)entry->Protected, "Number", entry->Number); free(t); if (entry->Ringtone != NULL) { v = RingtoneToPython(entry->Ringtone); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Ringtone", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->Bitmap != NULL) { v = MultiBitmapToPython(entry->Bitmap); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Bitmap", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->Bookmark != NULL) { v = WAPBookmarkToPython(entry->Bookmark); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Bookmark", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); #if 0 if (entry->Settings != NULL) { v = WAPSettingsToPython(entry->Settings); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Settings", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); #endif if (entry->MMSIndicator != NULL) { v = MMSIndicatorToPython(entry->MMSIndicator); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "MMSIndicator", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->Phonebook != NULL) { v = MemoryEntryToPython(entry->Phonebook); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Phonebook", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->Calendar != NULL) { v = CalendarToPython(entry->Calendar); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Calendar", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->ToDo != NULL) { v = TodoToPython(entry->ToDo); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "ToDo", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->File != NULL) { v = FileToPython(entry->File); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "File", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); if (entry->Buffer != NULL) { v = UnicodeStringToPython(entry->Buffer); if (v == NULL) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } if (PyDict_SetItemString(r, "Buffer", v) != 0) { Py_DECREF(v); Py_DECREF(r); return NULL; } Py_DECREF(v); return r; } PyObject *SMSInfoToPython(GSM_MultiPartSMSInfo * smsinfo) { PyObject *v; PyObject *f; PyObject *r; int i; v = PyList_New(0); if (v == NULL) return NULL; for (i = 0; i < smsinfo->EntriesNum; i++) { if (smsinfo->Entries[i].ID != 0) { f = SMSPartToPython(&(smsinfo->Entries[i])); if (f == NULL) { Py_DECREF(v); return NULL; } if (PyList_Append(v, f) != 0) { Py_DECREF(f); Py_DECREF(v); return NULL; } Py_DECREF(f); } } r = Py_BuildValue("{s:i,s:i,s:i,s:i,s:O}", "Class", (int)smsinfo->Class, "Unknown", (int)smsinfo->Unknown, "ReplaceMessage", (int)smsinfo->ReplaceMessage, "Unicode", (int)smsinfo->UnicodeCoding, "Entries", v); Py_DECREF(v); return r; } int SMSPartFromPython(PyObject * dict, GSM_MultiPartSMSEntry * entry) { char *s; int i; PyObject *o; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "SMS info part is not a dictionary"); return 0; } s = GetCharFromDict(dict, "ID"); if (s == NULL) return 0; entry->ID = StringToMultiPartSMSID(s); free(s); if (entry->ID == 0) return 0; i = GetBoolFromDict(dict, "Left"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Left = i; } i = GetBoolFromDict(dict, "Right"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Right = i; } i = GetBoolFromDict(dict, "Center"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Center = i; } i = GetBoolFromDict(dict, "Large"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Large = i; } i = GetBoolFromDict(dict, "Small"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Small = i; } i = GetBoolFromDict(dict, "Bold"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Bold = i; } i = GetBoolFromDict(dict, "Italic"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Italic = i; } i = GetBoolFromDict(dict, "Underlined"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Underlined = i; } i = GetBoolFromDict(dict, "Strikethrough"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Strikethrough = i; } i = GetBoolFromDict(dict, "RingtoneNotes"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->RingtoneNotes = i; } i = GetBoolFromDict(dict, "Protected"); if (i == BOOL_INVALID) { PyErr_Clear(); } else { entry->Protected = i; } i = GetIntFromDict(dict, "Number"); if (i == INT_INVALID) { PyErr_Clear(); } else { entry->Number = i; } o = PyDict_GetItemString(dict, "Ringtone"); if (o != NULL && o != Py_None) { entry->Ringtone = (GSM_Ringtone *) malloc(sizeof(GSM_Ringtone)); if (entry->Ringtone == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!RingtoneFromPython(o, entry->Ringtone)) { return 0; } } o = PyDict_GetItemString(dict, "Bitmap"); if (o != NULL && o != Py_None) { entry->Bitmap = (GSM_MultiBitmap *) malloc(sizeof(GSM_MultiBitmap)); if (entry->Bitmap == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!MultiBitmapFromPython(o, entry->Bitmap)) { return 0; } } o = PyDict_GetItemString(dict, "Bookmark"); if (o != NULL && o != Py_None) { entry->Bookmark = (GSM_WAPBookmark *) malloc(sizeof(GSM_WAPBookmark)); if (entry->Bookmark == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!WAPBookmarkFromPython(o, entry->Bookmark)) { return 0; } } #if 0 o = PyDict_GetItemString(dict, "Settings"); if (o != NULL && o != Py_None) { entry->Settings = (GSM_WAPSettings *) malloc(sizeof(GSM_WAPSettings)); if (entry->Settings == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!SettingsFromPython(o, entry->Settings)) { return 0; } } #endif o = PyDict_GetItemString(dict, "MMSIndicator"); if (o != NULL && o != Py_None) { entry->MMSIndicator = (GSM_MMSIndicator *) malloc(sizeof(GSM_MMSIndicator)); if (entry->MMSIndicator == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!MMSIndicatorFromPython(o, entry->MMSIndicator)) { return 0; } } o = PyDict_GetItemString(dict, "Phonebook"); if (o != NULL && o != Py_None) { entry->Phonebook = (GSM_MemoryEntry *) malloc(sizeof(GSM_MemoryEntry)); if (entry->Phonebook == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!MemoryEntryFromPython(o, entry->Phonebook, FALSE)) { return 0; } } o = PyDict_GetItemString(dict, "Calendar"); if (o != NULL && o != Py_None) { entry->Calendar = (GSM_CalendarEntry *) malloc(sizeof(GSM_CalendarEntry)); if (entry->Calendar == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!CalendarFromPython(o, entry->Calendar, FALSE)) { return 0; } } o = PyDict_GetItemString(dict, "ToDo"); if (o != NULL && o != Py_None) { entry->ToDo = (GSM_ToDoEntry *) malloc(sizeof(GSM_ToDoEntry)); if (entry->ToDo == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!TodoFromPython(o, entry->ToDo, FALSE)) { return 0; } } o = PyDict_GetItemString(dict, "File"); if (o != NULL && o != Py_None) { entry->File = (GSM_File *) malloc(sizeof(GSM_File)); if (entry->File == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!FileFromPython(o, entry->File, FALSE)) { return 0; } } entry->Buffer = GetStringFromDict(dict, "Buffer"); if (entry->Buffer == NULL) { PyErr_Clear(); } return 1; } int SMSInfoFromPython(PyObject * dict, GSM_MultiPartSMSInfo * entry) { PyObject *o; PyObject *item; Py_ssize_t len; Py_ssize_t i; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "SMS info is not a dictionary"); return 0; } GSM_ClearMultiPartSMSInfo(entry); entry->UnicodeCoding = GetBoolFromDict(dict, "Unicode"); if (entry->UnicodeCoding == BOOL_INVALID) { PyErr_Clear(); entry->UnicodeCoding = 0; } i = GetIntFromDict(dict, "ReplaceMessage"); if (i == INT_INVALID) { PyErr_Clear(); entry->ReplaceMessage = 0; } else { entry->ReplaceMessage = i; } entry->Unknown = GetBoolFromDict(dict, "Unknown"); if (entry->Unknown == BOOL_INVALID) { PyErr_Clear(); entry->Unknown = FALSE; } i = GetIntFromDict(dict, "Class"); if (i == INT_INVALID) { PyErr_Clear(); entry->Class = -1; } else { entry->Class = i; } o = PyDict_GetItemString(dict, "Entries"); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Can not get string value for key Entries"); return 0; } if (!PyList_Check(o)) { PyErr_Format(PyExc_ValueError, "Key Entries doesn't contain list"); return 0; } len = PyList_Size(o); if (len > GSM_MAX_MULTI_SMS - 1) { pyg_warning("Too many entries, truncating from %" PY_FORMAT_SIZE_T "d to %d\n", len, GSM_MAX_MULTI_SMS - 1); len = GSM_MAX_MULTI_SMS - 1; } entry->EntriesNum = len; for (i = 0; i < len; i++) { item = PyList_GetItem(o, i); if (item == NULL) { return 0; } if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Entries is not dictionary", i); return 0; } if (!SMSPartFromPython(item, &(entry->Entries[i]))) { return 0; } } return 1; } PyObject *SMSFolderToPython(GSM_OneSMSFolder * folder) { Py_UNICODE *name; char *mt; PyObject *result; name = strGammuToPython(folder->Name); if (name == NULL) return NULL; mt = MemoryTypeToString(folder->Memory); if (mt == NULL) { free(name); return NULL; } result = Py_BuildValue("{s:u,s:s,s:i}", "Name", name, "Memory", mt, "Inbox", (int)folder->InboxFolder); free(mt); free(name); return result; } PyObject *SMSFoldersToPython(GSM_SMSFolders * folders) { PyObject *val; PyObject *item; int i; val = PyList_New(0); if (val == NULL) return NULL; for (i = 0; i < folders->Number; i++) { item = SMSFolderToPython(&folders->Folder[i]); if (item == NULL) { Py_DECREF(val); return NULL; } if (PyList_Append(val, item) != 0) { Py_DECREF(val); Py_DECREF(item); return NULL; } Py_DECREF(item); } return val; } #ifdef GSM_ENABLE_BACKUP PyObject *SMSBackupToPython(GSM_SMS_Backup * sms) { PyObject *val; PyObject *item; int i = 0; val = PyList_New(0); if (val == NULL) return NULL; while (sms->SMS[i] != NULL) { item = SMSToPython(sms->SMS[i]); if (item == NULL) { Py_DECREF(val); return NULL; } if (PyList_Append(val, item) != 0) { Py_DECREF(val); Py_DECREF(item); return NULL; } Py_DECREF(item); i++; } return val; } int SMSBackupFromPython(PyObject * list, GSM_SMS_Backup * sms) { PyObject *item; Py_ssize_t len; Py_ssize_t i; if (!PyList_Check(list)) { PyErr_Format(PyExc_ValueError, "SMS Backup is not a list"); return 0; } len = PyList_Size(list); if (len >= GSM_BACKUP_MAX_SMS) { PyErr_SetString(PyExc_MemoryError, "GSM_BACKUP_MAX_SMS too small to fit SMS Backup"); return 0; } for (i = 0; i < len; i++) { item = PyList_GetItem(list, i); if (item == NULL) { return 0; } if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in SMS Backup is not dict", i); return 0; } sms->SMS[i] = (GSM_SMSMessage *) malloc(sizeof(GSM_SMSMessage)); if (sms->SMS[i] == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate structure"); return 0; } if (!SMSFromPython(item, sms->SMS[i], 0, 0, 0)) { return 0; } } sms->SMS[len] = NULL; return 1; } #endif /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134753.0 python-gammu-3.2.4/gammu/src/convertors/string.c0000644000175000017500000001061200000000000020705 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Unicode strings conversion between Gammu and Python */ #include "convertors.h" unsigned char *StringPythonToGammu(PyObject * o) { PyObject *u; wchar_t *ps; unsigned char *gs; Py_ssize_t len; u = PyObject_Str(o); if (u == NULL) { PyErr_Format(PyExc_ValueError, "Value can not be converted to unicode object"); return NULL; } len = PyUnicode_GET_LENGTH(u) + 1; ps = malloc(len * sizeof(wchar_t)); if (ps == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate string"); return NULL; } len = PyUnicode_AsWideChar(u, ps, len -1); if (len == -1) { PyErr_Format(PyExc_ValueError, "Can not get unicode value"); return NULL; } gs = strPythonToGammu(ps, PyUnicode_GET_LENGTH(u)); Py_DECREF(u); return gs; } unsigned char *strPythonToGammu(const wchar_t * src, const size_t len) { unsigned char *dest; wchar_t wc, tmp; size_t i, j; /* Allocate memory */ dest = malloc((len + 1) * 2 * 2 * sizeof(unsigned char)); if (dest == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate string"); return NULL; } /* Convert and copy string. */ for (i = 0, j = 0; i < len; i++) { if (src[i] > 0xffff) { wc = src[i] - 0x10000; tmp = 0xD800 | (wc >> 10); dest[(j * 2)] = (tmp >> 8) & 0xff; dest[(j * 2) + 1] = tmp & 0xff; j++; tmp = 0xDC00 | (wc & 0x3ff); dest[(j * 2)] = (tmp >> 8) & 0xff; dest[(j * 2) + 1] = tmp & 0xff; j++; } else { dest[(j * 2)] = (src[i] >> 8) & 0xff; dest[(j * 2) + 1] = src[i] & 0xff; j++; } } /* Zero terminate string. */ dest[(j * 2)] = 0; dest[(j * 2) + 1] = 0; return dest; } wchar_t *strGammuToPython(const unsigned char *src) { int len = 0; size_t out_len = 0; /* Get string length */ len = UnicodeLength(src); return strGammuToPythonL(src, len, &out_len); } wchar_t *strGammuToPythonL(const unsigned char *src, const int len, size_t *out_len) { wchar_t *dest; wchar_t value, second; int i; /* Allocate memory */ dest = malloc((len + 1) * sizeof(wchar_t)); if (dest == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate string"); return NULL; } /* Convert string without zero at the end. */ *out_len = 0; for (i = 0; i < len; i++) { value = (src[2 * i] << 8) + src[(2 * i) + 1]; if (value >= 0xD800 && value <= 0xDBFF) { second = src[(i + 1) * 2] * 256 + src[(i + 1) * 2 + 1]; if (second >= 0xDC00 && second <= 0xDFFF) { value = ((value - 0xD800) << 10) + (second - 0xDC00) + 0x010000; i++; } else if (second == 0) { /* Surrogate at the end of string */ value = 0xFFFD; /* REPLACEMENT CHARACTER */ } } dest[(*out_len)++] = value; } /* Add trailing zero */ dest[*out_len] = 0; return dest; } PyObject *UnicodeStringToPython(const unsigned char *src) { Py_ssize_t len; len = UnicodeLength(src); return UnicodeStringToPythonL(src, len); } PyObject *UnicodeStringToPythonL(const unsigned char *src, const Py_ssize_t len) { wchar_t *val; PyObject *res; size_t out_len = 0; val = strGammuToPythonL(src, len, &out_len); if (val == NULL) return NULL; res = PyUnicode_FromWideChar(val, out_len); free(val); return res; } PyObject *LocaleStringToPython(const char *src) { unsigned char *w; size_t len; PyObject *ret; /* Length of input */ len = strlen(src); /* Allocate it */ w = malloc(2 * (len + 5)); if (w == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate string"); return NULL; } EncodeUnicode(w, src, len); ret = UnicodeStringToPython(w); free(w); return ret; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134780.0 python-gammu-3.2.4/gammu/src/convertors/time.c0000644000175000017500000001406500000000000020343 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* DateTime conversions */ #include "convertors.h" PyObject *BuildPythonDateTime(const GSM_DateTime * dt) { PyObject *pModule; PyObject *result; if (dt->Year == 0) { Py_RETURN_NONE; } /* import datetime */ pModule = PyImport_ImportModule("datetime"); if (pModule == NULL) return NULL; /* create datetime object */ result = PyObject_CallMethod(pModule, "datetime", "iiiiii", dt->Year, dt->Month, dt->Day, dt->Hour, dt->Minute, dt->Second); Py_DECREF(pModule); return result; } PyObject *BuildPythonTime(const GSM_DateTime * dt) { PyObject *pModule; PyObject *result; /* import datetime */ pModule = PyImport_ImportModule("datetime"); if (pModule == NULL) return NULL; /* create datetime object */ result = PyObject_CallMethod(pModule, "time", "iii", dt->Hour, dt->Minute, dt->Second); Py_DECREF(pModule); return result; } int BuildGSMDateTime(PyObject * pydt, GSM_DateTime * dt) { PyObject *result; static GSM_DateTime nulldt = { 0, 0, 0, 0, 0, 0, 0 }; *dt = nulldt; if (pydt == Py_None) return 1; result = PyObject_GetAttrString(pydt, "year"); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Attribute year is missing"); return 0; } if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "year"); Py_DECREF(result); return 0; } dt->Year = PyLong_AsLong(result); Py_DECREF(result); result = PyObject_GetAttrString(pydt, "month"); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Attribute month is missing"); return 0; } if (!PyLong_Check(result)) { Py_DECREF(result); PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "month"); return 0; } dt->Month = PyLong_AsLong(result); Py_DECREF(result); result = PyObject_GetAttrString(pydt, "day"); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Attribute day is missing"); return 0; } if (!PyLong_Check(result)) { Py_DECREF(result); PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "day"); return 0; } dt->Day = PyLong_AsLong(result); Py_DECREF(result); result = PyObject_GetAttrString(pydt, "hour"); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Attribute hour is missing"); return 0; } if (!PyLong_Check(result)) { Py_DECREF(result); PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "hour"); return 0; } dt->Hour = PyLong_AsLong(result); Py_DECREF(result); result = PyObject_GetAttrString(pydt, "minute"); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Attribute minute is missing"); return 0; } if (!PyLong_Check(result)) { Py_DECREF(result); PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "minute"); return 0; } dt->Minute = PyLong_AsLong(result); Py_DECREF(result); result = PyObject_GetAttrString(pydt, "second"); if (result == NULL) { PyErr_Format(PyExc_ValueError, "Attribute second is missing"); return 0; } if (!PyLong_Check(result)) { Py_DECREF(result); PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "second"); return 0; } dt->Second = PyLong_AsLong(result); Py_DECREF(result); return 1; } int BuildGSMDate(PyObject * pydt, GSM_DateTime * dt) { PyObject *result; static GSM_DateTime nulldt = { 0, 0, 0, 0, 0, 0, 0 }; *dt = nulldt; if (pydt == Py_None) return 1; result = PyObject_GetAttrString(pydt, "year"); if (result == NULL) return 0; if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "year"); return 0; } dt->Year = PyLong_AsLong(result); result = PyObject_GetAttrString(pydt, "month"); if (result == NULL) return 0; if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "month"); return 0; } dt->Month = PyLong_AsLong(result); result = PyObject_GetAttrString(pydt, "day"); if (result == NULL) return 0; if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "day"); return 0; } dt->Day = PyLong_AsLong(result); return 1; } int BuildGSMTime(PyObject * pydt, GSM_DateTime * dt) { PyObject *result; static GSM_DateTime nulldt = { 0, 0, 0, 0, 0, 0, 0 }; *dt = nulldt; if (pydt == Py_None) return 1; result = PyObject_GetAttrString(pydt, "hour"); if (result == NULL) return 0; if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "hour"); return 0; } dt->Hour = PyLong_AsLong(result); result = PyObject_GetAttrString(pydt, "minute"); if (result == NULL) return 0; if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "minute"); return 0; } dt->Minute = PyLong_AsLong(result); result = PyObject_GetAttrString(pydt, "second"); if (result == NULL) return 0; if (!PyLong_Check(result)) { PyErr_Format(PyExc_ValueError, "Attribute %s doesn't seem to be integer", "second"); return 0; } dt->Second = PyLong_AsLong(result); return 1; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/todo.c0000644000175000017500000002433700000000000020355 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* ToDo related conversions */ #include "convertors.h" #include "misc.h" char *TodoPriorityToString(GSM_ToDo_Priority p) { char *s = NULL; switch (p) { case GSM_Priority_High: s = strdup("High"); break; case GSM_Priority_Medium: s = strdup("Medium"); break; case GSM_Priority_Low: s = strdup("Low"); break; case GSM_Priority_None: s = strdup("None"); break; case GSM_Priority_INVALID: s = strdup(""); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for TodoPriority from Gammu: '%d'", p); return NULL; } return s; } GSM_ToDo_Priority StringToTodoPriority(const char *s) { if (strcmp("High", s) == 0) return GSM_Priority_High; else if (strcmp("Medium", s) == 0) return GSM_Priority_Medium; else if (strcmp("Low", s) == 0) return GSM_Priority_Low; else if (strcmp("None", s) == 0) return GSM_Priority_None; PyErr_Format(PyExc_MemoryError, "Bad value for Todo Priority '%s'", s); return GSM_Priority_INVALID; } PyObject *TodoToPython(const GSM_ToDoEntry * entry) { PyObject *v; PyObject *f; PyObject *r; PyObject *d; int i; Py_UNICODE *s; char *p; char *t; v = PyList_New(0); if (v == NULL) return NULL; for (i = 0; i < entry->EntriesNum; i++) { f = Py_None; switch (entry->Entries[i].EntryType) { case TODO_END_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "END_DATETIME", "Value", d); Py_DECREF(d); break; case TODO_START_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "START_DATETIME", "Value", d); Py_DECREF(d); break; case TODO_COMPLETED_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "COMPLETED_DATETIME", "Value", d); Py_DECREF(d); break; case TODO_ALARM_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "ALARM_DATETIME", "Value", d); Py_DECREF(d); break; case TODO_SILENT_ALARM_DATETIME: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "SILENT_ALARM_DATETIME", "Value", d); Py_DECREF(d); break; case TODO_LAST_MODIFIED: d = BuildPythonDateTime(& (entry->Entries[i]. Date)); if (d == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:O}", "Type", "LAST_MODIFIED", "Value", d); Py_DECREF(d); break; case TODO_TEXT: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u}", "Type", "TEXT", "Value", s); free(s); break; case TODO_LOCATION: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u}", "Type", "LOCATION", "Value", s); free(s); break; case TODO_DESCRIPTION: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u}", "Type", "DESCRIPTION", "Value", s); free(s); break; case TODO_LUID: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u}", "Type", "LUID", "Value", s); free(s); break; case TODO_COMPLETED: f = Py_BuildValue("{s:s,s:i}", "Type", "COMPLETED", "Value", entry->Entries[i].Number); break; case TODO_PRIVATE: f = Py_BuildValue("{s:s,s:i}", "Type", "PRIVATE", "Value", entry->Entries[i].Number); break; case TODO_CATEGORY: f = Py_BuildValue("{s:s,s:i}", "Type", "CATEGORY", "Value", entry->Entries[i].Number); break; case TODO_CONTACTID: f = Py_BuildValue("{s:s,s:i}", "Type", "CONTACTID", "Value", entry->Entries[i].Number); break; case TODO_PHONE: s = strGammuToPython(entry->Entries[i].Text); if (s == NULL) { Py_DECREF(v); return NULL; } f = Py_BuildValue("{s:s,s:u}", "Type", "PHONE", "Value", s); free(s); break; } if (f == Py_None) { Py_DECREF(v); PyErr_Format(PyExc_ValueError, "Bad ToDo item type from gammu: %d", entry->Entries[i].EntryType); return NULL; } if (f == NULL) { Py_DECREF(v); return NULL; } if (PyList_Append(v, f) != 0) { Py_DECREF(f); Py_DECREF(v); return NULL; } Py_DECREF(f); } p = TodoPriorityToString(entry->Priority); if (p == NULL) { Py_DECREF(v); return NULL; } t = CalendarTypeToString(entry->Type); if (t == NULL) { free(p); Py_DECREF(v); return NULL; } r = Py_BuildValue("{s:i,s:s,s:s,s:O}", "Location", entry->Location, "Type", t, "Priority", p, "Entries", v); free(p); free(t); Py_DECREF(v); return r; } int TodoFromPython(PyObject * dict, GSM_ToDoEntry * entry, int needs_location) { PyObject *o; PyObject *item; Py_ssize_t len; Py_ssize_t i; char *p; char *t; char *type; char valuetype; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "Todo entry is not a dictionary"); return 0; } memset(entry, 0, sizeof(GSM_ToDoEntry)); if (needs_location) { entry->Location = GetIntFromDict(dict, "Location"); if (entry->Location == INT_INVALID) return 0; } t = GetCharFromDict(dict, "Type"); if (t == NULL) return 0; entry->Type = StringToCalendarType(t); free(t); if (entry->Type == 0) return 0; p = GetCharFromDict(dict, "Priority"); if (p == NULL) return 0; entry->Priority = StringToTodoPriority(p); free(p); if (entry->Priority == GSM_Priority_INVALID) return 0; o = PyDict_GetItemString(dict, "Entries"); if (o == NULL) { PyErr_Format(PyExc_ValueError, "Can not get string value for key Values"); return 0; } if (!PyList_Check(o)) { PyErr_Format(PyExc_ValueError, "Key Values doesn't contain list"); return 0; } len = PyList_Size(o); if (len > GSM_TODO_ENTRIES) { pyg_warning("Using just %i entries from list!", GSM_TODO_ENTRIES); len = GSM_TODO_ENTRIES; } entry->EntriesNum = len; for (i = 0; i < len; i++) { item = PyList_GetItem(o, i); if (item == NULL) return 0; if (!PyDict_Check(item)) { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Values is not dictionary", i); return 0; } type = GetCharFromDict(item, "Type"); if (type == NULL) return 0; if (strcmp("END_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = TODO_END_DATETIME; } else if (strcmp("START_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = TODO_START_DATETIME; } else if (strcmp("COMPLETED_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = TODO_COMPLETED_DATETIME; } else if (strcmp("COMPLETED", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = TODO_COMPLETED; } else if (strcmp("ALARM_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = TODO_ALARM_DATETIME; } else if (strcmp("SILENT_ALARM_DATETIME", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = TODO_SILENT_ALARM_DATETIME; } else if (strcmp("LAST_MODIFIED", type) == 0) { valuetype = 'd'; entry->Entries[i].EntryType = TODO_LAST_MODIFIED; } else if (strcmp("LUID", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = TODO_LUID; } else if (strcmp("LOCATION", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = TODO_LOCATION; } else if (strcmp("DESCRIPTION", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = TODO_DESCRIPTION; } else if (strcmp("TEXT", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = TODO_TEXT; } else if (strcmp("PRIVATE", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = TODO_PRIVATE; } else if (strcmp("CATEGORY", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = TODO_CATEGORY; } else if (strcmp("CONTACTID", type) == 0) { valuetype = 'n'; entry->Entries[i].EntryType = TODO_CONTACTID; } else if (strcmp("PHONE", type) == 0) { valuetype = 't'; entry->Entries[i].EntryType = TODO_PHONE; } else { PyErr_Format(PyExc_ValueError, "Element %" PY_FORMAT_SIZE_T "d in Values has bad type: %s", i, type); free(type); return 0; } free(type); switch (valuetype) { case 'n': entry->Entries[i].Number = GetIntFromDict(item, "Value"); if (entry->Entries[i].Number == INT_INVALID) return 0; break; case 't': if (!CopyStringFromDict (item, "Value", GSM_PHONEBOOK_TEXT_LENGTH, entry->Entries[i].Text)) return 0; break; case 'd': entry->Entries[i].Date = GetDateTimeFromDict(item, "Value"); if (entry->Entries[i].Date.Year == -1) return 0; break; } } /* end for */ return 1; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/convertors/wap.c0000644000175000017500000001105600000000000020171 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* MMS and WAP related conversions */ #include "convertors.h" char *MMSClassToString(GSM_MMS_Class c) { char *s = NULL; switch (c) { case GSM_MMS_Personal: s = strdup("Personal"); break; case GSM_MMS_Advertisement: s = strdup("Advertisement"); break; case GSM_MMS_Info: s = strdup("Info"); break; case GSM_MMS_Auto: s = strdup("Auto"); break; case GSM_MMS_None: case GSM_MMS_INVALID: s = strdup(""); break; } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Bad value for MMS Class from Gammu: '%d'", c); return NULL; } return s; } GSM_MMS_Class MMSClassFromString(const char *s) { if (strcmp("Personal", s) == 0) return GSM_MMS_Personal; else if (strcmp("Advertisement", s) == 0) return GSM_MMS_Advertisement; else if (strcmp("Info", s) == 0) return GSM_MMS_Info; else if (strcmp("Auto", s) == 0) return GSM_MMS_Auto; else if (strcmp("", s) == 0) return GSM_MMS_None; PyErr_Format(PyExc_MemoryError, "Bad value for MMS Class Type '%s'", s); return GSM_MMS_INVALID; } PyObject *MMSIndicatorToPython(GSM_MMSIndicator * mms) { char *class; PyObject *ret; class = MMSClassToString(mms->Class); if (class == NULL) { return NULL; } ret = Py_BuildValue("{s:s,s:s,s:s,s:i,s:s}", "Address", mms->Address, "Title", mms->Title, "Sender", mms->Sender, "MessageSize", (int)mms->MessageSize, "Class", class); free(class); return ret; } int MMSIndicatorFromPython(PyObject * dict, GSM_MMSIndicator * mms) { char *s; if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "MMSIndicator is not a dictionary"); return 0; } memset(mms, 0, sizeof(GSM_MMSIndicator)); s = GetCharFromDict(dict, "Address"); if (s == NULL) { PyErr_Format(PyExc_ValueError, "Address is missing!"); return 0; } else if (strlen(s) > 499) { PyErr_Format(PyExc_ValueError, "Address too long!"); free(s); return 0; } strcpy(s, mms->Address); free(s); s = GetCharFromDict(dict, "Title"); if (s == NULL) { PyErr_Format(PyExc_ValueError, "Title is missing!"); return 0; } else if (strlen(s) > 499) { free(s); PyErr_Format(PyExc_ValueError, "Title too long!"); return 0; } strcpy(s, mms->Title); free(s); s = GetCharFromDict(dict, "Sender"); if (s == NULL) { PyErr_Format(PyExc_ValueError, "Sender is missing!"); return 0; } else if (strlen(s) > 499) { free(s); PyErr_Format(PyExc_ValueError, "Sender too long!"); return 0; } strcpy(s, mms->Sender); free(s); mms->MessageSize = GetIntFromDict(dict, "MessageSender"); if (mms->MessageSize == INT_INVALID) { mms->MessageSize = 0; } s = GetCharFromDict(dict, "Class"); if (s != NULL) { mms->Class = MMSClassFromString(s); free(s); if (mms->Class == GSM_MMS_INVALID) { return 0; } } return 1; } PyObject *WAPBookmarkToPython(GSM_WAPBookmark * wap) { PyObject *ret; Py_UNICODE *title, *address; title = strGammuToPython(wap->Title); if (title == NULL) return NULL; address = strGammuToPython(wap->Address); if (address == NULL) { free(title); return NULL; } ret = Py_BuildValue("{s:s,s:s,s:i}", "Address", address, "Title", title, "Location", wap->Location); free(title); free(address); return ret; } int WAPBookmarkFromPython(PyObject * dict, GSM_WAPBookmark * wap) { if (!PyDict_Check(dict)) { PyErr_Format(PyExc_ValueError, "WAPBookmark is not a dictionary"); return 0; } memset(wap, 0, sizeof(GSM_WAPBookmark)); wap->Location = GetIntFromDict(dict, "Location"); if (wap->Location == INT_INVALID) return 0; if (!CopyStringFromDict(dict, "Address", 255, wap->Address)) return 0; if (!CopyStringFromDict(dict, "Title", 50, wap->Title)) return 0; return 1; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/gammu/src/data.c0000644000175000017500000000342200000000000016105 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #include "data.h" #include "convertors.h" int gammu_create_data(PyObject *d) { PyObject *country_list; PyObject *network_list; PyObject *val; int i; country_list = PyDict_New(); if (country_list == NULL) return 0; for (i = 0; GSM_Countries[i].Code[0] != 0; i++) { val = PyUnicode_FromString(GSM_Countries[i].Name); PyDict_SetItemString(country_list, GSM_Countries[i].Code, val); Py_DECREF(val); } PyDict_SetItemString(d, "GSMCountries", country_list); Py_DECREF(country_list); network_list = PyDict_New(); if (network_list == NULL) return 0; for (i = 0; GSM_Networks[i].Code[0] != 0; i++) { val = PyUnicode_FromString(GSM_Networks[i].Name); PyDict_SetItemString(network_list, GSM_Networks[i].Code, val); Py_DECREF(val); } PyDict_SetItemString(d, "GSMNetworks", network_list); Py_DECREF(network_list); return 1; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/gammu/src/errors.c0000644000175000017500000001122400000000000016507 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #include "errors.h" #include "convertors.h" PyObject *GammuError; PyObject *gammu_error_map[ERR_LAST_VALUE + 1]; int checkError(GSM_Error error, const char *where) { PyObject *val = NULL; PyObject *text; PyObject *err = GammuError; const char *msg; if (error == ERR_NONE) return 1; if (error < ERR_LAST_VALUE && error >= ERR_NONE) err = gammu_error_map[error]; msg = GSM_ErrorString(error); text = LocaleStringToPython(msg); if (text != NULL) { val = Py_BuildValue("{s:O,s:s,s:i}", "Text", text, "Where", where, "Code", error); Py_DECREF(text); } if (val == NULL) { PyErr_Format(err, "GSM Error %d (%s) in %s", error, msg, where); } else { PyErr_SetObject(err, val); Py_DECREF(val); } return 0; } int gammu_create_errors(PyObject *d) { PyObject *help_text; PyObject *error_dict; PyObject *error_list; PyObject *errornumber_list; PyObject *id; GSM_Error error; char errname[100]; char errhelp[4096]; /* Prepare dict for error codes */ error_list = PyDict_New(); if (error_list == NULL) return 0; errornumber_list = PyDict_New(); if (errornumber_list == NULL) return 0; /* Help text */ help_text = PyUnicode_FromString("Generic class as parent for all gammu exceptions. This is never raised directly."); if (help_text == NULL) return 0; error_dict = PyDict_New(); if (error_dict == NULL) return 0; PyDict_SetItemString(error_dict, "__doc__", help_text); Py_DECREF(help_text); /* Create exception */ GammuError = PyErr_NewException("gammu.GSMError", NULL, error_dict); Py_DECREF(error_dict); if (GammuError == NULL) return 0; PyDict_SetItemString(d, "GSMError", GammuError); Py_DECREF(GammuError); /* Create exception objects and mappings */ for (error = ERR_NONE; error < ERR_LAST_VALUE; error++) { /* Do we know name of this exception? */ if (GSM_ErrorName(error) == NULL) { pyg_error("failed to convert error code %d to string!\n", error); continue; } /* Help text */ snprintf( errhelp, sizeof(errhelp) - 1, "Exception corresponding to gammu error ERR_%s.\n" "Verbose error description: %s", GSM_ErrorName(error), GSM_ErrorString(error) ); help_text = PyUnicode_FromString(errhelp); if (help_text == NULL) return 0; /* Exception dictionary (contains only help for now) */ error_dict = PyDict_New(); if (error_dict == NULL) return 0; PyDict_SetItemString(error_dict, "__doc__", help_text); Py_DECREF(help_text); /* Create exception */ strcpy(errname, "gammu.ERR_"); strcat(errname, GSM_ErrorName(error)); gammu_error_map[error] = PyErr_NewException(errname, GammuError, error_dict); Py_DECREF(error_dict); if (gammu_error_map[error] == NULL) return 0; /* Add it to module dictionary */ strcpy(errname, "ERR_"); strcat(errname, GSM_ErrorName(error)); PyDict_SetItemString(d, errname, gammu_error_map[error]); Py_DECREF(gammu_error_map[error]); /* Store ids in dictionary */ id = PyLong_FromLong(error); if (id == NULL) return 0; PyDict_SetItemString(error_list, errname, id); PyDict_SetItem(errornumber_list, id, PyUnicode_FromString(errname)); Py_DECREF(id); } /* Add ID dictionaries to module */ PyDict_SetItemString(d, "Errors", error_list); Py_DECREF(error_list); PyDict_SetItemString(d, "ErrorNumbers", errornumber_list); Py_DECREF(errornumber_list); return 1; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134884.0 python-gammu-3.2.4/gammu/src/gammu.c0000644000175000017500000057026200000000000016315 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #define PY_SSIZE_T_CLEAN /* Python-gammu configuration */ #include #include /* Gammu includes */ #include #include /* Locales */ #include /* Strings */ #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif /* For locking */ #ifdef WITH_THREAD #include #endif /* Convertors between Gammu and Python types */ #include "convertors.h" /* Error objects */ #include "errors.h" /* Data objects */ #include "data.h" /* Other useful stuff */ #include "misc.h" /* Length of buffers used in most of code */ #define BUFFER_LENGTH 255 #ifdef WITH_THREAD /* Use python locking */ #define BEGIN_PHONE_COMM \ Py_BEGIN_ALLOW_THREADS \ PyThread_acquire_lock(self->mutex, 1); #define END_PHONE_COMM \ PyThread_release_lock(self->mutex); \ Py_END_ALLOW_THREADS \ CheckIncomingEvents(self); #else /* No need for locking when no threads */ #define BEGIN_PHONE_COMM #define END_PHONE_COMM \ CheckIncomingEvents(self); #endif PyObject *DebugFile; #define MAX_EVENTS 10 /* ----------------------------------------------------- */ /* Declarations for objects of type StateMachine */ typedef struct { PyObject_HEAD GSM_StateMachine *s; PyObject *DebugFile; PyObject *IncomingCallback; volatile GSM_Error SMSStatus; volatile int MessageReference; GSM_Call *IncomingCallQueue[MAX_EVENTS + 1]; GSM_SMSMessage *IncomingSMSQueue[MAX_EVENTS + 1]; GSM_CBMessage *IncomingCBQueue[MAX_EVENTS + 1]; GSM_USSDMessage *IncomingUSSDQueue[MAX_EVENTS + 1]; GSM_MemoryType memory_entry_cache_type; int memory_entry_cache; int todo_entry_cache; int calendar_entry_cache; #ifdef WITH_THREAD PyThread_type_lock mutex; #endif } StateMachineObject; static PyObject * gammu_set_debug(GSM_Debug_Info *di, PyObject *value, PyObject **debug_object) { char *s; FILE *f; GSM_Error error; PyObject *new_debug_object = NULL; PyObject *str; int fd; fd = PyObject_AsFileDescriptor(value); if (fd == -1) { PyErr_Clear(); } if (value == Py_None) { error = GSM_SetDebugFileDescriptor(NULL, FALSE, di); if (!checkError(error, "SetDebugFileDescriptor")) return NULL; } else if (fd != -1) { new_debug_object = value; fd = dup(fd); if (fd == -1) return NULL; f = fdopen(fd, "a"); if (f == NULL) return NULL; error = GSM_SetDebugFileDescriptor(f, TRUE, di); if (!checkError(error, "SetDebugFileDescriptor")) return NULL; } else if (PyUnicode_Check(value)) { str = PyUnicode_EncodeFSDefault(value); if (str == NULL) { return NULL; } s = PyBytes_AsString(str); if (s == NULL) return NULL; error = GSM_SetDebugFile(s, di); Py_DECREF(str); if (!checkError(error, "SetDebugFile")) return NULL; } else { PyErr_SetString(PyExc_TypeError, "Valid are only None, string or file parameters!"); return NULL; } if (*debug_object != NULL) { Py_DECREF(*debug_object); *debug_object = NULL; } if (new_debug_object != NULL) { Py_INCREF(new_debug_object); } *debug_object = new_debug_object; Py_RETURN_NONE; } /* ---------------------------------------------------------------- */ /* * Callbacks follow. Those are common for all state machines and thus need to * lookup correct state machine. */ /** * SMS sending status callback, we handle this ourself and this is not * published. */ static void SendSMSStatus (GSM_StateMachine *s, int status, int mr, void *user) { StateMachineObject *sm = (StateMachineObject *)user; if (sm == NULL) { pyg_error("Received callback without user pointer!\n"); return; } if (sm->s != s) { pyg_error("Callback user pointer doesn't match state machine!\n"); return; } sm->MessageReference = mr; if (status == 0) { sm->SMSStatus = ERR_NONE; } else if (status == 322) { sm->SMSStatus = ERR_FULL; } else { sm->SMSStatus = ERR_UNKNOWN; } } /** * Incoming call callback. */ static void IncomingCall (GSM_StateMachine *s, GSM_Call *call, void *user) { StateMachineObject *sm = (StateMachineObject *)user; GSM_Call *message; int i = 0; if (sm == NULL) { pyg_error("Received callback without user pointer!\n"); return; } if (sm->s != s) { pyg_error("Callback user pointer doesn't match state machine!\n"); return; } while (i < MAX_EVENTS && sm->IncomingCallQueue[i] != NULL) i++; if (i == MAX_EVENTS) { pyg_error("Incoming call queue overflow!\n"); return; } message = malloc(sizeof(GSM_Call)); if (message == NULL) return; *message = *call; sm->IncomingCallQueue[i + 1] = NULL; sm->IncomingCallQueue[i] = message; } /** * Incoming SMS callback. */ static void IncomingSMS (GSM_StateMachine *s, GSM_SMSMessage *msg, void *user) { StateMachineObject *sm = (StateMachineObject *)user; GSM_SMSMessage *message; int i = 0; if (sm == NULL) { pyg_error("Received callback without user pointer!\n"); return; } if (sm->s != s) { pyg_error("Callback user pointer doesn't match state machine!\n"); return; } while (i < MAX_EVENTS && sm->IncomingSMSQueue[i] != NULL) i++; if (i == MAX_EVENTS) { pyg_error("Incoming SMS queue overflow!\n"); return; } message = malloc(sizeof(GSM_SMSMessage)); if (message == NULL) return; *message = *msg; sm->IncomingSMSQueue[i + 1] = NULL; sm->IncomingSMSQueue[i] = message; } /** * Incoming CB callback. */ static void IncomingCB (GSM_StateMachine *s, GSM_CBMessage *cb, void *user) { StateMachineObject *sm = (StateMachineObject *)user; GSM_CBMessage *message; int i = 0; if (sm == NULL) { pyg_error("Received callback without user pointer!\n"); return; } if (sm->s != s) { pyg_error("Callback user pointer doesn't match state machine!\n"); return; } while (i < MAX_EVENTS && sm->IncomingCBQueue[i] != NULL) i++; if (i == MAX_EVENTS) { pyg_error("Incoming CB queue overflow!\n"); return; } message = malloc(sizeof(GSM_CBMessage)); if (message == NULL) return; *message = *cb; sm->IncomingCBQueue[i + 1] = NULL; sm->IncomingCBQueue[i] = message; } /** * Incoming USSD callback. */ static void IncomingUSSD (GSM_StateMachine *s, GSM_USSDMessage *ussd, void *user) { StateMachineObject *sm = (StateMachineObject *)user; GSM_USSDMessage *message; int i = 0; if (sm == NULL) { pyg_error("Received callback without user pointer!\n"); return; } if (sm->s != s) { pyg_error("Callback user pointer doesn't match state machine!\n"); return; } while (i < MAX_EVENTS && sm->IncomingUSSDQueue[i] != NULL) i++; if (i == MAX_EVENTS) { pyg_error("Incoming USSD queue overflow!\n"); return; } pyg_warning("Adding USSD to queue, position %d\n", i); message = malloc(sizeof(GSM_USSDMessage)); if (message == NULL) return; *message = *ussd; sm->IncomingUSSDQueue[i + 1] = NULL; sm->IncomingUSSDQueue[i] = message; } /** * Process queue of incoming events from phone. */ static void CheckIncomingEvents(StateMachineObject *sm) { int i; PyObject *arglist; PyObject *event; if (sm->IncomingCallQueue[0] != NULL) { event = CallToPython(sm->IncomingCallQueue[0]); if (event == NULL) { pyg_error("Discarding incoming call event due to conversion error!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } arglist = Py_BuildValue("(OsO)", sm, "Call", event); Py_DECREF(event); free(sm->IncomingCallQueue[0]); /* Shift queue */ i = 0; do { sm->IncomingCallQueue[i] = sm->IncomingCallQueue[i + 1]; i++; } while (i < MAX_EVENTS && sm->IncomingCallQueue[i] != NULL); if (arglist == NULL) { pyg_error("Discarding incoming call event due to error while building params!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } PyObject_Call(sm->IncomingCallback, arglist, NULL); Py_DECREF(arglist); } if (sm->IncomingSMSQueue[0] != NULL) { /* Did we get full message on location only? */ if (sm->IncomingSMSQueue[0]->State == 0) { /* Location only */ event = Py_BuildValue("{s:i,s:i,s:i}", "Location", sm->IncomingSMSQueue[0]->Location, "Folder", sm->IncomingSMSQueue[0]->Folder, "InboxFolder", (int)sm->IncomingSMSQueue[0]->InboxFolder ); } else { event = SMSToPython(sm->IncomingSMSQueue[0]); if (event == NULL) { pyg_error("Discarding incoming SMS event due to conversion error!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } } free(sm->IncomingSMSQueue[0]); /* Shift queue */ i = 0; do { sm->IncomingSMSQueue[i] = sm->IncomingSMSQueue[i + 1]; i++; } while (i < MAX_EVENTS && sm->IncomingSMSQueue[i] != NULL); arglist = Py_BuildValue("(OsO)", sm, "SMS", event); Py_DECREF(event); if (arglist == NULL) { pyg_error("Discarding incoming SMS event due to error while building params!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } PyObject_Call(sm->IncomingCallback, arglist, NULL); Py_DECREF(arglist); } if (sm->IncomingCBQueue[0] != NULL) { event = CBToPython(sm->IncomingCBQueue[0]); if (event == NULL) { pyg_error("Discarding incoming CB event due to conversion error!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } arglist = Py_BuildValue("(OsO)", sm, "CB", event); Py_DECREF(event); free(sm->IncomingCBQueue[0]); /* Shift queue */ i = 0; do { sm->IncomingCBQueue[i] = sm->IncomingCBQueue[i + 1]; i++; } while (i < MAX_EVENTS && sm->IncomingCBQueue[i] != NULL); if (arglist == NULL) { pyg_error("Discarding incoming CB event due to error while building params!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } PyObject_Call(sm->IncomingCallback, arglist, NULL); Py_DECREF(arglist); } if (sm->IncomingUSSDQueue[0] != NULL) { event = USSDToPython(sm->IncomingUSSDQueue[0]); if (event == NULL) { pyg_error("Discarding incoming USSD event due to conversion error!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } arglist = Py_BuildValue("(OsO)", sm, "USSD", event); Py_DECREF(event); free(sm->IncomingUSSDQueue[0]); /* Shift queue */ i = 0; do { sm->IncomingUSSDQueue[i] = sm->IncomingUSSDQueue[i + 1]; i++; } while (i < MAX_EVENTS && sm->IncomingUSSDQueue[i] != NULL); if (arglist == NULL) { pyg_error("Discarding incoming USSD event due to error while building params!\n"); PyErr_WriteUnraisable((PyObject *)sm); return; } PyObject_Call(sm->IncomingCallback, arglist, NULL); } } /* ---------------------------------------------------------------- */ static char StateMachine_GetConfig__doc__[] = "GetConfig(Section)\n\n" "Gets specified config section. Configuration consists of all params which can be defined in gammurc config file:\n" " - Model\n" " - DebugLevel\n" " - Device\n" " - Connection\n" " - SyncTime\n" " - LockDevice\n" " - DebugFile\n" " - StartInfo\n" " - UseGlobalDebugFile\n" "\n" "@param Section: Index of config section to read. Defaults to 0.\n" "@type Section: int\n" "@return: Hash containing configuration\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetConfig(StateMachineObject *self, PyObject *args, PyObject *kwds) { int section = 0; static char *kwlist[] = {"Section", NULL}; GSM_Config *Config; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, §ion)) return NULL; if (GSM_GetConfigNum(self->s) <= section) { PyErr_Format(PyExc_ValueError, "Requested configuration not available (requested: %d, available: %d)", section, GSM_GetConfigNum(self->s)); return NULL; } Config = GSM_GetConfig(self->s, section); if (Config == NULL) { PyErr_Format(PyExc_ValueError, "Requested configuration not available"); return NULL; } return Py_BuildValue("{s:s,s:s,s:s,s:s,s:s,s:i,s:i,s:i,s:i}", "Model", Config->Model, "DebugLevel", Config->DebugLevel, "Device", Config->Device, "Connection", Config->Connection, "DebugFile", Config->DebugFile, "SyncTime", Config->SyncTime, "LockDevice", Config->LockDevice, "StartInfo", Config->StartInfo, "UseGlobalDebugFile", Config->UseGlobalDebugFile); } static char StateMachine_SetConfig__doc__[] = "SetConfig(Section, Values)\n\n" "Sets specified config section.\n\n" "@param Section: Index of config section to modify\n" "@type Section: int\n" "@param Values: Config values, see L{GetConfig} for description of accepted\n" "@type Values: hash\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetConfig(StateMachineObject *self, PyObject *args, PyObject *kwds) { int section = 0; static char *kwlist[] = {"Section", "Values", NULL}; PyObject *key, *value, *str, *keystr; PyObject *dict; char *s, *v, *setv; Py_ssize_t pos = 0; GSM_Config *Config; if (!PyArg_ParseTupleAndKeywords(args, kwds, "IO!", kwlist, §ion, &PyDict_Type, &dict)) return NULL; /* Get pointer to configuration data */ Config = GSM_GetConfig(self->s, section); if (Config == NULL) { PyErr_Format(PyExc_ValueError, "Requested configuration not available"); return NULL; } while (PyDict_Next(dict, &pos, &key, &value)) { keystr = NULL; s = NULL; if (PyUnicode_Check(key)) { keystr = PyUnicode_AsASCIIString(key); if (keystr == NULL) { return NULL; } s = PyBytes_AsString(keystr); } if (s == NULL) { PyErr_Format(PyExc_ValueError, "Non string key in configuration values"); return NULL; } if (strcmp(s, "UseGlobalDebugFile") == 0) { Config->UseGlobalDebugFile = BoolFromPython(value, "UseGlobalDebugFile"); if (Config->UseGlobalDebugFile == BOOL_INVALID) { return NULL; } } else if (strcmp(s, "LockDevice") == 0) { Config->LockDevice = BoolFromPython(value, "LockDevice"); if (Config->LockDevice == BOOL_INVALID) { return NULL; } } else if (strcmp(s, "StartInfo") == 0) { Config->StartInfo = BoolFromPython(value, "StartInfo"); if (Config->StartInfo == BOOL_INVALID) { return NULL; } } else if (strcmp(s, "SyncTime") == 0) { Config->SyncTime = BoolFromPython(value, "SyncTime"); if (Config->SyncTime == BOOL_INVALID) { return NULL; } } else { if (PyBytes_Check(value) || PyUnicode_Check(value)) { if (PyUnicode_Check(value)) { str = PyUnicode_EncodeFSDefault(value); if (str == NULL) { PyErr_Format(PyExc_ValueError, "Non string value for %s (unicode)", s); return NULL; } } else { str = value; Py_INCREF(str); } v = PyBytes_AsString(str); if (v == NULL) { PyErr_Format(PyExc_ValueError, "Non string value for (string) %s", s); return NULL; } else { setv = strdup(v); } Py_DECREF(str); } else { v = NULL; if (value == Py_None) { setv = NULL; } else { PyErr_Format(PyExc_ValueError, "Non string value for %s", s); return NULL; } } if (strcmp(s, "Model") == 0) { free(setv); if (v == NULL) { Config->Model[0] = 0; } else { mystrncpy(Config->Model, v, sizeof(Config->Model) - 1); } } else if (strcmp(s, "DebugLevel") == 0) { free(setv); if (v == NULL) { Config->DebugLevel[0] = 0; } else { mystrncpy(Config->DebugLevel, v, sizeof(Config->DebugLevel) - 1); } } else if (strcmp(s, "Device") == 0) { free(Config->Device); Config->Device = setv; } else if (strcmp(s, "Connection") == 0) { free(Config->Connection); Config->Connection = setv; } else if (strcmp(s, "DebugFile") == 0) { free(Config->DebugFile); Config->DebugFile = setv; } else if (strcmp(s, "Localize") == 0) { /* We ignore this for backward compatibility */ free(setv); } else { free(setv); PyErr_Format(PyExc_ValueError, "Uknown key: %s", s); return NULL; } } if (keystr != NULL) { Py_DECREF(keystr); } } /* Tell Gammu we have configured another section */ GSM_SetConfigNum(self->s, section + 1); Py_RETURN_NONE; } static char StateMachine_ReadConfig__doc__[] = "ReadConfig(Section, Configuration, Filename)\n\n" "Reads specified section of gammurc\n\n" "@param Section: Index of config section to read. Defaults to 0.\n" "@type Section: int\n" "@param Configuration: Index where config section will be stored. Defaults to Section.\n" "@type Configuration: int\n" "@param Filename: Path to configuration file (otherwise it is autodetected).\n" "@type Filename: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_ReadConfig(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int section = 0; int dst = -1; INI_Section *cfg; char *cfg_path = NULL; GSM_Config *Config; static char *kwlist[] = {"Section", "Configuration", "Filename", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|IIs", kwlist, §ion, &dst, &cfg_path)) return NULL; if (dst == -1) dst = section; Config = GSM_GetConfig(self->s, dst); if (Config == NULL) { PyErr_Format(PyExc_ValueError, "Maximal configuration storage exceeded"); return NULL; } error = GSM_FindGammuRC(&cfg, cfg_path); if (!checkError(error, "FindGammuRC via ReadConfig")) return NULL; if (cfg == NULL) { PyErr_SetString(PyExc_IOError, "Can not read gammurc"); return NULL; } error = GSM_ReadConfig(cfg, Config, section); if (!checkError(error, "ReadConfig")) { INI_Free(cfg); return NULL; } Config->UseGlobalDebugFile = FALSE; /* Tell Gammu we have configured another section */ GSM_SetConfigNum(self->s, dst + 1); INI_Free(cfg); Py_RETURN_NONE; } static char StateMachine_Init__doc__[] = "Init(Replies)\n\n" "Initialises the connection with phone.\n\n" "@param Replies: Number of replies to wait for on each request. Defaults to 1.\n" "@type Replies: int\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_Init(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int replies = 1; static char *kwlist[] = {"Replies", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &replies)) return NULL; BEGIN_PHONE_COMM error = GSM_InitConnection(self->s, replies); END_PHONE_COMM if (!checkError(error, "Init")) return NULL; /* Set callbacks */ GSM_SetIncomingCallCallback(self->s, IncomingCall, self); GSM_SetIncomingSMSCallback(self->s, IncomingSMS, self); GSM_SetIncomingCBCallback(self->s, IncomingCB, self); GSM_SetIncomingUSSDCallback(self->s, IncomingUSSD, self); GSM_SetSendSMSStatusCallback(self->s, SendSMSStatus, self); /* No cached data */ self->memory_entry_cache_type = 0; self->memory_entry_cache = 1; self->todo_entry_cache = 1; self->calendar_entry_cache = 1; Py_RETURN_NONE; } static char StateMachine_Abort__doc__[] = "Abort()\n\n" "Aborts current operation.\n\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_Abort(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; error = GSM_AbortOperation(self->s); if (!checkError(error, "Abort")) return NULL; Py_RETURN_NONE; } static char StateMachine_Terminate__doc__[] = "Terminate()\n\n" "Terminates the connection with phone.\n\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_Terminate(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; /* Disable any possible incoming notifications */ BEGIN_PHONE_COMM GSM_SetIncomingSMS(self->s, FALSE); GSM_SetIncomingCall(self->s, FALSE); GSM_SetIncomingCB(self->s, FALSE); GSM_SetIncomingUSSD(self->s, FALSE); END_PHONE_COMM /* Remove callbacks */ GSM_SetIncomingCallCallback(self->s, NULL, NULL); GSM_SetIncomingSMSCallback(self->s, NULL, NULL); GSM_SetIncomingCBCallback(self->s, NULL, NULL); GSM_SetIncomingUSSDCallback(self->s, NULL, NULL); GSM_SetSendSMSStatusCallback(self->s, NULL, NULL); if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_TerminateConnection(self->s); END_PHONE_COMM if (!checkError(error, "Terminate")) return NULL; Py_RETURN_NONE; } static char StateMachine_ReadDevice__doc__[] = "ReadDevice(Wait)\n\n" "Reads data from device.\n\n" "@param Wait: Whether to wait, default is not to wait.\n" "@type Wait: boolean\n" "@return: Number of bytes read\n" "@rtype: int\n" ; static PyObject * StateMachine_ReadDevice(StateMachineObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Wait", NULL}; PyObject *o = Py_None; gboolean waiting = FALSE; long int result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &o)) return NULL; if (o != Py_None) { waiting = BoolFromPython(o, "Wait"); if (waiting == BOOL_INVALID) { return NULL; } } BEGIN_PHONE_COMM result = GSM_ReadDevice(self->s, waiting); END_PHONE_COMM return PyLong_FromLong(result); } /*******************/ /* GetManufacturer */ /*******************/ static char StateMachine_GetManufacturer__doc__[] = "GetManufacturer()\n\n" "Reads manufacturer from phone.\n\n" "@return: String with manufacturer name\n" "@rtype: string\n" ; static PyObject * StateMachine_GetManufacturer(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char value[GSM_MAX_MANUFACTURER_LENGTH + 1]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetManufacturer(self->s, value); END_PHONE_COMM if (!checkError(error, "GetManufacturer")) return NULL; return Py_BuildValue("s", value); } /************/ /* GetModel */ /************/ static char StateMachine_GetModel__doc__[] = "GetModel()\n\n" "Reads model from phone.\n\n" "@return: Tuple containing gammu identification and real model returned by phone.\n" "@rtype: tuple\n" ; static PyObject * StateMachine_GetModel(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char value[GSM_MAX_MODEL_LENGTH + 1]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetModel(self->s, value); END_PHONE_COMM if (!checkError(error, "GetModel")) return NULL; return Py_BuildValue("ss", GSM_GetModelInfo(self->s)->model, value); } /***************/ /* GetFirmware */ /***************/ static char StateMachine_GetFirmware__doc__[] = "GetFirmware()\n\n" "Reads firmware information from phone.\n\n" "@return: Tuple from version, date and numeric version.\n" "@rtype: tuple\n" ; static PyObject * StateMachine_GetFirmware(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char firmware[GSM_MAX_VERSION_LENGTH + 1]; char date[GSM_MAX_VERSION_DATE_LENGTH + 1]; double ver; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetFirmware(self->s, firmware, date, &ver); END_PHONE_COMM if (!checkError(error, "GetFirmware")) return NULL; return Py_BuildValue("(s,s,d)", firmware, date, ver); } /***********/ /* GetIMEI */ /***********/ static char StateMachine_GetIMEI__doc__[] = "GetIMEI()\n\n" "Reads IMEI/serial number from phone.\n\n" "@return: IMEI of phone as string.\n" "@rtype: string\n" ; static PyObject * StateMachine_GetIMEI(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char value[GSM_MAX_IMEI_LENGTH + 1]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetIMEI(self->s, value); END_PHONE_COMM if (!checkError(error, "GetIMEI")) return NULL; return Py_BuildValue("s", value); } /*******************/ /* GetOriginalIMEI */ /*******************/ static char StateMachine_GetOriginalIMEI__doc__[] = "GetOriginalIMEI()\n\n" "Gets original IMEI from phone.\n\n" "@return: Original IMEI of phone as string.\n" "@rtype: string\n" ; static PyObject * StateMachine_GetOriginalIMEI(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char buffer[BUFFER_LENGTH]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetOriginalIMEI(self->s, buffer); END_PHONE_COMM if (!checkError(error, "GetOriginalIMEI")) return NULL; return Py_BuildValue("s", buffer); } /***********************/ /* GetManufactureMonth */ /***********************/ static char StateMachine_GetManufactureMonth__doc__[] = "GetManufactureMonth()\n\n" "Gets month when device was manufactured.\n\n" "@return: Month of manufacture as string.\n" "@rtype: string\n" ; static PyObject * StateMachine_GetManufactureMonth(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char buffer[BUFFER_LENGTH]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetManufactureMonth(self->s, buffer); END_PHONE_COMM if (!checkError(error, "GetManufactureMonth")) return NULL; return Py_BuildValue("s", buffer); } /******************/ /* GetProductCode */ /******************/ static char StateMachine_GetProductCode__doc__[] = "GetProductCode()\n\n" "Gets product code of device.\n" "@return: Product code as string.\n" "@rtype: string\n" ; static PyObject * StateMachine_GetProductCode(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char buffer[BUFFER_LENGTH]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetProductCode(self->s, buffer); END_PHONE_COMM if (!checkError(error, "GetProductCode")) return NULL; return Py_BuildValue("s", buffer); } /***************/ /* GetHardware */ /***************/ static char StateMachine_GetHardware__doc__[] = "GetHardware()\n\n" "Gets hardware information about device.\n\n" "@return: Hardware information as string.\n" "@rtype: string\n" ; static PyObject * StateMachine_GetHardware(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char buffer[BUFFER_LENGTH]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetHardware(self->s, buffer); END_PHONE_COMM if (!checkError(error, "GetHardware")) return NULL; return Py_BuildValue("s", buffer); } /**********/ /* GetPPM */ /**********/ static char StateMachine_GetPPM__doc__[] = "GetPPM()\n\n" "Gets PPM (Post Programmable Memory) from phone.\n\n" "@return: PPM as string\n" "@rtype: string\n" ; static PyObject * StateMachine_GetPPM(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char buffer[BUFFER_LENGTH]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetPPM(self->s, buffer); END_PHONE_COMM if (!checkError(error, "GetPPM")) return NULL; return Py_BuildValue("s", buffer); } /**************/ /* GetSIMIMSI */ /**************/ static char StateMachine_GetSIMIMSI__doc__[] = "GetSIMIMSI()\n\n" "Gets SIM IMSI from phone.\n\n" "@return: SIM IMSI as string\n" "@rtype: string\n" ; static PyObject * StateMachine_GetSIMIMSI(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char buffer[BUFFER_LENGTH]; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetSIMIMSI(self->s, buffer); END_PHONE_COMM if (!checkError(error, "GetSIMIMSI")) return NULL; return Py_BuildValue("s", buffer); } /***************/ /* GetDateTime */ /***************/ static char StateMachine_GetDateTime__doc__[] = "GetDateTime()\n\n" "Reads date and time from phone.\n\n" "@return: Date and time from phone as datetime.datetime object.\n" "@rtype: datetime.datetime\n" ; static PyObject * StateMachine_GetDateTime(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_DateTime dt; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetDateTime(self->s, &dt); END_PHONE_COMM if (!checkError(error, "GetDateTime")) return NULL; return BuildPythonDateTime(&dt); } /***************/ /* SetDateTime */ /***************/ static char StateMachine_SetDateTime__doc__[] = "SetDateTime(Date)\n\n" "Sets date and time in phone.\n\n" "@param Date: Date to set\n" "@type Date: datetime.datetime\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetDateTime(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; PyObject *pydt; GSM_DateTime dt; static char *kwlist[] = {"Date", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist,&(pydt))) return NULL; if (!BuildGSMDateTime(pydt, &dt)) return NULL; BEGIN_PHONE_COMM error = GSM_SetDateTime(self->s, &dt); END_PHONE_COMM if (!checkError(error, "SetDateTime")) return NULL; Py_RETURN_NONE; } /************/ /* GetAlarm */ /************/ static char StateMachine_GetAlarm__doc__[] = "GetAlarm(Location)\n\n" "Reads alarm set in phone.\n\n" "@param Location: Which alarm to read. Many phone support only one alarm. Default is 1.\n" "@type Location: int\n" "@return: Alarm hash\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetAlarm(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Alarm gsm_alarm; PyObject *dt; Py_UNICODE *s; PyObject *result; static char *kwlist[] = {"Location", NULL}; gsm_alarm.Location = 1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &(gsm_alarm.Location))) return NULL; BEGIN_PHONE_COMM error = GSM_GetAlarm(self->s, &gsm_alarm); END_PHONE_COMM if (!checkError(error, "GetAlarm")) return NULL; s = strGammuToPython(gsm_alarm.Text); if (s == NULL) return NULL; if (gsm_alarm.Repeating) { dt = BuildPythonTime(&(gsm_alarm.DateTime)); if (dt == NULL) { free(s); return NULL; } result = Py_BuildValue("{s:i,s:O,s:i,s:u}", "Location", gsm_alarm.Location, "DateTime", dt, "Repeating", gsm_alarm.Repeating, "Text", s); Py_DECREF(dt); } else { dt = BuildPythonTime(&(gsm_alarm.DateTime)); if (dt == NULL) { free(s); return NULL; } result = Py_BuildValue("{s:i,s:O,s:i,s:u}", "Location", gsm_alarm.Location, "Time", dt, "Repeating", gsm_alarm.Repeating, "Text", s); Py_DECREF(dt); } free(s); return result; } /************/ /* SetAlarm */ /************/ static char StateMachine_SetAlarm__doc__[] = "SetAlarm(DateTime, Location, Repeating, Text)\n\n" "Sets alarm in phone.\n" "@param DateTime: When should alarm happen.\n" "@type DateTime: datetime.datetime\n" "@param Location: Location of alarm to set. Defaults to 1.\n" "@type Location: int\n" "@param Repeating: Whether alarm should be repeating. Defaults to True.\n" "@type Repeating: boolean\n" "@param Text: Text to be displayed on alarm. Defaults to empty.\n" "@type Text: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetAlarm(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Alarm gsm_alarm; PyObject *pydt; PyObject *s = NULL; unsigned char *gs; static char *kwlist[] = {"DateTime", "Location", "Repeating", "Text", NULL}; gsm_alarm.Location = 1; gsm_alarm.Text[0] = 0; gsm_alarm.Repeating = TRUE; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|IIO", kwlist, &pydt, &(gsm_alarm.Location), &(gsm_alarm.Repeating), &(s))) return NULL; if (s != NULL) { gs = StringPythonToGammu(s); if (gs == NULL) return NULL; if (UnicodeLength(gs) > GSM_MAX_CALENDAR_TEXT_LENGTH) { pyg_warning("Alarm text too long, truncating to %d (from %ld)\n", GSM_MAX_CALENDAR_TEXT_LENGTH, (long)UnicodeLength(gs)); } CopyUnicodeString(gsm_alarm.Text, gs); free(gs); } if (gsm_alarm.Repeating) { if (!BuildGSMDateTime(pydt, &(gsm_alarm.DateTime))) return NULL; } else { if (!BuildGSMTime(pydt, &(gsm_alarm.DateTime))) return NULL; } BEGIN_PHONE_COMM error = GSM_SetAlarm(self->s, &gsm_alarm); END_PHONE_COMM if (!checkError(error, "SetAlarm")) return NULL; Py_RETURN_NONE; } /*************/ /* GetLocale */ /*************/ static char StateMachine_GetLocale__doc__[] = "GetLocale()\n\n" "Gets locale information from phone.\n\n" "@return: Hash of locale settings. L{SetLocale} lists them all.\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetLocale(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Locale locale; char s[2]; static char *dtfmts[] = {"", "DDMMYYYY", "MMDDYYYY", "YYYYMMDD"}; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetLocale(self->s, &locale); END_PHONE_COMM if (!checkError(error, "GetLocale")) return NULL; s[0] = locale.DateSeparator; s[1] = 0; return Py_BuildValue("{s:s,s:s,s:i}", "DateSeparator", s, "DateFormat", dtfmts[locale.DateFormat], "AMPMTime", locale.AMPMTime); } /*************/ /* SetLocale */ /*************/ static char StateMachine_SetLocale__doc__[] = "SetLocale(DateSeparator, DateFormat, AMPMTime)\n\n" "Sets locale of phone.\n\n" "@param DateSeparator: Date separator.\n" "@type DateSeparator: string\n" "@param DateFormat: Date format, one of 'DDMMYYYY', 'MMDDYYYY', 'YYYYMMDD'\n" "@type DateFormat: string\n" "@param AMPMTime: Whether to use AM/PM time.\n" "@type AMPMTime: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetLocale(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Locale locale; char *ds; char *df; int ampm; static char *kwlist[] = {"DateSeparator", "DateFormat", "AMPMTime", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "ssi", kwlist, &ds, &df, &m)) return NULL; if (strcmp(df, "DDMMYYYY") == 0) locale.DateFormat = GSM_Date_DDMMYYYY; else if (strcmp(df, "MMDDYYYY") == 0) locale.DateFormat = GSM_Date_MMDDYYYY; else if (strcmp(df, "YYYYMMDD") == 0) locale.DateFormat = GSM_Date_YYYYMMDD; else { PyErr_Format(PyExc_ValueError, "Bad value for DateFormat: '%s'", df); return NULL; } if (strlen(ds) != 1) { PyErr_Format(PyExc_ValueError, "Bad value for DateSeparator: '%s'", ds); return NULL; } locale.DateSeparator = ds[0]; locale.AMPMTime = ampm; BEGIN_PHONE_COMM error = GSM_SetLocale(self->s, &locale); END_PHONE_COMM if (!checkError(error, "SetLocale")) return NULL; Py_RETURN_NONE; } /************/ /* PressKey */ /************/ static char StateMachine_PressKey__doc__[] = "PressKey(Key, Press)\n\n" "Emulates key press.\n\n" "@param Key: What key to press\n" "@type Key: string\n" "@param Press: Whether to emulate press or release.\n" "@type Press: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_PressKey(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int press = 1; char *key; static char *kwlist[] = {"Key", "Press", NULL}; GSM_KeyCode KeyCode[1]; size_t Length; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &key, &press)) return NULL; if (strlen(key) != 1) { PyErr_Format(PyExc_ValueError, "Bad value for Key: '%s'", key); return NULL; } error = MakeKeySequence(key, KeyCode, &Length); if (!checkError(error, "MakeKeySequence")) return NULL; BEGIN_PHONE_COMM error = GSM_PressKey(self->s, KeyCode[0], press); END_PHONE_COMM if (!checkError(error, "PressKey")) return NULL; Py_RETURN_NONE; } /*********/ /* Reset */ /*********/ static char StateMachine_Reset__doc__[] = "Reset(Hard)\n\n" "Performs phone reset.\n\n" "@param Hard: Whether to make hard reset\n" "@type Hard: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_Reset(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int hard = 0; static char *kwlist[] = {"Hard", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &hard)) return NULL; BEGIN_PHONE_COMM error = GSM_Reset(self->s, hard); END_PHONE_COMM if (!checkError(error, "Reset")) return NULL; Py_RETURN_NONE; } /**********************/ /* ResetPhoneSettings */ /**********************/ static char StateMachine_ResetPhoneSettings__doc__[] = "ResetPhoneSettings(Type)\n\n" "Resets phone settings.\n\n" "@param Type: What to reset, one of 'PHONE', 'UIF', 'ALL', 'DEV', 'FACTORY'\n" "@type Type: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_ResetPhoneSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; char *s; static char *kwlist[] = {"Type", NULL}; GSM_ResetSettingsType Type; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return NULL; if (strcmp(s, "PHONE") == 0) Type = GSM_RESET_PHONESETTINGS; else if (strcmp(s, "UIF") == 0) Type = GSM_RESET_USERINTERFACE; else if (strcmp(s, "ALL") == 0) Type = GSM_RESET_USERINTERFACE_PHONESETTINGS; else if (strcmp(s, "DEV") == 0) Type = GSM_RESET_DEVICE; else if (strcmp(s, "FACTORY") == 0) Type = GSM_RESET_FULLFACTORY; else { PyErr_Format(PyExc_ValueError, "Bad value for Type: '%s'", s); return NULL; } BEGIN_PHONE_COMM error = GSM_ResetPhoneSettings(self->s, Type); END_PHONE_COMM if (!checkError(error, "ResetPhoneSettings")) return NULL; Py_RETURN_NONE; } /*********************/ /* EnterSecurityCode */ /*********************/ static char StateMachine_EnterSecurityCode__doc__[] = "EnterSecurityCode(Type, Code, NewPIN)\n\n" "Entres security code.\n" "@param Type: What code to enter, one of 'PIN', 'PUK', 'PIN2', 'PUK2', 'Phone'.\n" "@type Type: string\n" "@param Code: Code value\n" "@type Code: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_EnterSecurityCode(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SecurityCode Code; char *s; char *code; char *newpin = NULL; static char *kwlist[] = {"Type", "Code", "NewPIN", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|s", kwlist, &s, &code, &newpin)) return NULL; if (strcasecmp(s, "PIN") == 0) Code.Type = SEC_Pin; else if (strcasecmp(s, "PUK") == 0) Code.Type = SEC_Puk; else if (strcasecmp(s, "PIN2") == 0) Code.Type = SEC_Pin2; else if (strcasecmp(s, "PUK2") == 0) Code.Type = SEC_Puk2; else if (strcasecmp(s, "Phone") == 0) Code.Type = SEC_Phone; else if (strcasecmp(s, "Network") == 0) Code.Type = SEC_Network; else { PyErr_Format(PyExc_ValueError, "Bad value for Type: '%s'", s); return NULL; } mystrncpy(Code.Code, code, GSM_SECURITY_CODE_LEN); if (newpin == NULL) { Code.NewPIN[0] = 0; } else { mystrncpy(Code.NewPIN, newpin, GSM_SECURITY_CODE_LEN); } BEGIN_PHONE_COMM error = GSM_EnterSecurityCode(self->s, &Code); END_PHONE_COMM if (!checkError(error, "EnterSecurityCode")) return NULL; Py_RETURN_NONE; } /*********************/ /* GetSecurityStatus */ /*********************/ static char StateMachine_GetSecurityStatus__doc__[] = "GetSecurityStatus()\n\n" "Queries whether some security code needs to be entered.\n\n" "@return: String indicating which code needs to be entered or None if none is needed\n" "@rtype: string\n" ; static PyObject * StateMachine_GetSecurityStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SecurityCodeType Status; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetSecurityStatus(self->s, &Status); END_PHONE_COMM if (!checkError(error, "GetSecurityStatus")) return NULL; switch (Status) { case SEC_SecurityCode: return Py_BuildValue("s", "SecurityCode"); case SEC_Pin: return Py_BuildValue("s", "PIN"); case SEC_Pin2: return Py_BuildValue("s", "PIN2"); case SEC_Puk: return Py_BuildValue("s", "PUK"); case SEC_Puk2: return Py_BuildValue("s", "PUK2"); case SEC_Phone: return Py_BuildValue("s", "Phone"); case SEC_Network: return Py_BuildValue("s", "Network"); case SEC_None: Py_RETURN_NONE; } Py_RETURN_NONE; } /********************/ /* GetDisplayStatus */ /********************/ static char StateMachine_GetDisplayStatus__doc__[] = "GetDisplayStatus()\n\n" "Acquired display status.\n" "@return: List of indicators displayed on display\n" "@rtype: list\n" ; static PyObject * StateMachine_GetDisplayStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_DisplayFeatures features; PyObject * list; PyObject * val; int i; char *buffer; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetDisplayStatus(self->s, &features); END_PHONE_COMM if (!checkError(error, "GetDisplayStatus")) return NULL; list = PyList_New(0); for (i = 0; i < features.Number; i++) { buffer = "Unknown"; switch (features.Feature[i]) { case GSM_CallActive: buffer = "CallActive"; break; case GSM_UnreadSMS: buffer = "UnreadSMS"; break; case GSM_VoiceCall: buffer = "VoiceCall"; break; case GSM_FaxCall: buffer = "FaxCall"; break; case GSM_DataCall: buffer = "DataCall"; break; case GSM_KeypadLocked: buffer = "KeypadLocked"; break; case GSM_SMSMemoryFull: buffer = "SMSMemoryFull"; break; } val = Py_BuildValue("s", buffer); if (PyList_Append(list, val) != 0) { Py_DECREF(list); Py_DECREF(val); return NULL; } Py_DECREF(val); } return list; } /***********************/ /* SetAutoNetworkLogin */ /***********************/ static char StateMachine_SetAutoNetworkLogin__doc__[] = "SetAutoNetworkLogin()\n\n" "Enables network auto login.\n\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetAutoNetworkLogin(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_SetAutoNetworkLogin(self->s); END_PHONE_COMM if (!checkError(error, "SetAutoNetworkLogin")) return NULL; Py_RETURN_NONE; } /********************/ /* GetBatteryCharge */ /********************/ static char StateMachine_GetBatteryCharge__doc__[] = "GetBatteryCharge()\n\n" "Gets information about battery charge and phone charging state.\n\n" "@return: Hash containing information about battery state (BatteryPercent and ChargeState)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetBatteryCharge(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_BatteryCharge bat; char *buffer; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetBatteryCharge(self->s, &bat); END_PHONE_COMM if (!checkError(error, "GetBatteryCharge")) return NULL; buffer = "Unknown"; switch (bat.ChargeState) { case GSM_BatteryPowered: buffer = "BatteryPowered"; break; case GSM_BatteryConnected: buffer = "BatteryConnected"; break; case GSM_BatteryCharging: buffer = "BatteryCharging"; break; case GSM_BatteryFull: buffer = "BatteryFull"; break; case GSM_BatteryNotConnected: buffer = "BatteryNotConnected"; break; case GSM_PowerFault: buffer = "PowerFault"; break; } return Py_BuildValue("{s:i,s:s,s:i,s:i,s:i,s:i,s:i,s:i,s:i}", "BatteryPercent", bat.BatteryPercent, "ChargeState", buffer, "BatteryVoltage", bat.BatteryVoltage, "ChargeVoltage", bat.ChargeVoltage, "ChargeCurrent", bat.ChargeCurrent, "PhoneCurrent", bat.PhoneCurrent, "BatteryTemperature", bat.BatteryTemperature, "PhoneTemperature", bat.PhoneTemperature, "BatteryCapacity", bat.BatteryCapacity ); } /********************/ /* GetSignalQuality */ /********************/ static char StateMachine_GetSignalQuality__doc__[] = "GetSignalQuality()\n\n" "Reads signal quality (strength and error rate).\n\n" "@return: Hash containing information about signal state (SignalStrength, SignalPercent and BitErrorRate)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetSignalQuality(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SignalQuality sig; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetSignalQuality(self->s, &sig); END_PHONE_COMM if (!checkError(error, "GetSignalQuality")) return NULL; return Py_BuildValue("{s:i,s:i,s:i}", "SignalStrength", sig.SignalStrength, "SignalPercent", sig.SignalPercent, "BitErrorRate", sig.BitErrorRate); } /******************/ /* GetNetworkInfo */ /******************/ static char StateMachine_GetNetworkInfo__doc__[] = "GetNetworkInfo()\n\n" "Gets network information.\n\n" "@return: Hash with information about network (NetworkName, State, NetworkCode, CID and LAC)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetNetworkInfo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_NetworkInfo netinfo; char *buffer, *packet_state; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetNetworkInfo(self->s, &netinfo); END_PHONE_COMM if (!checkError(error, "GetNetworkInfo")) return NULL; buffer = "Unknown"; switch(netinfo.State) { case GSM_HomeNetwork: buffer = "HomeNetwork"; break; case GSM_RoamingNetwork: buffer = "RoamingNetwork"; break; case GSM_RequestingNetwork: buffer = "RequestingNetwork"; break; case GSM_NoNetwork: buffer = "NoNetwork"; break; case GSM_RegistrationDenied: buffer = "RegistrationDenied"; break; case GSM_NetworkStatusUnknown: buffer = "NetworkStatusUnknown"; break; } packet_state = "Unknown"; switch(netinfo.PacketState) { case GSM_HomeNetwork: packet_state = "HomeNetwork"; break; case GSM_RoamingNetwork: packet_state = "RoamingNetwork"; break; case GSM_RequestingNetwork: packet_state = "RequestingNetwork"; break; case GSM_NoNetwork: packet_state = "NoNetwork"; break; case GSM_RegistrationDenied: packet_state = "RegistrationDenied"; break; case GSM_NetworkStatusUnknown: packet_state = "NetworkStatusUnknown"; break; } return Py_BuildValue("{s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s}", "NetworkName", netinfo.NetworkName, "State", buffer, "PacketState", packet_state, "NetworkCode", netinfo.NetworkCode, "CID", netinfo.CID, "PacketCID", netinfo.PacketCID, "GPRS", netinfo.GPRS == 0 ? "Unknown" : (netinfo.GPRS == GSM_GPRS_Attached ? "Attached" : "Detached"), "PacketLAC", netinfo.PacketLAC, "LAC", netinfo.LAC); } /***************/ /* GetCategory */ /***************/ static char StateMachine_GetCategory__doc__[] = "GetCategory(Type, Location)\n\n" "Reads category from phone.\n\n" "@param Type: Type of category to read, one of 'ToDo', 'Phonebook'\n" "@type Type: string\n" "@param Location: Location of category to read\n" "@type Location: int\n" "@return: Category name as string\n" "@rtype: string\n" ; static PyObject * StateMachine_GetCategory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Category Category; static char *kwlist[] = {"Type", "Location", NULL}; char *s; Py_UNICODE *u; PyObject *o; if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, &s, &(Category.Location))) return NULL; Category.Type = StringToCategoryType(s); if (Category.Type == 0) return NULL; BEGIN_PHONE_COMM error = GSM_GetCategory(self->s, &Category); END_PHONE_COMM if (!checkError(error, "GetCategory")) return NULL; u = strGammuToPython(Category.Name); if (u == NULL) return NULL; o = Py_BuildValue("u", u); free(u); return o; } /***************/ /* AddCategory */ /***************/ static char StateMachine_AddCategory__doc__[] = "AddCategory(Type, Name)\n\n" "Adds category to phone.\n\n" "@param Type: Type of category to read, one of 'ToDo', 'Phonebook'\n" "@type Type: string\n" "@param Name: Category name\n" "@type Name: string\n" "@return: Location of created category\n" "@rtype: int\n" ; static PyObject * StateMachine_AddCategory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Category Category; static char *kwlist[] = {"Type", "Name", NULL}; char *s; PyObject *u; unsigned char *name; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sU", kwlist, &s, &u)) return NULL; Category.Type = StringToCategoryType(s); if (Category.Type == 0) return NULL; name = StringPythonToGammu(u); if (name == NULL) return NULL; if (UnicodeLength(name) > GSM_MAX_CATEGORY_NAME_LENGTH) { pyg_warning("Category name too long, truncating to %d (from %ld)\n", GSM_MAX_CATEGORY_NAME_LENGTH, (long)UnicodeLength(name)); name[2*GSM_MAX_CATEGORY_NAME_LENGTH] = 0; name[2*GSM_MAX_CATEGORY_NAME_LENGTH + 1] = 0; } CopyUnicodeString(Category.Name, name); free(name); BEGIN_PHONE_COMM error = GSM_AddCategory(self->s, &Category); END_PHONE_COMM if (!checkError(error, "AddCategory")) return NULL; return Py_BuildValue("i", Category.Location); } /*********************/ /* GetCategoryStatus */ /*********************/ static char StateMachine_GetCategoryStatus__doc__[] = "GetCategoryStatus(Type)\n\n" "Reads category status (number of used entries) from phone.\n" "@param Type: Type of category to read, one of 'ToDo', 'Phonebook'\n" "@type Type: string\n" "@return: Hash containing information about category status (Used)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetCategoryStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CategoryStatus Status; static char *kwlist[] = {"Type", NULL}; char *s; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return NULL; Status.Type = StringToCategoryType(s); if (Status.Type == 0) return NULL; BEGIN_PHONE_COMM error = GSM_GetCategoryStatus(self->s, &Status); END_PHONE_COMM if (!checkError(error, "GetCategoryStatus")) return NULL; return Py_BuildValue("{s:i}", "Used", Status.Used); } /*******************/ /* GetMemoryStatus */ /*******************/ static char StateMachine_GetMemoryStatus__doc__[] = "GetMemoryStatus(Type)\n\n" "Gets memory (phonebooks or calls) status (eg. number of used andfree entries).\n\n" "@param Type: Memory type, one of 'ME', 'SM', 'ON', 'DC', 'RC', 'MC', 'MT', 'FD', 'VM'\n" "@type Type: string\n" "@return: Hash with information about memory (Used and Free)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetMemoryStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MemoryStatus Status; static char *kwlist[] = {"Type", NULL}; char *s; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return NULL; Status.MemoryType = StringToMemoryType(s); if (Status.MemoryType == 0) return NULL; BEGIN_PHONE_COMM error = GSM_GetMemoryStatus(self->s, &Status); END_PHONE_COMM if (!checkError(error, "GetMemoryStatus")) return NULL; return Py_BuildValue("{s:i,s:i}", "Used", Status.MemoryUsed, "Free", Status.MemoryFree); } /*************/ /* GetMemory */ /*************/ static char StateMachine_GetMemory__doc__[] = "GetMemory(Type, Location)\n\n" "Reads entry from memory (phonebooks or calls). Which entry shouldbe read is defined in entry.\n" "@param Type: Memory type, one of 'ME', 'SM', 'ON', 'DC', 'RC', 'MC', 'MT', 'FD', 'VM'\n" "@type Type: string\n" "@return: Memory entry as hash\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetMemory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MemoryEntry entry; static char *kwlist[] = {"Type", "Location", NULL}; char *s; PyObject *result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, &s, &(entry.Location))) return NULL; entry.MemoryType = StringToMemoryType(s); if (entry.MemoryType == 0) return NULL; BEGIN_PHONE_COMM error = GSM_GetMemory(self->s, &entry); END_PHONE_COMM if (!checkError(error, "GetMemory")) return NULL; result = MemoryEntryToPython(&entry); GSM_FreeMemoryEntry(&entry); return result; } /*****************/ /* GetNextMemory */ /*****************/ static char StateMachine_GetNextMemory__doc__[] = "GetNextMemory(Type, Start, Location)\n\n" "Reads entry from memory (phonebooks or calls). Which entry shouldbe read is defined in entry. This can be easily used for reading all entries.\n\n" "@param Type: Memory type, one of 'ME', 'SM', 'ON', 'DC', 'RC', 'MC', 'MT', 'FD', 'VM'\n" "@type Type: string\n" "@param Start: Whether to start. This can not be used together with Location\n" "@type Start: boolean\n" "@param Location: Last read location. This can not be used together with Start\n" "@type Location: int\n" "@return: Memory entry as hash\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetNextMemory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MemoryEntry entry; static char *kwlist[] = {"Type", "Start", "Location", NULL}; char *s = NULL; int start = FALSE; PyObject *result; entry.Location = -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ii", kwlist, &s, &start, &(entry.Location))) return NULL; if (!start && entry.Location == -1) { PyErr_SetString(PyExc_TypeError, "you have to specify Type and (Start or Location)"); return NULL; } entry.MemoryType = StringToMemoryType(s); if (entry.MemoryType == 0) return NULL; BEGIN_PHONE_COMM error = GSM_GetNextMemory(self->s, &entry, start); END_PHONE_COMM if (!checkError(error, "GetNextMemory")) return NULL; result = MemoryEntryToPython(&entry); GSM_FreeMemoryEntry(&entry); return result; } /*************/ /* SetMemory */ /*************/ static char StateMachine_SetMemory__doc__[] = "SetMemory(Value)\n\n" "Sets memory (phonebooks or calls) entry.\n\n" "@param Value: Memory entry\n" "@type Value: hash\n" "@return: Location of created entry\n" "@rtype: int\n" ; static PyObject * StateMachine_SetMemory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; PyObject *value; GSM_MemoryEntry entry; static char *kwlist[] = {"Value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!MemoryEntryFromPython(value, &entry, 1)) return NULL; BEGIN_PHONE_COMM error = GSM_SetMemory(self->s, &entry); END_PHONE_COMM if (!checkError(error, "SetMemory")) return NULL; return PyLong_FromLong(entry.Location); } /*************/ /* AddMemory */ /*************/ static char StateMachine_AddMemory__doc__[] = "AddMemory(Value)\n\n" "Adds memory (phonebooks or calls) entry.\n\n" "@param Value: Memory entry\n" "@type Value: hash\n" "@return: Location of created entry\n" "@rtype: int\n" ; static PyObject * StateMachine_AddMemory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Error error2; PyObject *value; GSM_MemoryEntry entry; GSM_MemoryEntry tmp; static char *kwlist[] = {"Value", NULL}; int loc; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!MemoryEntryFromPython(value, &entry, 0)) return NULL; BEGIN_PHONE_COMM error = GSM_AddMemory(self->s, &entry); /* Phone does not support adding, let's implement it here */ if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { /* Speed up lookup by starting from last location */ if (self->memory_entry_cache_type == entry.MemoryType) { loc = self->memory_entry_cache; } else { loc = 1; } error2 = ERR_NONE; while (error2 == ERR_NONE) { tmp.MemoryType = entry.MemoryType; tmp.Location = loc; loc++; error2 = GSM_GetMemory(self->s, &tmp); } if (error2 == ERR_EMPTY) { /* Found what wanted, use regullar add */ self->memory_entry_cache = loc; entry.Location = tmp.Location; error = GSM_SetMemory(self->s, &entry); } else if (error2 == ERR_INVALIDLOCATION) { /* Indicate full memory */ error = ERR_FULL; } else { /* Propagate error */ error = error2; } } END_PHONE_COMM if (!checkError(error, "AddMemory")) return NULL; return PyLong_FromLong(entry.Location); } /****************/ /* DeleteMemory */ /****************/ static char StateMachine_DeleteMemory__doc__[] = "DeleteMemory(Type, Location)\n\n" "Deletes memory (phonebooks or calls) entry.\n\n" "@param Type: Memory type, one of 'ME', 'SM', 'ON', 'DC', 'RC', 'MC', 'MT', 'FD', 'VM'\n" "@type Type: string\n" "@param Location: Location of entry to delete\n" "@type Location: int\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteMemory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MemoryEntry entry; static char *kwlist[] = {"Type", "Location", NULL}; char *s; if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", kwlist, &s, &(entry.Location))) return NULL; entry.MemoryType = StringToMemoryType(s); if (entry.MemoryType == 0) return NULL; /* Move hint for adding entries */ if (entry.MemoryType == self->memory_entry_cache_type && entry.Location < self->memory_entry_cache) { self->memory_entry_cache = entry.Location; } BEGIN_PHONE_COMM error = GSM_DeleteMemory(self->s, &entry); END_PHONE_COMM if (!checkError(error, "DeleteMemory")) return NULL; Py_RETURN_NONE; } /*******************/ /* DeleteAllMemory */ /*******************/ static char StateMachine_DeleteAllMemory__doc__[] = "DeleteAllMemory(Type)\n\n" "Deletes all memory (phonebooks or calls) entries of specified type.\n\n" "@param Type: Memory type, one of 'ME', 'SM', 'ON', 'DC', 'RC', 'MC', 'MT', 'FD', 'VM'\n" "@type Type: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteAllMemory(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MemoryType MemoryType; static char *kwlist[] = {"Type", NULL}; char *s; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return NULL; MemoryType = StringToMemoryType(s); if (MemoryType == 0) return NULL; BEGIN_PHONE_COMM error = GSM_DeleteAllMemory(self->s, MemoryType); END_PHONE_COMM if (!checkError(error, "DeleteAllMemory")) return NULL; Py_RETURN_NONE; } /****************/ /* GetSpeedDial */ /****************/ static char StateMachine_GetSpeedDial__doc__[] = "GetSpeedDial(Location)\n\n" "Gets speed dial.\n\n" "@param Location: Location of entry to read\n" "@type Location: int\n" "@return: Hash with speed dial (Location, MemoryLocation, MemoryNumberID, MemoryType)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetSpeedDial(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SpeedDial Speed; static char *kwlist[] = {"Location", NULL}; char *s; PyObject *ret; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &(Speed.Location))) return NULL; BEGIN_PHONE_COMM error = GSM_GetSpeedDial(self->s, &Speed); END_PHONE_COMM if (!checkError(error, "GetSpeedDial")) return NULL; s = MemoryTypeToString(Speed.MemoryType); ret = Py_BuildValue("{s:i,s:i,s:i,s:s}", "Location", Speed.Location, "MemoryLocation", Speed.MemoryLocation, "MemoryNumberID", Speed.MemoryNumberID, "MemoryType", s); free(s); return ret; } /****************/ /* SetSpeedDial */ /****************/ static char StateMachine_SetSpeedDial__doc__[] = "SetSpeedDial(Value)\n\n" "Sets speed dial.\n\n" "@param Value: Speed dial data, see L{GetSpeedDial} for listing.\n" "@type Value: hash\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetSpeedDial(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SpeedDial Speed; static char *kwlist[] = {"Value", NULL}; PyObject *value; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; Speed.Location = GetIntFromDict(value, "Location"); if (Speed.Location == INT_INVALID) return NULL; Speed.MemoryNumberID = GetIntFromDict(value, "MemoryNumberID"); if (Speed.MemoryNumberID == INT_INVALID) return NULL; Speed.MemoryLocation = GetIntFromDict(value, "MemoryLocation"); if (Speed.MemoryLocation == INT_INVALID) return NULL; Speed.MemoryType = GetMemoryTypeFromDict(value, "MemoryType"); if (Speed.MemoryType == MEM_INVALID) return NULL; BEGIN_PHONE_COMM error = GSM_SetSpeedDial(self->s, &Speed); END_PHONE_COMM if (!checkError(error, "SetSpeedDial")) return NULL; Py_RETURN_NONE; } /***********/ /* GetSMSC */ /***********/ static char StateMachine_GetSMSC__doc__[] = "GetSMSC(Location)\n\n" "Gets SMS Service Center number and SMS settings.\n\n" "@param Location: Location of entry to read. Defaults to 1\n" "@type Location: int\n" "@return: Hash with SMSC information\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetSMSC(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSC smsc; static char *kwlist[] = {"Location", NULL}; smsc.Location = 1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &(smsc.Location))) return NULL; BEGIN_PHONE_COMM error = GSM_GetSMSC(self->s, &smsc); END_PHONE_COMM if (!checkError(error, "GetSMSC")) return NULL; return SMSCToPython(&smsc); } /***********/ /* SetSMSC */ /***********/ static char StateMachine_SetSMSC__doc__[] = "SetSMSC(Value)\n\n" "Sets SMS Service Center number and SMS settings.\n\n" "@param Value: SMSC information\n" "@type Value: hash\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetSMSC(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; PyObject *value; GSM_SMSC smsc; static char *kwlist[] = {"Value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!SMSCFromPython(value, &smsc, TRUE)) return NULL; BEGIN_PHONE_COMM error = GSM_SetSMSC(self->s, &smsc); END_PHONE_COMM if (!checkError(error, "SetSMSC")) return NULL; Py_RETURN_NONE; } /****************/ /* GetSMSStatus */ /****************/ static char StateMachine_GetSMSStatus__doc__[] = "GetSMSStatus()\n\n" "Gets information about SMS memory (read/unread/size of memory for both SIM and phone).\n\n" "@return: Hash with information about phone memory (SIMUnRead, SIMUsed, SIMSize, PhoneUnRead, PhoneUsed, PhoneSize and TemplatesUsed)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetSMSStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSMemoryStatus status; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetSMSStatus(self->s, &status); END_PHONE_COMM if (!checkError(error, "GetSMSStatus")) return NULL; return Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i}", "SIMUnRead", status.SIMUnRead, "SIMUsed", status.SIMUsed, "SIMSize", status.SIMSize, "PhoneUnRead", status.PhoneUnRead, "PhoneUsed", status.PhoneUsed, "PhoneSize", status.PhoneSize, "TemplatesUsed", status.TemplatesUsed); } /**********/ /* GetSMS */ /**********/ static char StateMachine_GetSMS__doc__[] = "GetSMS(Folder, Location)\n\n" "Reads SMS message.\n\n" "@param Folder: Folder where to read entry (0 is emulated flat memory)\n" "@type Folder: int\n" "@param Location: Location of entry to read\n" "@type Location: int\n" "@return: Hash with SMS data\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MultiSMSMessage sms; int i; static char *kwlist[] = {"Folder", "Location", NULL}; /* Clear SMS structure */ for (i = 0; i < GSM_MAX_MULTI_SMS; i++) { GSM_SetDefaultSMSData(&sms.SMS[i]); } if (!PyArg_ParseTupleAndKeywords(args, kwds, "II", kwlist, &(sms.SMS[0].Folder), &(sms.SMS[0].Location))) return NULL; sms.Number = 0; BEGIN_PHONE_COMM error = GSM_GetSMS(self->s, &sms); END_PHONE_COMM if (!checkError(error, "GetSMS")) return NULL; return MultiSMSToPython(&sms); } /**************/ /* GetNextSMS */ /**************/ static char StateMachine_GetNextSMS__doc__[] = "GetNextSMS(Folder, Start, Location)\n\n" "Reads next (or first if start set) SMS message. This might befaster for some phones than using L{GetSMS} for each message.\n\n" "@param Folder: Folder where to read entry (0 is emulated flat memory)\n" "@type Folder: int\n" "@param Start: Whether to start. This can not be used together with Location\n" "@type Start: boolean\n" "@param Location: Location last read entry. This can not be used together with Start\n" "@type Location: int\n" "@return: Hash with SMS data\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetNextSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MultiSMSMessage sms; int i; static char *kwlist[] = {"Folder", "Start", "Location", NULL}; int start = FALSE; /* Clear SMS structure */ for (i = 0; i < GSM_MAX_MULTI_SMS; i++) { GSM_SetDefaultSMSData(&sms.SMS[i]); } sms.SMS[0].Location = -1; sms.SMS[0].Folder = -1; sms.Number = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwlist, &(sms.SMS[0].Folder), &start, &(sms.SMS[0].Location))) return NULL; if (!start && sms.SMS[0].Location == -1) { PyErr_SetString(PyExc_TypeError, "you have to specify Folder and (Start or Location)"); return NULL; } BEGIN_PHONE_COMM error = GSM_GetNextSMS(self->s, &sms, start); END_PHONE_COMM if (!checkError(error, "GetNextSMS")) return NULL; return MultiSMSToPython(&sms); } /**********/ /* SetSMS */ /**********/ static char StateMachine_SetSMS__doc__[] = "SetSMS(Value)\n\n" "Sets SMS.\n\n" "@param Value: SMS data\n" "@type Value: hash\n" "@return: Tuple for location and folder.\n" "@rtype: tuple\n" ; static PyObject * StateMachine_SetSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSMessage sms; PyObject *value; static char *kwlist[] = {"Value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!SMSFromPython(value, &sms, 1, 1, 0)) return NULL; BEGIN_PHONE_COMM error = GSM_SetSMS(self->s, &sms); END_PHONE_COMM if (!checkError(error, "SetSMS")) return NULL; return Py_BuildValue("i,i", sms.Location, sms.Folder); } /**********/ /* AddSMS */ /**********/ static char StateMachine_AddSMS__doc__[] = "AddSMS(Value)\n\n" "Adds SMS to specified folder.\n" "@param Value: SMS data\n" "@type Value: hash\n" "@return: Tuple for location and folder.\n" "@rtype: tuple\n" ; static PyObject * StateMachine_AddSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSMessage sms; PyObject *value; static char *kwlist[] = {"Value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!SMSFromPython(value, &sms, 0, 1, 0)) return NULL; BEGIN_PHONE_COMM error = GSM_AddSMS(self->s, &sms); END_PHONE_COMM if (!checkError(error, "AddSMS")) return NULL; return Py_BuildValue("i,i", sms.Location, sms.Folder); } /*************/ /* DeleteSMS */ /*************/ static char StateMachine_DeleteSMS__doc__[] = "DeleteSMS(Folder, Location)\n\n" "Deletes SMS.\n\n" "@param Folder: Folder where to read entry (0 is emulated flat memory)\n" "@type Folder: int\n" "@param Location: Location of entry to delete\n" "@type Location: int\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSMessage sms; static char *kwlist[] = {"Folder", "Location", NULL}; memset(&sms, 0, sizeof(GSM_SMSMessage)); if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &(sms.Folder), &(sms.Location))) return NULL; BEGIN_PHONE_COMM error = GSM_DeleteSMS(self->s, &sms); END_PHONE_COMM if (!checkError(error, "DeleteSMS")) return NULL; Py_RETURN_NONE; } /***********/ /* SendSMS */ /***********/ static char StateMachine_SendSMS__doc__[] = "SendSMS(Value)\n\n" "Sends SMS.\n\n" "@param Value: SMS data\n" "@type Value: hash\n" "@return: Message reference as integer\n" "@rtype: int\n" ; static PyObject * StateMachine_SendSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSMessage sms; PyObject *value; static char *kwlist[] = {"Value", NULL}; int i = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!SMSFromPython(value, &sms, 0, 0, 1)) return NULL; self->SMSStatus = ERR_TIMEOUT; BEGIN_PHONE_COMM error = GSM_SendSMS(self->s, &sms); END_PHONE_COMM if (!checkError(error, "SendSMS")) return NULL; while (self->SMSStatus != ERR_NONE) { i++; BEGIN_PHONE_COMM GSM_ReadDevice(self->s, TRUE); END_PHONE_COMM if (self->SMSStatus == ERR_FULL || self->SMSStatus == ERR_UNKNOWN || i == 100) { if (!checkError(self->SMSStatus, "SendSMS")) { return NULL; } } } return PyLong_FromLong(self->MessageReference); } static char StateMachine_SendSavedSMS__doc__[] = "SendSavedSMS(Folder, Location)\n\n" "Sends SMS saved in phone.\n\n" "@param Folder: Folder where to read entry (0 is emulated flat memory)\n" "@type Folder: int\n" "@param Location: Location of entry to send\n" "@type Location: int\n" "@return: Message reference as integer\n" "@rtype: int\n" ; static PyObject * StateMachine_SendSavedSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int Folder; int Location; static char *kwlist[] = {"Folder", "Location", NULL}; int i = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &Folder, &Location)) return NULL; BEGIN_PHONE_COMM error = GSM_SendSavedSMS(self->s, Folder, Location); END_PHONE_COMM self->SMSStatus = ERR_TIMEOUT; if (!checkError(error, "SendSavedSMS")) return NULL; while (self->SMSStatus != ERR_NONE) { i++; BEGIN_PHONE_COMM GSM_ReadDevice(self->s,TRUE); END_PHONE_COMM if (self->SMSStatus == ERR_FULL || self->SMSStatus == ERR_UNKNOWN || i == 100) { if (!checkError(self->SMSStatus, "SendSavedSMS")) { return NULL; } } } return PyLong_FromLong(self->MessageReference); } /******************/ /* SetIncomingSMS */ /******************/ static char StateMachine_SetIncomingSMS__doc__[] = "SetIncomingSMS(Enable)\n\n" "Enable/disable notification on incoming SMS.\n\n" "@type Enable: boolean\n" "@param Enable: Whether to enable notifications, default is True\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetIncomingSMS(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int enable = TRUE; static char *kwlist[] = {"Enable", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &enable)) return NULL; BEGIN_PHONE_COMM error = GSM_SetIncomingSMS(self->s, enable); END_PHONE_COMM if (!checkError(error, "SetIncomingSMS")) return NULL; Py_RETURN_NONE; } /*****************/ /* SetIncomingCB */ /*****************/ static char StateMachine_SetIncomingCB__doc__[] = "SetIncomingCB(Enable)\n\n" "Gets network information from phone.\n" "@type Enable: boolean\n" "@param Enable: Whether to enable notifications, default is True\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetIncomingCB(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int enable = TRUE; static char *kwlist[] = {"Enable", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &enable)) return NULL; BEGIN_PHONE_COMM error = GSM_SetIncomingCB(self->s, enable); END_PHONE_COMM if (!checkError(error, "SetIncomingCB")) return NULL; Py_RETURN_NONE; } /*******************/ /* SetIncomingCall */ /*******************/ static char StateMachine_SetIncomingCall__doc__[] = "SetIncomingCall(Enable)\n\n" "Activates/deactivates noticing about incoming calls.\n" "@type Enable: boolean\n" "@param Enable: Whether to enable notifications, default is True\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetIncomingCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int enable = TRUE; static char *kwlist[] = {"Enable", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &enable)) return NULL; BEGIN_PHONE_COMM error = GSM_SetIncomingCall(self->s, enable); END_PHONE_COMM if (!checkError(error, "SetIncomingCall")) return NULL; Py_RETURN_NONE; } /*******************/ /* SetIncomingUSSD */ /*******************/ static char StateMachine_SetIncomingUSSD__doc__[] = "SetIncomingUSSD(Enable)\n\n" "Activates/deactivates noticing about incoming USSDs (UnStructured Supplementary Services).\n" "@type Enable: boolean\n" "@param Enable: Whether to enable notifications, default is True\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetIncomingUSSD(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; int enable = TRUE; static char *kwlist[] = {"Enable", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &enable)) return NULL; BEGIN_PHONE_COMM error = GSM_SetIncomingUSSD(self->s, enable); END_PHONE_COMM if (!checkError(error, "SetIncomingUSSD")) return NULL; Py_RETURN_NONE; } /*****************/ /* GetSMSFolders */ /*****************/ static char StateMachine_GetSMSFolders__doc__[] = "GetSMSFolders()\n\n" "Returns SMS folders information.\n\n" "@return: List of SMS folders.\n" "@rtype: list\n" ; static PyObject * StateMachine_GetSMSFolders(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_SMSFolders folders; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetSMSFolders(self->s, &folders); END_PHONE_COMM if (!checkError(error, "GetSMSFolders")) return NULL; return SMSFoldersToPython(&folders); } /****************/ /* AddSMSFolder */ /****************/ static char StateMachine_AddSMSFolder__doc__[] = "AddSMSFolder(Name)\n\n" "Creates SMS folder.\n\n" "@param Name: Name of new folder\n" "@type Name: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_AddSMSFolder(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; PyObject *val; unsigned char *str; static char *kwlist[] = {"Name", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U", kwlist, &val)) return NULL; str = StringPythonToGammu(val); if (str == NULL) return NULL; BEGIN_PHONE_COMM error = GSM_AddSMSFolder(self->s, str); END_PHONE_COMM free(str); if (!checkError(error, "AddSMSFolder")) return NULL; Py_RETURN_NONE; } /*******************/ /* DeleteSMSFolder */ /*******************/ static char StateMachine_DeleteSMSFolder__doc__[] = "DeleteSMSFolder(ID)\n\n" "Deletes SMS folder.\n\n" "@param ID: Index of folder to delete\n" "@type ID: int\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteSMSFolder(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", NULL}; int val; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &val)) return NULL; BEGIN_PHONE_COMM error = GSM_DeleteSMSFolder(self->s, val); END_PHONE_COMM if (!checkError(error, "DeleteSMSFolder")) return NULL; Py_RETURN_NONE; } /*************/ /* DialVoice */ /*************/ static char StateMachine_DialVoice__doc__[] = "DialVoice(Number, ShowNumber)\n\n" "Dials number and starts voice call.\n" "@param Number: Number to dial\n" "@type Number: string\n" "@param ShowNumber: Identifies whether to enable CLIR (None = keep default phone settings). Default is None\n" "@type ShowNumber: boolean or None\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DialVoice(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Number", "ShowNumber", NULL}; char *s; PyObject *o = Py_None; GSM_CallShowNumber ShowNumber = GSM_CALL_DefaultNumberPresence; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwlist, &s, &o)) return NULL; if (o != Py_None) { switch (BoolFromPython(o, "ShowNumber")) { case BOOL_INVALID: return NULL; case TRUE: ShowNumber = GSM_CALL_ShowNumber; break; case FALSE: ShowNumber = GSM_CALL_HideNumber; break; } } BEGIN_PHONE_COMM error = GSM_DialVoice(self->s, s, ShowNumber); END_PHONE_COMM if (!checkError(error, "DialVoice")) return NULL; Py_RETURN_NONE; } /*************/ /* DialService */ /*************/ static char StateMachine_DialService__doc__[] = "DialService(Number)\n\n" "Dials number and starts voice call.\n" "@param Number: Number to dial\n" "@type Number: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DialService(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Number", NULL}; char *s; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return NULL; BEGIN_PHONE_COMM error = GSM_DialService(self->s, s); END_PHONE_COMM if (!checkError(error, "DialService")) return NULL; Py_RETURN_NONE; } /**************/ /* AnswerCall */ /**************/ static char StateMachine_AnswerCall__doc__[] = "AnswerCall(ID, All)\n\n" "Accept current incoming call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@param All: Answer all calls?\n" "@type All: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_AnswerCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", "All", NULL}; int id=0; gboolean all=TRUE; PyObject *o = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &id, &o)) return NULL; if (o != Py_None) { all = BoolFromPython(o, "All"); if (all == BOOL_INVALID) { return NULL; } } BEGIN_PHONE_COMM error = GSM_AnswerCall(self->s, id, all); END_PHONE_COMM if (!checkError(error, "AnswerCall")) return NULL; Py_RETURN_NONE; } /**************/ /* CancelCall */ /**************/ static char StateMachine_CancelCall__doc__[] = "CancelCall(ID, All)\n\n" "Hangups call (either ongoing or incoming).\n" "@param ID: ID of call\n" "@type ID: integer\n" "@param All: Cancel all calls?\n" "@type All: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_CancelCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", "All", NULL}; int id=0; gboolean all=TRUE; PyObject *o = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &id, &o)) return NULL; if (o != Py_None) { all = BoolFromPython(o, "All"); if (all == BOOL_INVALID) { return NULL; } } BEGIN_PHONE_COMM error = GSM_CancelCall(self->s, id, all); END_PHONE_COMM if (!checkError(error, "CancelCall")) return NULL; Py_RETURN_NONE; } /************/ /* HoldCall */ /************/ static char StateMachine_HoldCall__doc__[] = "HoldCall(ID)\n\n" "Holds call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_HoldCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", NULL}; int id; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &id)) return NULL; BEGIN_PHONE_COMM error = GSM_HoldCall(self->s, id); END_PHONE_COMM if (!checkError(error, "HoldCall")) return NULL; Py_RETURN_NONE; } /**************/ /* UnholdCall */ /**************/ static char StateMachine_UnholdCall__doc__[] = "UnholdCall(ID)\n\n" "Unholds call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_UnholdCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", NULL}; int id; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &id)) return NULL; BEGIN_PHONE_COMM error = GSM_UnholdCall(self->s, id); END_PHONE_COMM if (!checkError(error, "UnholdCall")) return NULL; Py_RETURN_NONE; } /******************/ /* ConferenceCall */ /******************/ static char StateMachine_ConferenceCall__doc__[] = "ConferenceCall(ID)\n\n" "Initiates conference call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_ConferenceCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", NULL}; int id; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &id)) return NULL; BEGIN_PHONE_COMM error = GSM_ConferenceCall(self->s, id); END_PHONE_COMM if (!checkError(error, "ConferenceCall")) return NULL; Py_RETURN_NONE; } /*************/ /* SplitCall */ /*************/ static char StateMachine_SplitCall__doc__[] = "SplitCall(ID)\n\n" "Splits call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SplitCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", NULL}; int id; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &id)) return NULL; BEGIN_PHONE_COMM error = GSM_SplitCall(self->s, id); END_PHONE_COMM if (!checkError(error, "SplitCall")) return NULL; Py_RETURN_NONE; } /****************/ /* TransferCall */ /****************/ static char StateMachine_TransferCall__doc__[] = "TransferCall(ID, Next)\n\n" "Transfers call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_TransferCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", "Next", NULL}; int id; gboolean next; PyObject *o = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kwds, "iO", kwlist, &id, &o)) return NULL; next = BoolFromPython(o, "Next"); if (next == BOOL_INVALID) { return NULL; } BEGIN_PHONE_COMM error = GSM_TransferCall(self->s, id, next); END_PHONE_COMM if (!checkError(error, "TransferCall")) return NULL; Py_RETURN_NONE; } /**************/ /* SwitchCall */ /**************/ static char StateMachine_SwitchCall__doc__[] = "SwitchCall(ID, Next)\n\n" "Switches call.\n" "@param ID: ID of call\n" "@type ID: integer\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SwitchCall(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"ID", "Next", NULL}; int id; gboolean next; PyObject *o = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kwds, "iO", kwlist, &id, &o)) return NULL; next = BoolFromPython(o, "Next"); if (next == BOOL_INVALID) { return NULL; } BEGIN_PHONE_COMM error = GSM_SwitchCall(self->s, id, next); END_PHONE_COMM if (!checkError(error, "SwitchCall")) return NULL; Py_RETURN_NONE; } /************/ /* SendDTMF */ /************/ static char StateMachine_SendDTMF__doc__[] = "SendDTMF(Number)\n\n" "Sends DTMF (Dual Tone Multi Frequency) tone.\n" "@param Number: Number to dial\n" "@type Number: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SendDTMF(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Number", NULL}; char *s; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return NULL; BEGIN_PHONE_COMM error = GSM_SendDTMF(self->s, s); END_PHONE_COMM if (!checkError(error, "SendDTMF")) return NULL; Py_RETURN_NONE; } /*****************/ /* GetCallDivert */ /*****************/ static char StateMachine_GetCallDivert__doc__[] = "Gets call diverts." ; static PyObject * StateMachine_GetCallDivert(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_MultiCallDivert result; GSM_CallDivert request; static char *kwlist[] = {"Divert", "Type", NULL}; char *cond = NULL, *type = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist, &cond, &type)) return NULL; if (type == NULL) { request.CallType = GSM_DIVERT_AllCalls; } else { request.CallType = DivertCallTypeFromString(type); if (request.CallType == 0) { return NULL; } } if (cond == NULL) { request.DivertType = GSM_DIVERT_AllTypes; } else { request.DivertType = DivertTypeFromString(cond); if (request.DivertType == 0) { return NULL; } } BEGIN_PHONE_COMM error = GSM_GetCallDivert(self->s, &request, &result); END_PHONE_COMM if (!checkError(error, "GetCallDivert")) return NULL; return CallDivertsToPython(&result); } /*****************/ /* SetCallDivert */ /*****************/ static char StateMachine_SetCallDivert__doc__[] = "Sets call diverts." ; static PyObject * StateMachine_SetCallDivert(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CallDivert divert; static char *kwlist[] = {"Divert", "Type", "Number", "Timeout", NULL}; char *cond, *type, *number; Py_ssize_t number_len; divert.Timeout = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sss#|i", kwlist, &cond, &type, &number, &number_len, &(divert.Timeout))) return NULL; divert.CallType = DivertCallTypeFromString(type); if (divert.CallType == 0) { return NULL; } divert.DivertType = DivertTypeFromString(cond); if (divert.DivertType == 0) { return NULL; } EncodeUnicode(divert.Number, number, number_len); BEGIN_PHONE_COMM error = GSM_SetCallDivert(self->s, &divert); END_PHONE_COMM if (!checkError(error, "SetCallDivert")) return NULL; Py_RETURN_NONE; } /********************/ /* CancelAllDiverts */ /********************/ static char StateMachine_CancelAllDiverts__doc__[] = "Cancels all diverts." ; static PyObject * StateMachine_CancelAllDiverts(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_CancelAllDiverts(self->s); END_PHONE_COMM if (!checkError(error, "CancelAllDiverts")) return NULL; Py_RETURN_NONE; } #if 0 /***************/ /* GetRingtone */ /***************/ static char StateMachine_GetRingtone__doc__[] = "Gets ringtone from phone." ; static PyObject * StateMachine_GetRingtone(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetRingtone(self->s); END_PHONE_COMM if (!checkError(error, "GetRingtone")) return NULL; Py_RETURN_NONE; } /***************/ /* SetRingtone */ /***************/ static char StateMachine_SetRingtone__doc__[] = "Sets ringtone in phone." ; static PyObject * StateMachine_SetRingtone(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetRingtone(self->s); END_PHONE_COMM if (!checkError(error, "SetRingtone")) return NULL; Py_RETURN_NONE; } /********************/ /* GetRingtonesInfo */ /********************/ static char StateMachine_GetRingtonesInfo__doc__[] = "Acquires ringtone informaiton." ; static PyObject * StateMachine_GetRingtonesInfo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetRingtonesInfo(self->s); END_PHONE_COMM if (!checkError(error, "GetRingtonesInfo")) return NULL; Py_RETURN_NONE; } /***********************/ /* DeleteUserRingtones */ /***********************/ static char StateMachine_DeleteUserRingtones__doc__[] = "Deletes user defined ringtones from phone." ; static PyObject * StateMachine_DeleteUserRingtones(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_DeleteUserRingtones(self->s); END_PHONE_COMM if (!checkError(error, "DeleteUserRingtones")) return NULL; Py_RETURN_NONE; } /************/ /* PlayTone */ /************/ static char StateMachine_PlayTone__doc__[] = "Plays tone." ; static PyObject * StateMachine_PlayTone(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_PlayTone(self->s); END_PHONE_COMM if (!checkError(error, "PlayTone")) return NULL; Py_RETURN_NONE; } /******************/ /* GetWAPBookmark */ /******************/ static char StateMachine_GetWAPBookmark__doc__[] = "Reads WAP bookmark." ; static PyObject * StateMachine_GetWAPBookmark(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetWAPBookmark(self->s); END_PHONE_COMM if (!checkError(error, "GetWAPBookmark")) return NULL; Py_RETURN_NONE; } /******************/ /* SetWAPBookmark */ /******************/ static char StateMachine_SetWAPBookmark__doc__[] = "Sets WAP bookmark." ; static PyObject * StateMachine_SetWAPBookmark(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetWAPBookmark(self->s); END_PHONE_COMM if (!checkError(error, "SetWAPBookmark")) return NULL; Py_RETURN_NONE; } /*********************/ /* DeleteWAPBookmark */ /*********************/ static char StateMachine_DeleteWAPBookmark__doc__[] = "Deletes WAP bookmark." ; static PyObject * StateMachine_DeleteWAPBookmark(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_DeleteWAPBookmark(self->s); END_PHONE_COMM if (!checkError(error, "DeleteWAPBookmark")) return NULL; Py_RETURN_NONE; } /******************/ /* GetWAPSettings */ /******************/ static char StateMachine_GetWAPSettings__doc__[] = "Acquires WAP settings." ; static PyObject * StateMachine_GetWAPSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetWAPSettings(self->s); END_PHONE_COMM if (!checkError(error, "GetWAPSettings")) return NULL; Py_RETURN_NONE; } /******************/ /* SetWAPSettings */ /******************/ static char StateMachine_SetWAPSettings__doc__[] = "Changes WAP settings." ; static PyObject * StateMachine_SetWAPSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetWAPSettings(self->s); END_PHONE_COMM if (!checkError(error, "SetWAPSettings")) return NULL; Py_RETURN_NONE; } /******************/ /* GetMMSSettings */ /******************/ static char StateMachine_GetMMSSettings__doc__[] = "Acquires MMS settings." ; static PyObject * StateMachine_GetMMSSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetMMSSettings(self->s); END_PHONE_COMM if (!checkError(error, "GetMMSSettings")) return NULL; Py_RETURN_NONE; } /******************/ /* SetMMSSettings */ /******************/ static char StateMachine_SetMMSSettings__doc__[] = "Changes MMS settings." ; static PyObject * StateMachine_SetMMSSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetMMSSettings(self->s); END_PHONE_COMM if (!checkError(error, "SetMMSSettings")) return NULL; Py_RETURN_NONE; } /*************/ /* GetBitmap */ /*************/ static char StateMachine_GetBitmap__doc__[] = "Gets bitmap." ; static PyObject * StateMachine_GetBitmap(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetBitmap(self->s); END_PHONE_COMM if (!checkError(error, "GetBitmap")) return NULL; Py_RETURN_NONE; } /*************/ /* SetBitmap */ /*************/ static char StateMachine_SetBitmap__doc__[] = "Sets bitmap." ; static PyObject * StateMachine_SetBitmap(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetBitmap(self->s); END_PHONE_COMM if (!checkError(error, "SetBitmap")) return NULL; Py_RETURN_NONE; } #endif /*****************/ /* GetToDoStatus */ /*****************/ static char StateMachine_GetToDoStatus__doc__[] = "GetToDoStatus()\n\n" "Gets status of ToDos (count of used entries).\n\n" "@return: Hash of status (Used)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetToDoStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_ToDoStatus status; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetToDoStatus(self->s, &status); END_PHONE_COMM if (!checkError(error, "GetToDoStatus")) return NULL; return Py_BuildValue("{s:i,s:i}", "Used", status.Used, "Free", status.Free); } /***********/ /* GetToDo */ /***********/ static char StateMachine_GetToDo__doc__[] = "GetToDo(Location)\n\n" "Reads ToDo from phone.\n" "@param Location: Location of entry to read\n" "@type Location: int\n" "@return: Hash with ToDo values\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetToDo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_ToDoEntry todo; static char *kwlist[] = {"Location", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &(todo.Location))) return NULL; BEGIN_PHONE_COMM error = GSM_GetToDo(self->s, &todo); END_PHONE_COMM if (!checkError(error, "GetToDo")) return NULL; return TodoToPython(&todo); } /***************/ /* GetNextToDo */ /***************/ static char StateMachine_GetNextToDo__doc__[] = "GetNextToDo(Start, Location)\n\n" "Reads ToDo from phone.\n\n" "@param Start: Whether to start. This can not be used together with Location\n" "@type Start: boolean\n" "@param Location: Last read location. This can not be used together with Start\n" "@type Location: int\n" "@return: Hash with ToDo values\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetNextToDo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Start", "Location", NULL}; GSM_ToDoEntry todo; int start = FALSE; todo.Location = -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &start, &(todo.Location))) return NULL; if (!start && todo.Location == -1) { PyErr_SetString(PyExc_TypeError, "you have to specify Start or Location"); return NULL; } BEGIN_PHONE_COMM error = GSM_GetNextToDo(self->s, &todo, start); END_PHONE_COMM if (!checkError(error, "GetNextToDo")) return NULL; return TodoToPython(&todo); } /***********/ /* SetToDo */ /***********/ static char StateMachine_SetToDo__doc__[] = "SetToDo(Value)\n\n" "Sets ToDo in phone.\n\n" "@param Value: ToDo data\n" "@type Value: hash\n" "@return: Location of created entry\n" "@rtype: int\n" ; static PyObject * StateMachine_SetToDo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_ToDoEntry entry; PyObject *value; static char *kwlist[] = {"Value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!TodoFromPython(value, &entry, 1)) return NULL; BEGIN_PHONE_COMM error = GSM_SetToDo(self->s, &entry); END_PHONE_COMM if (!checkError(error, "SetToDo")) return NULL; return PyLong_FromLong(entry.Location); } /***********/ /* AddToDo */ /***********/ static char StateMachine_AddToDo__doc__[] = "AddToDo(Value)\n\n" "Adds ToDo in phone.\n\n" "@param Value: ToDo data\n" "@type Value: hash\n" "@return: Location of created entry\n" "@rtype: int\n" ; static PyObject * StateMachine_AddToDo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Error error2; GSM_ToDoEntry entry; GSM_ToDoEntry tmp; PyObject *value; static char *kwlist[] = {"Value", NULL}; int loc; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!TodoFromPython(value, &entry, 0)) return NULL; BEGIN_PHONE_COMM error = GSM_AddToDo(self->s, &entry); /* Phone does not support adding, let's implement it here */ if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { /* Speed up lookup by starting from last location */ loc = self->todo_entry_cache; error2 = ERR_NONE; while (error2 == ERR_NONE) { tmp.Location = loc; loc++; error2 = GSM_GetToDo(self->s, &tmp); } if (error2 == ERR_EMPTY) { /* Found what wanted, use regullar add */ self->todo_entry_cache = loc; entry.Location = tmp.Location; error = GSM_SetToDo(self->s, &entry); } else if (error2 == ERR_INVALIDLOCATION) { /* Indicate full memory */ error = ERR_FULL; } else { /* Propagate error */ error = error2; } } END_PHONE_COMM if (!checkError(error, "AddToDo")) return NULL; return PyLong_FromLong(entry.Location); } /**************/ /* DeleteToDo */ /**************/ static char StateMachine_DeleteToDo__doc__[] = "DeleteToDo(Location)\n\n" "Deletes ToDo entry in phone.\n" "@param Location: Location of entry to delete\n" "@type Location: int\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteToDo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_ToDoEntry entry; static char *kwlist[] = {"Location", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &(entry.Location))) return NULL; /* Move hint for adding entries */ self->todo_entry_cache = entry.Location; BEGIN_PHONE_COMM error = GSM_DeleteToDo(self->s, &entry); END_PHONE_COMM if (!checkError(error, "DeleteToDo")) return NULL; Py_RETURN_NONE; } /*****************/ /* DeleteAllToDo */ /*****************/ static char StateMachine_DeleteAllToDo__doc__[] = "DeleteAllToDo()\n\n" "Deletes all todo entries in phone.\n\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteAllToDo(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_DeleteAllToDo(self->s); END_PHONE_COMM if (!checkError(error, "DeleteAllToDo")) return NULL; Py_RETURN_NONE; } /*********************/ /* GetCalendarStatus */ /*********************/ static char StateMachine_GetCalendarStatus__doc__[] = "GetCalendarStatus()\n\n" "Retrieves calendar status (number of used entries).\n\n" "@return: Hash with calendar status (Used)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetCalendarStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CalendarStatus status; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetCalendarStatus(self->s, &status); END_PHONE_COMM if (!checkError(error, "GetCalendarStatus")) return NULL; return Py_BuildValue("{s:i,s:i}", "Used", status.Used, "Free", status.Free); } /***************/ /* GetCalendar */ /***************/ static char StateMachine_GetCalendar__doc__[] = "GetCalendar(Location)\n\n" "Retrieves calendar entry.\n\n" "@param Location: Calendar entry to read\n" "@type Location: int\n" "@return: Hash with calendar values\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetCalendar(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CalendarEntry entry; static char *kwlist[] = {"Location", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &(entry.Location))) return NULL; BEGIN_PHONE_COMM error = GSM_GetCalendar(self->s, &entry); END_PHONE_COMM if (!checkError(error, "GetCalendar")) return NULL; return CalendarToPython(&entry); } /*******************/ /* GetNextCalendar */ /*******************/ static char StateMachine_GetNextCalendar__doc__[] = "GetNextCalendar(Start, Location)\n\n" "Retrieves calendar entry. This is useful for continuous reading of all calendar entries.\n\n" "@param Start: Whether to start. This can not be used together with Location\n" "@type Start: boolean\n" "@param Location: Last read location. This can not be used together with Start\n" "@type Location: int\n" "@return: Hash with calendar values\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetNextCalendar(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CalendarEntry entry; int start = FALSE; static char *kwlist[] = {"Start", "Location", NULL}; entry.Location = -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &start, &(entry.Location))) return NULL; if (!start && entry.Location == -1) { PyErr_SetString(PyExc_TypeError, "you have to specify Start or Location"); return NULL; } BEGIN_PHONE_COMM error = GSM_GetNextCalendar(self->s, &entry, start); END_PHONE_COMM if (!checkError(error, "GetNextCalendar")) return NULL; return CalendarToPython(&entry); } /***************/ /* SetCalendar */ /***************/ static char StateMachine_SetCalendar__doc__[] = "SetCalendar(Value)\n\n" "Sets calendar entry\n\n" "@param Value: Calendar entry data\n" "@type Value: hash\n" "@return: Location of set entry\n" "@rtype: int\n" ; static PyObject * StateMachine_SetCalendar(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CalendarEntry entry; PyObject *value; static char *kwlist[] = {"Value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!CalendarFromPython(value, &entry, 1)) return NULL; BEGIN_PHONE_COMM error = GSM_SetCalendar(self->s, &entry); END_PHONE_COMM if (!checkError(error, "SetCalendar")) return NULL; return PyLong_FromLong(entry.Location); } /***************/ /* AddCalendar */ /***************/ static char StateMachine_AddCalendar__doc__[] = "AddCalendar(Value)\n\n" "Adds calendar entry.\n\n" "@param Value: Calendar entry data\n" "@type Value: hash\n" "@return: Location of newly created entry\n" "@rtype: int\n" ; static PyObject * StateMachine_AddCalendar(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_Error error2; GSM_CalendarEntry entry; GSM_CalendarEntry tmp; PyObject *value; static char *kwlist[] = {"Value", NULL}; int loc; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!CalendarFromPython(value, &entry, 0)) return NULL; BEGIN_PHONE_COMM error = GSM_AddCalendar(self->s, &entry); /* Phone does not support adding, let's implement it here */ if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { /* Speed up lookup by starting from last location */ loc = self->calendar_entry_cache; error2 = ERR_NONE; while (error2 == ERR_NONE) { tmp.Location = loc; loc++; error2 = GSM_GetCalendar(self->s, &tmp); } if (error2 == ERR_EMPTY) { /* Found what wanted, use regullar add */ self->calendar_entry_cache = loc; entry.Location = tmp.Location; error = GSM_SetCalendar(self->s, &entry); } else if (error2 == ERR_INVALIDLOCATION) { /* Indicate full memory */ error = ERR_FULL; } else { /* Propagate error */ error = error2; } } END_PHONE_COMM if (!checkError(error, "AddCalendar")) return NULL; return PyLong_FromLong(entry.Location); } /******************/ /* DeleteCalendar */ /******************/ static char StateMachine_DeleteCalendar__doc__[] = "DeleteCalendar(Location)\n\n" "Deletes calendar entry.\n\n" "@param Location: Calendar entry to delete\n" "@type Location: int\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteCalendar(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_CalendarEntry entry; static char *kwlist[] = {"Location", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &(entry.Location))) return NULL; /* Move hint for adding entries */ self->calendar_entry_cache = entry.Location; BEGIN_PHONE_COMM error = GSM_DeleteCalendar(self->s, &entry); END_PHONE_COMM if (!checkError(error, "DeleteCalendar")) return NULL; Py_RETURN_NONE; } /*********************/ /* DeleteAllCalendar */ /*********************/ static char StateMachine_DeleteAllCalendar__doc__[] = "DeleteAllCalendar()\n\n" "Deletes all calendar entries.\n\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteAllCalendar(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_DeleteAllCalendar(self->s); END_PHONE_COMM if (!checkError(error, "DeleteAllCalendar")) return NULL; Py_RETURN_NONE; } #if 0 /***********************/ /* GetCalendarSettings */ /***********************/ static char StateMachine_GetCalendarSettings__doc__[] = "Reads calendar settings." ; static PyObject * StateMachine_GetCalendarSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetCalendarSettings(self->s); END_PHONE_COMM if (!checkError(error, "GetCalendarSettings")) return NULL; Py_RETURN_NONE; } /***********************/ /* SetCalendarSettings */ /***********************/ static char StateMachine_SetCalendarSettings__doc__[] = "Sets calendar settings." ; static PyObject * StateMachine_SetCalendarSettings(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetCalendarSettings(self->s); END_PHONE_COMM if (!checkError(error, "SetCalendarSettings")) return NULL; Py_RETURN_NONE; } /***********/ /* GetNote */ /***********/ static char StateMachine_GetNote__doc__[] = "Gets note." ; static PyObject * StateMachine_GetNote(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetNote(self->s); END_PHONE_COMM if (!checkError(error, "GetNote")) return NULL; Py_RETURN_NONE; } /**************/ /* GetProfile */ /**************/ static char StateMachine_GetProfile__doc__[] = "Reads profile." ; static PyObject * StateMachine_GetProfile(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetProfile(self->s); END_PHONE_COMM if (!checkError(error, "GetProfile")) return NULL; Py_RETURN_NONE; } /**************/ /* SetProfile */ /**************/ static char StateMachine_SetProfile__doc__[] = "Updates profile." ; static PyObject * StateMachine_SetProfile(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetProfile(self->s); END_PHONE_COMM if (!checkError(error, "SetProfile")) return NULL; Py_RETURN_NONE; } /****************/ /* GetFMStation */ /****************/ static char StateMachine_GetFMStation__doc__[] = "Reads FM station." ; static PyObject * StateMachine_GetFMStation(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetFMStation(self->s); END_PHONE_COMM if (!checkError(error, "GetFMStation")) return NULL; Py_RETURN_NONE; } /****************/ /* SetFMStation */ /****************/ static char StateMachine_SetFMStation__doc__[] = "Sets FM station." ; static PyObject * StateMachine_SetFMStation(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetFMStation(self->s); END_PHONE_COMM if (!checkError(error, "SetFMStation")) return NULL; Py_RETURN_NONE; } /*******************/ /* ClearFMStations */ /*******************/ static char StateMachine_ClearFMStations__doc__[] = "Clears defined FM stations." ; static PyObject * StateMachine_ClearFMStations(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_ClearFMStations(self->s); END_PHONE_COMM if (!checkError(error, "ClearFMStations")) return NULL; Py_RETURN_NONE; } #endif /*********************/ /* GetNextFileFolder */ /*********************/ static char StateMachine_GetNextFileFolder__doc__[] = "GetNextFileFolder(Start)\n\n" "Gets next filename from filesystem.\n\n" "@param Start: Whether we're starting listing. Defaults to False.\n" "@type Start: boolean\n" "@return: File data as hash\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetNextFileFolder(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Start", NULL}; int start = FALSE; GSM_File File; memset(&File, 0, sizeof(File)); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &start)) return NULL; BEGIN_PHONE_COMM error = GSM_GetNextFileFolder(self->s, &File, start); END_PHONE_COMM if (!checkError(error, "GetNextFileFolder")) return NULL; return FileToPython(&File); } /*********************/ /* GetFolderListing */ /*********************/ static char StateMachine_GetFolderListing__doc__[] = "GetFolderListing(Folder, Start)\n\n" "Gets next filename from filesystem folder.\n\n" "@param Folder: Folder to list\n" "@type Folder: string\n" "@param Start: Whether we're starting listing. Defaults to False.\n" "@type Start: boolean\n" "@return: File data as hash\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetFolderListing(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Folder", "Start", NULL}; PyObject *folder_p; unsigned char *folder_g; int start = FALSE; GSM_File File; memset(&File, 0, sizeof(File)); if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|i", kwlist, &folder_p, &start)) return NULL; folder_g = StringPythonToGammu(folder_p); CopyUnicodeString(File.ID_FullName, folder_g); free(folder_g); File.Folder = TRUE; BEGIN_PHONE_COMM error = GSM_GetFolderListing(self->s, &File, start); END_PHONE_COMM if (!checkError(error, "GetFolderListing")) return NULL; return FileToPython(&File); } /*********************/ /* GetNextRootFolder */ /*********************/ static char StateMachine_GetNextRootFolder__doc__[] = "GetNextRootFolder(Folder)\n\n" "Gets next root folder from filesystem. Start with empty folder name.\n\n" "@param Folder: Previous read fodlder. Start with empty folder name.\n" "@type Folder: string\n" "@return: Structure with folder information\n" ; static PyObject * StateMachine_GetNextRootFolder(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Folder", NULL}; PyObject *folder_p; unsigned char *folder_g; GSM_File File; memset(&File, 0, sizeof(File)); if (!PyArg_ParseTupleAndKeywords(args, kwds, "U", kwlist, &folder_p)) return NULL; folder_g = StringPythonToGammu(folder_p); CopyUnicodeString(File.ID_FullName, folder_g); free(folder_g); File.Folder = TRUE; BEGIN_PHONE_COMM error = GSM_GetNextRootFolder(self->s, &File); END_PHONE_COMM if (!checkError(error, "GetNextRootFolder")) return NULL; return FileToPython(&File); } /*********************/ /* SetFileAttributes */ /*********************/ static char StateMachine_SetFileAttributes__doc__[] = "SetFileAttributes(Filename, ReadOnly, Protected, System, Hidden)\n\n" "Sets file attributes.\n\n" "@param Filename: File to modify\n" "@type Filename: string\n" "@param ReadOnly: Whether file is read only. Default to False.\n" "@type ReadOnly: boolean\n" "@param Protected: Whether file is protected. Default to False.\n" "@type Protected: boolean\n" "@param System: Whether file is system. Default to False.\n" "@type System: boolean\n" "@param Hidden: Whether file is hidden. Default to False.\n" "@type Hidden: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetFileAttributes(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"Folder", "ReadOnly", "Protected", "System", "Hidden", NULL}; PyObject *folder_p; unsigned char *folder_g; int readonly_attr = 0, protected_attr = 0, system_attr = 0, hidden_attr = 0; GSM_File File; memset(&File, 0, sizeof(File)); File.ReadOnly = FALSE; File.Protected = FALSE; File.System = FALSE; File.Hidden = FALSE; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|iiii", kwlist, &folder_p, &readonly_attr, &protected_attr, &system_attr, &hidden_attr)) return NULL; if (readonly_attr > 0) File.ReadOnly = TRUE; if (protected_attr > 0) File.Protected = TRUE; if (system_attr > 0) File.System = TRUE; if (hidden_attr > 0) File.Hidden = TRUE; folder_g = StringPythonToGammu(folder_p); CopyUnicodeString(File.ID_FullName, folder_g); free(folder_g); BEGIN_PHONE_COMM error = GSM_SetFileAttributes(self->s, &File); END_PHONE_COMM if (!checkError(error, "SetFileAttributes")) return NULL; Py_RETURN_NONE; } /***************/ /* GetFilePart */ /***************/ static char StateMachine_GetFilePart__doc__[] = "GetFilePart(File)\n\n" "Gets file part from filesystem.\n\n" "@param File: File data\n" "@type File: hash\n" "@return: File data for subsequent calls (Finished indicates transfer has been completed)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetFilePart(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"File", NULL}; PyObject *value, *result; GSM_File File; int handle; size_t size; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!FileFromPython(value, &File, FALSE)) return NULL; handle = GetIntFromDict(value, "Handle"); if (handle == INT_INVALID) { handle = 0; PyErr_Clear(); } size = GetIntFromDict(value, "Size"); if (size == INT_INVALID) { size = 0; PyErr_Clear(); } BEGIN_PHONE_COMM error = GSM_GetFilePart(self->s, &File, &handle, &size); END_PHONE_COMM // We can not throw exception here, we need to return rest of data if (error != ERR_EMPTY) { if (!checkError(error, "GetFilePart")) return NULL; } result = FileToPython(&File); free(File.Buffer); File.Buffer = NULL; if (result == NULL) return NULL; value = PyLong_FromLong(size); if (value == NULL) { Py_DECREF(result); return NULL; } PyDict_SetItemString(result, "Size", value); Py_DECREF(value); value = PyLong_FromLong(handle); if (value == NULL) { Py_DECREF(result); return NULL; } PyDict_SetItemString(result, "Handle", value); Py_DECREF(value); PyDict_SetItemString(result, "Finished", (error == ERR_EMPTY) ? Py_True : Py_False); return result; } /***************/ /* AddFilePart */ /***************/ static char StateMachine_AddFilePart__doc__[] = "AddFilePart(File)\n\n" "Adds file part to filesystem.\n\n" "@param File: File data\n" "@type File: hash\n" "@return: File data for subsequent calls (Finished indicates transfer has been completed)\n" "@rtype: hash\n" ; static PyObject * StateMachine_AddFilePart(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"File", NULL}; PyObject *value, *result; GSM_File File; int handle; size_t pos; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!FileFromPython(value, &File, TRUE)) return NULL; handle = GetIntFromDict(value, "Handle"); if (handle == INT_INVALID) { handle = 0; PyErr_Clear(); } pos = GetIntFromDict(value, "Pos"); if (pos == INT_INVALID) { pos = 0; PyErr_Clear(); } BEGIN_PHONE_COMM error = GSM_AddFilePart(self->s, &File, &pos, &handle); END_PHONE_COMM // Do not throw exception here to be compatible with GetFilePart if (error != ERR_EMPTY) { if (!checkError(error, "AddFilePart")) return NULL; } result = FileToPython(&File); free(File.Buffer); File.Buffer = NULL; if (result == NULL) return NULL; value = PyLong_FromLong(pos); if (value == NULL) { Py_DECREF(result); return NULL; } PyDict_SetItemString(result, "Pos", value); Py_DECREF(value); value = PyLong_FromLong(handle); if (value == NULL) { Py_DECREF(result); return NULL; } PyDict_SetItemString(result, "Handle", value); Py_DECREF(value); PyDict_SetItemString(result, "Finished", (error == ERR_EMPTY) ? Py_True : Py_False); return result; } /****************/ /* SendFilePart */ /****************/ static char StateMachine_SendFilePart__doc__[] = "SendFilePart(File)\n\n" "Sends file part to phone.\n\n" "@param File: File data\n" "@type File: hash\n" "@return: File data for subsequent calls (Finished indicates transfer has been completed)\n" "@rtype: hash\n" ; static PyObject * StateMachine_SendFilePart(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"File", NULL}; PyObject *value, *result; GSM_File File; int handle; size_t pos; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!FileFromPython(value, &File, TRUE)) return NULL; handle = GetIntFromDict(value, "Handle"); if (handle == INT_INVALID) { handle = 0; PyErr_Clear(); } pos = GetIntFromDict(value, "Pos"); if (pos == INT_INVALID) { pos = 0; PyErr_Clear(); } BEGIN_PHONE_COMM error = GSM_SendFilePart(self->s, &File, &pos, &handle); END_PHONE_COMM // Do not throw exception here to be compatible with GetFilePart if (error != ERR_EMPTY) { if (!checkError(error, "SendFilePart")) return NULL; } result = FileToPython(&File); free(File.Buffer); File.Buffer = NULL; if (result == NULL) return NULL; value = PyLong_FromLong(pos); if (value == NULL) { Py_DECREF(result); return NULL; } PyDict_SetItemString(result, "Pos", value); Py_DECREF(value); value = PyLong_FromLong(handle); if (value == NULL) { Py_DECREF(result); return NULL; } PyDict_SetItemString(result, "Handle", value); Py_DECREF(value); PyDict_SetItemString(result, "Finished", (error == ERR_EMPTY) ? Py_True : Py_False); return result; } /***********************/ /* GetFileSystemStatus */ /***********************/ static char StateMachine_GetFileSystemStatus__doc__[] = "GetFileSystemStatus()\n\n" "Acquires filesystem status.\n\n" "@return: Hash containing filesystem status (Used and Free)\n" "@rtype: hash\n" ; static PyObject * StateMachine_GetFileSystemStatus(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; GSM_FileSystemStatus Status; if (!PyArg_ParseTuple(args, "")) return NULL; BEGIN_PHONE_COMM error = GSM_GetFileSystemStatus(self->s, &Status); END_PHONE_COMM if (!checkError(error, "GetFileSystemStatus")) return NULL; return Py_BuildValue("{s:i,s:i,s:i,s:i,s:i}", "Used", Status.Used, "Free", Status.Free, "UsedImages", Status.UsedImages, "UsedThemes", Status.UsedThemes, "UsedSounds", Status.UsedSounds); } /**************/ /* DeleteFile */ /**************/ static char StateMachine_DeleteFile__doc__[] = "DeleteFile(FileID)\n\n" "Deletes file from filesystem.\n\n" "@param FileID: File to delete\n" "@type FileID: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteFile(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"File", NULL}; PyObject *folder_p; unsigned char *folder_g; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U", kwlist, &folder_p)) return NULL; folder_g = StringPythonToGammu(folder_p); BEGIN_PHONE_COMM error = GSM_DeleteFile(self->s, folder_g); END_PHONE_COMM free(folder_g); if (!checkError(error, "DeleteFile")) return NULL; Py_RETURN_NONE; } /*************/ /* AddFolder */ /*************/ static char StateMachine_AddFolder__doc__[] = "AddFolder(ParentFolderID, Name)\n\n" "Adds folder to filesystem.\n\n" "@param ParentFolderID: Folder where to create subfolder\n" "@type ParentFolderID: string\n" "@param Name: New folder name\n" "@type Name: string\n" "@return: New folder ID.\n" "@rtype: string\n" ; static PyObject * StateMachine_AddFolder(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"FolderID", "Name", NULL}; PyObject *folder_p, *name_p; unsigned char *folder_g, *name_g; GSM_File File; memset(&File, 0, sizeof(File)); if (!PyArg_ParseTupleAndKeywords(args, kwds, "UU", kwlist, &folder_p, &name_p)) return NULL; File.ReadOnly = FALSE; File.Protected = FALSE; File.System = FALSE; File.Hidden = FALSE; folder_g = StringPythonToGammu(folder_p); name_g = StringPythonToGammu(name_p); CopyUnicodeString(File.ID_FullName, folder_g); CopyUnicodeString(File.Name, name_g); free(folder_g); free(name_g); BEGIN_PHONE_COMM error = GSM_AddFolder(self->s, &File); END_PHONE_COMM if (!checkError(error, "AddFolder")) return NULL; return UnicodeStringToPython(File.ID_FullName); } /****************/ /* DeleteFolder */ /****************/ static char StateMachine_DeleteFolder__doc__[] = "DeleteFolder(FolderID)\n\n" "Deletes folder on filesystem.\n\n" "@param FolderID: Folder to delete\n" "@type FolderID: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_DeleteFolder(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; static char *kwlist[] = {"FolderID", NULL}; PyObject *folder_p; unsigned char *folder_g; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U", kwlist, &folder_p)) return NULL; folder_g = StringPythonToGammu(folder_p); BEGIN_PHONE_COMM error = GSM_DeleteFolder(self->s, folder_g); END_PHONE_COMM free(folder_g); if (!checkError(error, "DeleteFolder")) return NULL; Py_RETURN_NONE; } #if 0 /**********************/ /* GetGPRSAccessPoint */ /**********************/ static char StateMachine_GetGPRSAccessPoint__doc__[] = "Gets GPRS access point." ; static PyObject * StateMachine_GetGPRSAccessPoint(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_GetGPRSAccessPoint(self->s); END_PHONE_COMM if (!checkError(error, "GetGPRSAccessPoint")) return NULL; Py_RETURN_NONE; } /**********************/ /* SetGPRSAccessPoint */ /**********************/ static char StateMachine_SetGPRSAccessPoint__doc__[] = "Sets GPRS access point." ; static PyObject * StateMachine_SetGPRSAccessPoint(StateMachineObject *self, PyObject *args, PyObject *kwds) { GSM_Error error; BEGIN_PHONE_COMM error = GSM_SetGPRSAccessPoint(self->s); END_PHONE_COMM if (!checkError(error, "SetGPRSAccessPoint")) return NULL; Py_RETURN_NONE; } #endif static char StateMachine_SetDebugFile__doc__[] = "SetDebugFile(File, Global)\n\n" "Sets state machine debug file.\n\n" "@param File: File where to write debug stuff (as configured by L{SetDebugLevel}). Can be either None for no file, Python file object or filename.\n" "@type File: mixed\n" "@param Global: Whether to use global debug structure (overrides File)\n" "@type Global: boolean\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetDebugFile(StateMachineObject *self, PyObject *args, PyObject *kwds) { PyObject *value; int global = 0; static char *kwlist[] = {"File", "Global", NULL}; GSM_Debug_Info * di; di = GSM_GetDebug(self->s); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &value, &global)) return NULL; /* Set global debug config */ GSM_SetDebugGlobal(global, di); return gammu_set_debug(di, value, &(self->DebugFile)); } static char StateMachine_SetDebugLevel__doc__[] = "SetDebugLevel(Level)\n\n" "Sets state machine debug level accorting to passed string. You need to configure output file using L{SetDebugFile} to activate it.\n\n" "@type Level: string\n" "@param Level: name of debug level to use, currently one of:\n" " - nothing\n" " - text\n" " - textall\n" " - binary\n" " - errors\n" " - textdate\n" " - textalldate\n" " - errorsdate\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetDebugLevel(StateMachineObject *self, PyObject *args, PyObject *kwds) { char *level; static char *kwlist[] = {"Level", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &level)) return NULL; if (!GSM_SetDebugLevel(level, GSM_GetDebug(self->s))) { PyErr_SetString(PyExc_ValueError, level); return NULL; } Py_RETURN_NONE; } static char StateMachine_SetIncomingCallback__doc__[] = "SetIncomingCallback(Callback)\n\n" "Sets callback function which is called whenever any (enabled) incoming event appears. Please note that you have to enable each event type by calling SetIncoming* functions.\n\n" "@param Callback: callback function or None for disabling\n" "@type Callback: function, it will get three params: StateMachine object, event type and it's data in dictionary\n" "@return: None\n" "@rtype: None\n" ; static PyObject * StateMachine_SetIncomingCallback(StateMachineObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Callback", NULL}; PyObject *temp; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &temp)) return NULL; if (temp == Py_None) { temp = NULL; } else if (!PyCallable_Check(temp)) { PyErr_SetString(PyExc_TypeError, "Parameter must be callable"); return NULL; } /* Use X variants here as we might have NULL there and those handle it gracefully. */ Py_XDECREF(self->IncomingCallback); self->IncomingCallback = temp; Py_XINCREF(self->IncomingCallback); Py_RETURN_NONE; } static struct PyMethodDef StateMachine_methods[] = { {"ReadConfig", (PyCFunction)StateMachine_ReadConfig, METH_VARARGS|METH_KEYWORDS, StateMachine_ReadConfig__doc__}, {"SetConfig", (PyCFunction)StateMachine_SetConfig, METH_VARARGS|METH_KEYWORDS, StateMachine_SetConfig__doc__}, {"GetConfig", (PyCFunction)StateMachine_GetConfig, METH_VARARGS|METH_KEYWORDS, StateMachine_GetConfig__doc__}, {"Init", (PyCFunction)StateMachine_Init, METH_VARARGS|METH_KEYWORDS, StateMachine_Init__doc__}, {"Terminate", (PyCFunction)StateMachine_Terminate, METH_VARARGS|METH_KEYWORDS, StateMachine_Terminate__doc__}, {"Abort", (PyCFunction)StateMachine_Abort, METH_VARARGS|METH_KEYWORDS, StateMachine_Abort__doc__}, {"ReadDevice", (PyCFunction)StateMachine_ReadDevice, METH_VARARGS|METH_KEYWORDS, StateMachine_ReadDevice__doc__}, {"GetManufacturer", (PyCFunction)StateMachine_GetManufacturer, METH_VARARGS|METH_KEYWORDS, StateMachine_GetManufacturer__doc__}, {"GetModel", (PyCFunction)StateMachine_GetModel, METH_VARARGS|METH_KEYWORDS, StateMachine_GetModel__doc__}, {"GetFirmware", (PyCFunction)StateMachine_GetFirmware, METH_VARARGS|METH_KEYWORDS, StateMachine_GetFirmware__doc__}, {"GetIMEI", (PyCFunction)StateMachine_GetIMEI, METH_VARARGS|METH_KEYWORDS, StateMachine_GetIMEI__doc__}, {"GetOriginalIMEI", (PyCFunction)StateMachine_GetOriginalIMEI, METH_VARARGS|METH_KEYWORDS, StateMachine_GetOriginalIMEI__doc__}, {"GetManufactureMonth", (PyCFunction)StateMachine_GetManufactureMonth, METH_VARARGS|METH_KEYWORDS, StateMachine_GetManufactureMonth__doc__}, {"GetProductCode", (PyCFunction)StateMachine_GetProductCode, METH_VARARGS|METH_KEYWORDS, StateMachine_GetProductCode__doc__}, {"GetHardware", (PyCFunction)StateMachine_GetHardware, METH_VARARGS|METH_KEYWORDS, StateMachine_GetHardware__doc__}, {"GetPPM", (PyCFunction)StateMachine_GetPPM, METH_VARARGS|METH_KEYWORDS, StateMachine_GetPPM__doc__}, {"GetSIMIMSI", (PyCFunction)StateMachine_GetSIMIMSI, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSIMIMSI__doc__}, {"GetDateTime", (PyCFunction)StateMachine_GetDateTime, METH_VARARGS|METH_KEYWORDS, StateMachine_GetDateTime__doc__}, {"SetDateTime", (PyCFunction)StateMachine_SetDateTime, METH_VARARGS|METH_KEYWORDS, StateMachine_SetDateTime__doc__}, {"GetAlarm", (PyCFunction)StateMachine_GetAlarm, METH_VARARGS|METH_KEYWORDS, StateMachine_GetAlarm__doc__}, {"SetAlarm", (PyCFunction)StateMachine_SetAlarm, METH_VARARGS|METH_KEYWORDS, StateMachine_SetAlarm__doc__}, {"GetLocale", (PyCFunction)StateMachine_GetLocale, METH_VARARGS|METH_KEYWORDS, StateMachine_GetLocale__doc__}, {"SetLocale", (PyCFunction)StateMachine_SetLocale, METH_VARARGS|METH_KEYWORDS, StateMachine_SetLocale__doc__}, {"PressKey", (PyCFunction)StateMachine_PressKey, METH_VARARGS|METH_KEYWORDS, StateMachine_PressKey__doc__}, {"Reset", (PyCFunction)StateMachine_Reset, METH_VARARGS|METH_KEYWORDS, StateMachine_Reset__doc__}, {"ResetPhoneSettings", (PyCFunction)StateMachine_ResetPhoneSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_ResetPhoneSettings__doc__}, {"EnterSecurityCode", (PyCFunction)StateMachine_EnterSecurityCode, METH_VARARGS|METH_KEYWORDS, StateMachine_EnterSecurityCode__doc__}, {"GetSecurityStatus", (PyCFunction)StateMachine_GetSecurityStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSecurityStatus__doc__}, {"GetDisplayStatus", (PyCFunction)StateMachine_GetDisplayStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetDisplayStatus__doc__}, {"SetAutoNetworkLogin", (PyCFunction)StateMachine_SetAutoNetworkLogin, METH_VARARGS|METH_KEYWORDS, StateMachine_SetAutoNetworkLogin__doc__}, {"GetBatteryCharge", (PyCFunction)StateMachine_GetBatteryCharge, METH_VARARGS|METH_KEYWORDS, StateMachine_GetBatteryCharge__doc__}, {"GetSignalQuality", (PyCFunction)StateMachine_GetSignalQuality, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSignalQuality__doc__}, {"GetNetworkInfo", (PyCFunction)StateMachine_GetNetworkInfo, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNetworkInfo__doc__}, {"GetCategory", (PyCFunction)StateMachine_GetCategory, METH_VARARGS|METH_KEYWORDS, StateMachine_GetCategory__doc__}, {"AddCategory", (PyCFunction)StateMachine_AddCategory, METH_VARARGS|METH_KEYWORDS, StateMachine_AddCategory__doc__}, {"GetCategoryStatus", (PyCFunction)StateMachine_GetCategoryStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetCategoryStatus__doc__}, {"GetMemoryStatus", (PyCFunction)StateMachine_GetMemoryStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetMemoryStatus__doc__}, {"GetMemory", (PyCFunction)StateMachine_GetMemory, METH_VARARGS|METH_KEYWORDS, StateMachine_GetMemory__doc__}, {"GetNextMemory", (PyCFunction)StateMachine_GetNextMemory, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNextMemory__doc__}, {"SetMemory", (PyCFunction)StateMachine_SetMemory, METH_VARARGS|METH_KEYWORDS, StateMachine_SetMemory__doc__}, {"AddMemory", (PyCFunction)StateMachine_AddMemory, METH_VARARGS|METH_KEYWORDS, StateMachine_AddMemory__doc__}, {"DeleteMemory", (PyCFunction)StateMachine_DeleteMemory, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteMemory__doc__}, {"DeleteAllMemory", (PyCFunction)StateMachine_DeleteAllMemory, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteAllMemory__doc__}, {"GetSpeedDial", (PyCFunction)StateMachine_GetSpeedDial, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSpeedDial__doc__}, {"SetSpeedDial", (PyCFunction)StateMachine_SetSpeedDial, METH_VARARGS|METH_KEYWORDS, StateMachine_SetSpeedDial__doc__}, {"GetSMSC", (PyCFunction)StateMachine_GetSMSC, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSMSC__doc__}, {"SetSMSC", (PyCFunction)StateMachine_SetSMSC, METH_VARARGS|METH_KEYWORDS, StateMachine_SetSMSC__doc__}, {"GetSMSStatus", (PyCFunction)StateMachine_GetSMSStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSMSStatus__doc__}, {"GetSMS", (PyCFunction)StateMachine_GetSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSMS__doc__}, {"GetNextSMS", (PyCFunction)StateMachine_GetNextSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNextSMS__doc__}, {"SetSMS", (PyCFunction)StateMachine_SetSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_SetSMS__doc__}, {"AddSMS", (PyCFunction)StateMachine_AddSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_AddSMS__doc__}, {"DeleteSMS", (PyCFunction)StateMachine_DeleteSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteSMS__doc__}, {"SendSMS", (PyCFunction)StateMachine_SendSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_SendSMS__doc__}, {"SendSavedSMS", (PyCFunction)StateMachine_SendSavedSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_SendSavedSMS__doc__}, {"SetIncomingSMS", (PyCFunction)StateMachine_SetIncomingSMS, METH_VARARGS|METH_KEYWORDS, StateMachine_SetIncomingSMS__doc__}, {"SetIncomingCB", (PyCFunction)StateMachine_SetIncomingCB, METH_VARARGS|METH_KEYWORDS, StateMachine_SetIncomingCB__doc__}, {"SetIncomingCall", (PyCFunction)StateMachine_SetIncomingCall, METH_VARARGS|METH_KEYWORDS, StateMachine_SetIncomingCall__doc__}, {"SetIncomingUSSD", (PyCFunction)StateMachine_SetIncomingUSSD, METH_VARARGS|METH_KEYWORDS, StateMachine_SetIncomingUSSD__doc__}, {"GetSMSFolders", (PyCFunction)StateMachine_GetSMSFolders, METH_VARARGS|METH_KEYWORDS, StateMachine_GetSMSFolders__doc__}, {"AddSMSFolder", (PyCFunction)StateMachine_AddSMSFolder, METH_VARARGS|METH_KEYWORDS, StateMachine_AddSMSFolder__doc__}, {"DeleteSMSFolder", (PyCFunction)StateMachine_DeleteSMSFolder, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteSMSFolder__doc__}, {"DialVoice", (PyCFunction)StateMachine_DialVoice, METH_VARARGS|METH_KEYWORDS, StateMachine_DialVoice__doc__}, {"DialService", (PyCFunction)StateMachine_DialService, METH_VARARGS|METH_KEYWORDS, StateMachine_DialService__doc__}, {"AnswerCall", (PyCFunction)StateMachine_AnswerCall, METH_VARARGS|METH_KEYWORDS, StateMachine_AnswerCall__doc__}, {"CancelCall", (PyCFunction)StateMachine_CancelCall, METH_VARARGS|METH_KEYWORDS, StateMachine_CancelCall__doc__}, {"HoldCall", (PyCFunction)StateMachine_HoldCall, METH_VARARGS|METH_KEYWORDS, StateMachine_HoldCall__doc__}, {"UnholdCall", (PyCFunction)StateMachine_UnholdCall, METH_VARARGS|METH_KEYWORDS, StateMachine_UnholdCall__doc__}, {"ConferenceCall", (PyCFunction)StateMachine_ConferenceCall, METH_VARARGS|METH_KEYWORDS, StateMachine_ConferenceCall__doc__}, {"SplitCall", (PyCFunction)StateMachine_SplitCall, METH_VARARGS|METH_KEYWORDS, StateMachine_SplitCall__doc__}, {"TransferCall", (PyCFunction)StateMachine_TransferCall, METH_VARARGS|METH_KEYWORDS, StateMachine_TransferCall__doc__}, {"SwitchCall", (PyCFunction)StateMachine_SwitchCall, METH_VARARGS|METH_KEYWORDS, StateMachine_SwitchCall__doc__}, {"SendDTMF", (PyCFunction)StateMachine_SendDTMF, METH_VARARGS|METH_KEYWORDS, StateMachine_SendDTMF__doc__}, {"GetCallDivert", (PyCFunction)StateMachine_GetCallDivert, METH_VARARGS|METH_KEYWORDS, StateMachine_GetCallDivert__doc__}, {"SetCallDivert", (PyCFunction)StateMachine_SetCallDivert, METH_VARARGS|METH_KEYWORDS, StateMachine_SetCallDivert__doc__}, {"CancelAllDiverts", (PyCFunction)StateMachine_CancelAllDiverts, METH_VARARGS|METH_KEYWORDS, StateMachine_CancelAllDiverts__doc__}, #if 0 {"GetRingtone", (PyCFunction)StateMachine_GetRingtone, METH_VARARGS|METH_KEYWORDS, StateMachine_GetRingtone__doc__}, {"SetRingtone", (PyCFunction)StateMachine_SetRingtone, METH_VARARGS|METH_KEYWORDS, StateMachine_SetRingtone__doc__}, {"GetRingtonesInfo", (PyCFunction)StateMachine_GetRingtonesInfo, METH_VARARGS|METH_KEYWORDS, StateMachine_GetRingtonesInfo__doc__}, {"DeleteUserRingtones", (PyCFunction)StateMachine_DeleteUserRingtones, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteUserRingtones__doc__}, {"PlayTone", (PyCFunction)StateMachine_PlayTone, METH_VARARGS|METH_KEYWORDS, StateMachine_PlayTone__doc__}, {"GetWAPBookmark", (PyCFunction)StateMachine_GetWAPBookmark, METH_VARARGS|METH_KEYWORDS, StateMachine_GetWAPBookmark__doc__}, {"SetWAPBookmark", (PyCFunction)StateMachine_SetWAPBookmark, METH_VARARGS|METH_KEYWORDS, StateMachine_SetWAPBookmark__doc__}, {"DeleteWAPBookmark", (PyCFunction)StateMachine_DeleteWAPBookmark, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteWAPBookmark__doc__}, {"GetWAPSettings", (PyCFunction)StateMachine_GetWAPSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_GetWAPSettings__doc__}, {"SetWAPSettings", (PyCFunction)StateMachine_SetWAPSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_SetWAPSettings__doc__}, {"GetMMSSettings", (PyCFunction)StateMachine_GetMMSSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_GetMMSSettings__doc__}, {"SetMMSSettings", (PyCFunction)StateMachine_SetMMSSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_SetMMSSettings__doc__}, {"GetBitmap", (PyCFunction)StateMachine_GetBitmap, METH_VARARGS|METH_KEYWORDS, StateMachine_GetBitmap__doc__}, {"SetBitmap", (PyCFunction)StateMachine_SetBitmap, METH_VARARGS|METH_KEYWORDS, StateMachine_SetBitmap__doc__}, #endif {"GetToDoStatus", (PyCFunction)StateMachine_GetToDoStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetToDoStatus__doc__}, {"GetToDo", (PyCFunction)StateMachine_GetToDo, METH_VARARGS|METH_KEYWORDS, StateMachine_GetToDo__doc__}, {"GetNextToDo", (PyCFunction)StateMachine_GetNextToDo, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNextToDo__doc__}, {"SetToDo", (PyCFunction)StateMachine_SetToDo, METH_VARARGS|METH_KEYWORDS, StateMachine_SetToDo__doc__}, {"AddToDo", (PyCFunction)StateMachine_AddToDo, METH_VARARGS|METH_KEYWORDS, StateMachine_AddToDo__doc__}, {"DeleteToDo", (PyCFunction)StateMachine_DeleteToDo, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteToDo__doc__}, {"DeleteAllToDo", (PyCFunction)StateMachine_DeleteAllToDo, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteAllToDo__doc__}, {"GetCalendarStatus", (PyCFunction)StateMachine_GetCalendarStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetCalendarStatus__doc__}, {"GetCalendar", (PyCFunction)StateMachine_GetCalendar, METH_VARARGS|METH_KEYWORDS, StateMachine_GetCalendar__doc__}, {"GetNextCalendar", (PyCFunction)StateMachine_GetNextCalendar, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNextCalendar__doc__}, {"SetCalendar", (PyCFunction)StateMachine_SetCalendar, METH_VARARGS|METH_KEYWORDS, StateMachine_SetCalendar__doc__}, {"AddCalendar", (PyCFunction)StateMachine_AddCalendar, METH_VARARGS|METH_KEYWORDS, StateMachine_AddCalendar__doc__}, {"DeleteCalendar", (PyCFunction)StateMachine_DeleteCalendar, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteCalendar__doc__}, {"DeleteAllCalendar", (PyCFunction)StateMachine_DeleteAllCalendar, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteAllCalendar__doc__}, #if 0 {"GetCalendarSettings", (PyCFunction)StateMachine_GetCalendarSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_GetCalendarSettings__doc__}, {"SetCalendarSettings", (PyCFunction)StateMachine_SetCalendarSettings, METH_VARARGS|METH_KEYWORDS, StateMachine_SetCalendarSettings__doc__}, {"GetNote", (PyCFunction)StateMachine_GetNote, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNote__doc__}, {"GetProfile", (PyCFunction)StateMachine_GetProfile, METH_VARARGS|METH_KEYWORDS, StateMachine_GetProfile__doc__}, {"SetProfile", (PyCFunction)StateMachine_SetProfile, METH_VARARGS|METH_KEYWORDS, StateMachine_SetProfile__doc__}, {"GetFMStation", (PyCFunction)StateMachine_GetFMStation, METH_VARARGS|METH_KEYWORDS, StateMachine_GetFMStation__doc__}, {"SetFMStation", (PyCFunction)StateMachine_SetFMStation, METH_VARARGS|METH_KEYWORDS, StateMachine_SetFMStation__doc__}, {"ClearFMStations", (PyCFunction)StateMachine_ClearFMStations, METH_VARARGS|METH_KEYWORDS, StateMachine_ClearFMStations__doc__}, #endif {"GetNextFileFolder", (PyCFunction)StateMachine_GetNextFileFolder, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNextFileFolder__doc__}, {"GetFolderListing", (PyCFunction)StateMachine_GetFolderListing, METH_VARARGS|METH_KEYWORDS, StateMachine_GetFolderListing__doc__}, {"GetNextRootFolder", (PyCFunction)StateMachine_GetNextRootFolder, METH_VARARGS|METH_KEYWORDS, StateMachine_GetNextRootFolder__doc__}, {"SetFileAttributes", (PyCFunction)StateMachine_SetFileAttributes, METH_VARARGS|METH_KEYWORDS, StateMachine_SetFileAttributes__doc__}, {"GetFilePart", (PyCFunction)StateMachine_GetFilePart, METH_VARARGS|METH_KEYWORDS, StateMachine_GetFilePart__doc__}, {"AddFilePart", (PyCFunction)StateMachine_AddFilePart, METH_VARARGS|METH_KEYWORDS, StateMachine_AddFilePart__doc__}, {"SendFilePart", (PyCFunction)StateMachine_SendFilePart, METH_VARARGS|METH_KEYWORDS, StateMachine_SendFilePart__doc__}, {"GetFileSystemStatus", (PyCFunction)StateMachine_GetFileSystemStatus, METH_VARARGS|METH_KEYWORDS, StateMachine_GetFileSystemStatus__doc__}, {"DeleteFile", (PyCFunction)StateMachine_DeleteFile, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteFile__doc__}, {"AddFolder", (PyCFunction)StateMachine_AddFolder, METH_VARARGS|METH_KEYWORDS, StateMachine_AddFolder__doc__}, {"DeleteFolder", (PyCFunction)StateMachine_DeleteFolder, METH_VARARGS|METH_KEYWORDS, StateMachine_DeleteFolder__doc__}, #if 0 {"GetGPRSAccessPoint", (PyCFunction)StateMachine_GetGPRSAccessPoint, METH_VARARGS|METH_KEYWORDS, StateMachine_GetGPRSAccessPoint__doc__}, {"SetGPRSAccessPoint", (PyCFunction)StateMachine_SetGPRSAccessPoint, METH_VARARGS|METH_KEYWORDS, StateMachine_SetGPRSAccessPoint__doc__}, #endif {"SetDebugFile", (PyCFunction)StateMachine_SetDebugFile, METH_VARARGS|METH_KEYWORDS, StateMachine_SetDebugFile__doc__}, {"SetDebugLevel", (PyCFunction)StateMachine_SetDebugLevel, METH_VARARGS|METH_KEYWORDS, StateMachine_SetDebugLevel__doc__}, {"SetIncomingCallback", (PyCFunction)StateMachine_SetIncomingCallback, METH_VARARGS|METH_KEYWORDS, StateMachine_SetIncomingCallback__doc__}, {NULL, NULL, 0, NULL} /* sentinel */ }; /* ---------- */ #if 0 static PyObject * StateMachine_getattr(StateMachineObject *self, char *name) { /* XXXX Add your own getattr code here */ return -1; // Py_FindMethod(StateMachine_methods, (PyObject *)self, name); } static int StateMachine_setattr(StateMachineObject *self, char *name, PyObject *v) { /* Set attribute 'name' to value 'v'. v==NULL means delete */ /* XXXX Add your own setattr code here */ return -1; } #endif #if 0 static int StateMachine_compare(StateMachineObject *v, StateMachineObject *w) { /* XXXX Compare objects and return -1, 0 or 1 */ } static PyObject * StateMachine_repr(StateMachineObject *self) { PyObject *s; /* XXXX Add code here to put self into s */ return s; } static PyObject * StateMachine_str(StateMachineObject *self) { PyObject *s; /* XXXX Add code here to put self into s */ return s; } #endif static void StateMachine_dealloc(StateMachineObject *self) { BEGIN_PHONE_COMM if (GSM_IsConnected(self->s)) { /* Disable any possible incoming notifications */ GSM_SetIncomingSMS(self->s, FALSE); GSM_SetIncomingCall(self->s, FALSE); GSM_SetIncomingCB(self->s, FALSE); GSM_SetIncomingUSSD(self->s, FALSE); /* Terminate the connection */ GSM_TerminateConnection(self->s); } GSM_FreeStateMachine(self->s); self->s = NULL; END_PHONE_COMM if (self->DebugFile != NULL) { Py_DECREF(self->DebugFile); self->DebugFile = NULL; } #ifdef WITH_THREAD PyThread_free_lock(self->mutex); #endif Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * StateMachine_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { StateMachineObject *self; self = (StateMachineObject *)type->tp_alloc(type, 0); self->s = GSM_AllocStateMachine(); /* Reset our structures */ self->DebugFile = NULL; self->IncomingCallback = NULL; self->IncomingCallQueue[0] = NULL; self->IncomingSMSQueue[0] = NULL; self->IncomingCBQueue[0] = NULL; self->IncomingUSSDQueue[0] = NULL; /* Create phone communication lock */ #ifdef WITH_THREAD self->mutex = PyThread_allocate_lock(); #endif return (PyObject *)self; } static int StateMachine_init(StateMachineObject *self, PyObject *args, PyObject *kwds) { char *s = NULL; static char *kwlist[] = {"Locale", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &s)) return -1; if (s != NULL && strcmp(s, "auto") == 0) { s = NULL; } /* Init Gammu locales, we don't care about NULL, it's handled correctly */ GSM_InitLocales(s); return 0; } static char StateMachineType__doc__[] = "StateMachine(Locale)\n\n" "StateMachine object, that is used for communication with phone.\n\n" /* FIXME: following doc should go elsewhere */ "param Locale: What locales to use for gammu error messages, default is 'auto' which does autodetection according to user locales\n" "type Locale: string\n" ; static PyTypeObject StateMachineType = { PyVarObject_HEAD_INIT(NULL, 0) "_gammu.StateMachine", /*tp_name*/ sizeof(StateMachineObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)StateMachine_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ #if 0 (getattrfunc)StateMachine_getattr, /*tp_getattr*/ (setattrfunc)StateMachine_setattr, /*tp_setattr*/ #endif 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, #if 0 (cmpfunc)StateMachine_compare, /*tp_compare*/ #endif 0, #if 0 (reprfunc)StateMachine_repr, /*tp_repr*/ #endif 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ 0, #if 0 (reprfunc)StateMachine_str, /*tp_str*/ #endif 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ StateMachineType__doc__, /* Documentation string */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ StateMachine_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)StateMachine_init, /* tp_init */ 0, /* tp_alloc */ StateMachine_new, /* tp_new */ NULL, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ #ifdef Py_TPFLAGS_HAVE_FINALIZE 0, /* tp_finalize */ #endif }; /* End of code for StateMachine objects */ /* -------------------------------------------------------- */ static char gammu_Version__doc__[] = "Version()\n\n" "Get version information.\n" "@return: Tuple of version information - Gammu runtime version, python-gammu version, build time Gammu version.\n" "@rtype: tuple\n" ; static PyObject * gammu_Version(PyObject *self) { return Py_BuildValue("s,s,s", GetGammuVersion(), PYTHON_GAMMU_VERSION, GAMMU_VERSION); } static char gammu_SetDebugFile__doc__[] = "SetDebugFile(File)\n\n" "Sets global debug file.\n\n" "@param File: File where to write debug stuff (as configured by L{SetDebugLevel}). Can be either None for no file, Python file object or filename.\n" "@type File: mixed\n" "@return: None\n" "@rtype: None\n" ; static PyObject * gammu_SetDebugFile(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *value; static char *kwlist[] = {"File", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &value)) return NULL; return gammu_set_debug(GSM_GetGlobalDebug(), value, &DebugFile); } static char gammu_SetDebugLevel__doc__[] = "SetDebugLevel(Level)\n\n" "Sets global debug level accorting to passed string. You need to configure output file using L{SetDebugFile} to activate it.\n\n" "@type Level: string\n" "@param Level: name of debug level to use, currently one of:\n" " - nothing\n" " - text\n" " - textall\n" " - binary\n" " - errors\n" " - textdate\n" " - textalldate\n" " - errorsdate\n" "@return: None\n" "@rtype: None\n" ; static PyObject * gammu_SetDebugLevel(PyObject *self, PyObject *args, PyObject *kwds) { char *level; static char *kwlist[] = {"Level", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &level)) return NULL; if (!GSM_SetDebugLevel(level, GSM_GetGlobalDebug())) { PyErr_SetString(PyExc_ValueError, level); return NULL; } Py_RETURN_NONE; } static char gammu_LinkSMS__doc__[] = "LinkSMS(Messages, EMS)\n\n" "Links multi part SMS messages.\n\n" "@type Messages: list\n" "@type EMS: boolean\n" "@param Messages: List of messages to link\n" "@param EMS: Whether to detect ems, defauls to True\n" "@return: List of linked messages\n" "@rtype: list\n" ; static PyObject * gammu_LinkSMS(PyObject *self, PyObject *args, PyObject *kwds) { int ems = 1; GSM_MultiSMSMessage **smsin; GSM_MultiSMSMessage **smsout; static char *kwlist[] = {"Messages", "EMS", NULL}; GSM_Error error; PyObject *value; PyObject *ret; Py_ssize_t len; int i; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|I", kwlist, &PyList_Type, &(value), &ems)) return NULL; len = PyList_Size(value); if (!MultiSMSListFromPython(value, &smsin)) return NULL; smsout = (GSM_MultiSMSMessage **)malloc((len + 1) * sizeof(GSM_MultiSMSMessage *)); error = GSM_LinkSMS(GSM_GetGlobalDebug(), smsin, smsout, ems); if (!checkError(error, "LinkSMS")) return NULL; ret = MultiSMSListToPython(smsout); i = 0; while(smsout[i] != NULL) { free(smsout[i]); i++; } free(smsout); i = 0; while(smsin[i] != NULL) { free(smsin[i]); i++; } free(smsin); return ret; } static char gammu_DecodeSMS__doc__[] = "DecodeSMS(Messages, EMS)\n\n" "Decodes multi part SMS message.\n\n" "@param Messages: Nessages to decode\n" "@type Messages: list\n" "@param EMS: Whether to use EMS, defalt to True\n" "@type EMS: boolean\n" "@return: Multi part message information\n" "@rtype: hash\n" ; static PyObject * gammu_DecodeSMS(PyObject *self, PyObject *args, PyObject *kwds) { int ems = 1; GSM_MultiSMSMessage smsin; GSM_MultiPartSMSInfo smsinfo; static char *kwlist[] = {"Messages", "EMS", NULL}; PyObject *value; PyObject *res; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|I", kwlist, &PyList_Type, &(value), &ems)) return NULL; if (!MultiSMSFromPython(value, &smsin)) return NULL; if (!GSM_DecodeMultiPartSMS(GSM_GetGlobalDebug(), &smsinfo, &smsin, ems)) { GSM_FreeMultiPartSMSInfo(&smsinfo); Py_RETURN_NONE; } res = SMSInfoToPython(&smsinfo); GSM_FreeMultiPartSMSInfo(&smsinfo); return res; } static char gammu_EncodeSMS__doc__[] = "EncodeSMS(MessageInfo)\n\n" "Encodes multi part SMS message.\n\n" "@param MessageInfo: Description of message\n" "@type MessageInfo: dict\n" "@return: Dictionary with raw message\n" "@rtype: dict\n" ; static PyObject * gammu_EncodeSMS(PyObject *self, PyObject *args, PyObject *kwds) { GSM_MultiSMSMessage smsout; GSM_MultiPartSMSInfo smsinfo; static char *kwlist[] = {"MessagesInfo", NULL}; PyObject *value; memset(&smsout, 0, sizeof(GSM_MultiSMSMessage)); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!SMSInfoFromPython(value, &smsinfo)) return NULL; if (!GSM_EncodeMultiPartSMS(GSM_GetGlobalDebug(), &smsinfo, &smsout)) { GSM_FreeMultiPartSMSInfo(&smsinfo); Py_RETURN_NONE; } GSM_FreeMultiPartSMSInfo(&smsinfo); return MultiSMSToPython(&smsout); } static char gammu_DecodeVCARD__doc__[] = "DecodeVCARD(Text)\n\n" "Decodes memory entry v from a string.\n\n" "@param Text: String to decode\n" "@type Text: string\n" "@return: Memory entry\n" "@rtype: hash\n" ; static PyObject * gammu_DecodeVCARD(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Text", NULL}; char *buffer; size_t pos = 0; GSM_MemoryEntry entry; GSM_Error error; PyObject *result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &buffer)) return NULL; error = GSM_DecodeVCARD(GSM_GetGlobalDebug(), buffer, &pos, &entry, SonyEricsson_VCard21); if (!checkError(error, "DecodeVCARD")) return NULL; result = MemoryEntryToPython(&entry); GSM_FreeMemoryEntry(&entry); return result; } static char gammu_EncodeVCARD__doc__[] = "EncodeVCARD(Entry)\n\n" "Encodes memory entry to a vCard.\n\n" "@param Entry: Memory entry\n" "@type Entry: dict\n" "@return: String with vCard\n" "@rtype: string\n" ; static PyObject * gammu_EncodeVCARD(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Entry", NULL}; PyObject *value; GSM_MemoryEntry entry; size_t pos = 0; GSM_Error error; char buffer[10240]; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!MemoryEntryFromPython(value, &entry, 1)) return NULL; error = GSM_EncodeVCARD(GSM_GetGlobalDebug(), buffer, sizeof(buffer), &pos, &entry, TRUE, SonyEricsson_VCard21); if (!checkError(error, "EncodeVCARD")) return NULL; return PyUnicode_FromString(buffer); } static char gammu_DecodeVCS__doc__[] = "DecodeVCS(Text)\n\n" "Decodes todo/calendar entry v from a string.\n\n" "@param Text: String to decode\n" "@type Text: string\n" "@return: Calendar or todo entry (whatever one was included in string)\n" "@rtype: hash\n" ; static PyObject * gammu_DecodeVCS(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Text", NULL}; char *buffer; size_t pos = 0; GSM_ToDoEntry todo_entry; GSM_CalendarEntry calendar_entry; GSM_Error error; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &buffer)) return NULL; todo_entry.Location = 0; calendar_entry.Location = 0; error = GSM_DecodeVCALENDAR_VTODO(GSM_GetGlobalDebug(), buffer, &pos, &calendar_entry, &todo_entry, SonyEricsson_VCalendar, SonyEricsson_VToDo); if (!checkError(error, "DecodeVCS")) return NULL; if (calendar_entry.EntriesNum > 0) { return CalendarToPython(&calendar_entry); } else { return TodoToPython(&todo_entry); } } static char gammu_DecodeICS__doc__[] = "DecodeICS(Text)\n\n" "Decodes todo/calendar entry v from a string.\n\n" "@param Text: String to decode\n" "@type Text: string\n" "@return: Calendar or todo entry (whatever one was included in string)\n" "@rtype: hash\n" ; static PyObject * gammu_DecodeICS(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Text", NULL}; char *buffer; size_t pos = 0; GSM_ToDoEntry todo_entry; GSM_CalendarEntry calendar_entry; GSM_Error error; todo_entry.Location = 0; calendar_entry.Location = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &buffer)) return NULL; error = GSM_DecodeVCALENDAR_VTODO(GSM_GetGlobalDebug(), buffer, &pos, &calendar_entry, &todo_entry, Mozilla_iCalendar, Mozilla_VToDo); if (!checkError(error, "DecodeICS")) return NULL; if (calendar_entry.EntriesNum > 0) { return CalendarToPython(&calendar_entry); } else { return TodoToPython(&todo_entry); } } static char gammu_EncodeVCALENDAR__doc__[] = "EncodeVCALENDAR(Entry)\n\n" "Encodes memory entry to a vCalendar.\n\n" "@param Entry: Memory entry\n" "@type Entry: dict\n" "@return: String with vCalendar\n" "@rtype: string\n" ; static PyObject * gammu_EncodeVCALENDAR(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Entry", NULL}; PyObject *value; GSM_CalendarEntry entry; size_t pos = 0; GSM_Error error; char buffer[10240]; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!CalendarFromPython(value, &entry, 1)) return NULL; error = GSM_EncodeVCALENDAR(buffer, sizeof(buffer), &pos, &entry, TRUE, SonyEricsson_VCalendar); if (!checkError(error, "EncodeVCALENDAR")) return NULL; return PyUnicode_FromString(buffer); } static char gammu_EncodeICALENDAR__doc__[] = "EncodeICALENDAR(Entry)\n\n" "Encodes memory entry to a iCalendar.\n\n" "@param Entry: Memory entry\n" "@type Entry: dict\n" "@return: String with iCalendar\n" "@rtype: string\n" ; static PyObject * gammu_EncodeICALENDAR(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Entry", NULL}; PyObject *value; GSM_CalendarEntry entry; size_t pos = 0; GSM_Error error; char buffer[10240]; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!CalendarFromPython(value, &entry, 1)) return NULL; error = GSM_EncodeVCALENDAR(buffer, sizeof(buffer), &pos, &entry, TRUE, Mozilla_iCalendar); if (!checkError(error, "EncodeICALENDAR")) return NULL; return PyUnicode_FromString(buffer); } static char gammu_EncodeVTODO__doc__[] = "EncodeVTODO(Entry)\n\n" "Encodes memory entry to a vTodo.\n\n" "@param Entry: Memory entry\n" "@type Entry: dict\n" "@return: String with vTodo\n" "@rtype: string\n" ; static PyObject * gammu_EncodeVTODO(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Entry", NULL}; PyObject *value; GSM_ToDoEntry entry; size_t pos = 0; GSM_Error error; char buffer[10240]; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!TodoFromPython(value, &entry, 1)) return NULL; error = GSM_EncodeVTODO(buffer, sizeof(buffer), &pos, &entry, TRUE, SonyEricsson_VToDo); if (!checkError(error, "EncodeVTODO")) return NULL; return PyUnicode_FromString(buffer); } static char gammu_EncodeITODO__doc__[] = "EncodeITODO(Entry)\n\n" "Encodes memory entry to a iTodo.\n\n" "@param Entry: Memory entry\n" "@type Entry: dict\n" "@return: String with vCard\n" "@rtype: string\n" ; static PyObject * gammu_EncodeITODO(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Entry", NULL}; PyObject *value; GSM_ToDoEntry entry; size_t pos = 0; GSM_Error error; char buffer[10240]; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyDict_Type, &(value))) return NULL; if (!TodoFromPython(value, &entry, 1)) return NULL; error = GSM_EncodeVTODO(buffer, sizeof(buffer), &pos, &entry, TRUE, Mozilla_VToDo); if (!checkError(error, "EncodeITODO")) return NULL; return PyUnicode_FromString(buffer); } static char gammu_SaveRingtone__doc__[] = "SaveRingtone(Filename, Ringtone, Format)\n\n" "Saves ringtone into file.\n\n" "@param Filename: Name of file where ringote will be saved\n" "@type Filename: string\n" "@param Ringtone: Ringtone to save\n" "@type Ringtone: dict\n" "@param Format: One of 'ott', 'mid', 'rng', 'imy', 'wav', 'rttl'\n" "@type Format: string\n" "@return: None\n" "@rtype: None\n" ; static PyObject * gammu_SaveRingtone(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Filename", "Ringtone", "Format", NULL}; PyObject *value; PyObject *file; char *s; char *name; FILE *f; GSM_Ringtone ringtone; gboolean closefile = FALSE; PyObject *str; int fd; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO!s", kwlist, &file, &PyDict_Type, &(value), &s)) return NULL; if (!RingtoneFromPython(value, &ringtone)) { return NULL; } fd = PyObject_AsFileDescriptor(value); if (fd == -1) { PyErr_Clear(); } if (fd != -1) { fd = dup(fd); if (fd == -1) return NULL; f = fdopen(fd, "wb"); if (f == NULL) return NULL; closefile = TRUE; } else if (PyUnicode_Check(value)) { str = PyUnicode_EncodeFSDefault(value); if (str == NULL) { return NULL; } name = PyBytes_AsString(str); if (name == NULL) return NULL; f = fopen(name, "wb"); Py_DECREF(str); if (f == NULL) { PyErr_SetString(PyExc_IOError, "Can not open file for writing!"); return NULL; } closefile = TRUE; } else { PyErr_SetString(PyExc_TypeError, "Valid are only string or file parameters!"); return NULL; } if (strcmp(s, "mid") == 0) { GSM_SaveRingtoneMidi(f, &ringtone); } else if (strcmp(s, "rng") == 0) { GSM_SaveRingtoneOtt(f, &ringtone); } else if (strcmp(s, "imy") == 0) { GSM_SaveRingtoneIMelody(f, &ringtone); } else if (strcmp(s, "wav") == 0) { GSM_SaveRingtoneWav(f, &ringtone); } else if (strcmp(s, "rttl") == 0) { GSM_SaveRingtoneRttl(f,&ringtone); } else if (strcmp(s, "ott") == 0) { GSM_SaveRingtoneOtt(f,&ringtone); } else { if (closefile) { fclose(f); } PyErr_Format(PyExc_ValueError, "Bad value for format: '%s'", s); return NULL; } if (closefile) { fclose(f); } Py_RETURN_NONE; } #ifdef GSM_ENABLE_BACKUP static char gammu_SaveBackup__doc__[] = "SaveBackup(Filename, Backup, Format)\n\n" "Saves backup into file.\n\n" "@param Filename: Name of file to read backup from\n" "@type Filename: string\n" "@param Backup: Backup data, see L{ReadBackup} for description\n" "@type Backup: dict\n" "@param Format: File format to use (default is AutoUnicode)\n" "@type Format: string (Auto, AutoUnicode, LMB, VCalendar, VCard, LDIF, ICS, Gammu, GammuUnicode)\n" "@return: None\n" "@rtype: None\n" ; static PyObject * gammu_SaveBackup(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Filename", "Backup", "Format", NULL}; PyObject *value; char *filename; GSM_Backup backup; GSM_Error error; GSM_BackupFormat format = GSM_Backup_AutoUnicode; char *s = NULL; GSM_ClearBackup(&backup); if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO!|s", kwlist, &filename, &PyDict_Type, &(value), &s)) return NULL; if (s != NULL) { if (!BackupFormatFromString(s, &format)) { return NULL; } } if (!BackupFromPython(value, &backup)) return NULL; GSM_GetCurrentDateTime(&backup.DateTime); backup.DateTimeAvailable = TRUE; error = GSM_SaveBackupFile(filename, &backup, format); if (!checkError(error, "SaveBackup")) return NULL; GSM_FreeBackup(&backup); Py_RETURN_NONE; } static char gammu_ReadBackup__doc__[] = "ReadBackup(Filename, Format)\n\n" "Reads backup into file.\n\n" "@param Filename: Name of file where backup is stored\n" "@type Filename: string\n" "@param Format: File format to use (default is AutoUnicode)\n" "@type Format: string (Auto, AutoUnicode, LMB, VCalendar, VCard, LDIF, ICS, Gammu, GammuUnicode)\n" "@return: Dictionary of read entries, it contains following keys, each might be empty:\n" " - IMEI\n" " - Model\n" " - Creator\n" " - PhonePhonebook\n" " - SIMPhonebook\n" " - Calendar\n" " - ToDo\n" " - DateTime\n" "@rtype: dict\n" ; static PyObject * gammu_ReadBackup(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Filename", "Format", NULL}; char *filename; GSM_Backup backup; GSM_Error error; GSM_BackupFormat format = GSM_Backup_AutoUnicode; char *s = NULL; PyObject *result; GSM_ClearBackup(&backup); if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, &filename, &s)) return NULL; if (s != NULL) { if (!BackupFormatFromString(s, &format)) { return NULL; } } error = GSM_ReadBackupFile(filename, &backup, format); if (!checkError(error, "ReadBackup")) return NULL; result = BackupToPython(&backup); GSM_FreeBackup(&backup); return result; } static char gammu_SaveSMSBackup__doc__[] = "SaveSMSBackup(Filename, Backup)\n\n" "Saves SMS backup into file.\n\n" "@param Filename: Name of file where to save SMS backup\n" "@type Filename: string\n" "@param Backup: List of messages to store\n" "@type Backup: list\n" "@return: None\n" "@rtype: None\n" ; static PyObject * gammu_SaveSMSBackup(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Filename", "Backup", NULL}; PyObject *value; char *filename; GSM_SMS_Backup backup; GSM_Error error; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO!", kwlist, &filename, &PyList_Type, &(value))) return NULL; if (!SMSBackupFromPython(value, &backup)) return NULL; error = GSM_AddSMSBackupFile(filename, &backup); if (!checkError(error, "SaveSMSBackup")) return NULL; GSM_FreeSMSBackup(&backup); Py_RETURN_NONE; } static char gammu_ReadSMSBackup__doc__[] = "ReadSMSBackup(Filename)\n\n" "Reads SMS backup into file.\n\n" "@param Filename: Name of file where SMS backup is stored\n" "@type Filename: string\n" "@return: List of messages read from file\n" "@rtype: list\n" ; static PyObject * gammu_ReadSMSBackup(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Filename", NULL}; char *filename; GSM_SMS_Backup backup; GSM_Error error; PyObject *result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filename)) return NULL; error = GSM_ReadSMSBackupFile(filename, &backup); if (!checkError(error, "ReadSMSBackup")) return NULL; result = SMSBackupToPython(&backup); GSM_FreeSMSBackup(&backup); return result; } #endif static char gammu_SMSCounter__doc__[] = "SMSCounter(Text, UDH = \"NoUDH\", Coding = \"Default\")\n\n" "Calculates number of SMS and free chars in SMS.\n\n" "@return: Number of messages and number of free chars\n" "@rtype: tuple\n" ; static PyObject * gammu_SMSCounter(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Text", "UDH", "Coding", NULL}; PyObject *o = Py_None; const char *udh_s = "\0", *coding_s = "\0"; unsigned char *str; GSM_UDH udh; GSM_Coding_Type coding; int SMSNum; size_t CharsLeft; if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|ss", kwlist, &o, &udh_s, &coding_s)) return NULL; str = StringPythonToGammu(o); if (str == NULL) return NULL; if (udh_s[0] == 0) { udh = UDH_NoUDH; } else { udh = StringToUDHType(udh_s); if (udh == 0) return NULL; } if (coding_s[0] == 0) { coding = SMS_Coding_Default_No_Compression; } else { coding = StringToSMSCoding(coding_s) ; if (coding == 0) return NULL; } GSM_SMSCounter(GSM_GetGlobalDebug(), str, udh, coding, &SMSNum, &CharsLeft); free(str); return Py_BuildValue("(ii)", SMSNum, CharsLeft); } static char gammu_DecodePDU__doc__[] = "DecodePDU(Data, SMSC = False)\n\n" "Parses PDU packet.\n\n" "@param Data: PDU data, need to be binary not hex encoded\n" "@type Data: string\n" "@param SMSC: Whether PDU includes SMSC.\n" "@type SMSC: boolean\n" "@return: Message data\n" "@rtype: dict\n" ; static PyObject * gammu_DecodePDU(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"Data", "SMSC", NULL}; GSM_Error error; PyObject *result; PyObject *o = Py_None; gboolean smsc; const unsigned char *pdu; Py_ssize_t pdulen; size_t parse_len = 0; GSM_SMSMessage sms; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|O", kwlist, &pdu, &pdulen, &o)) return NULL; if (o == Py_None) { smsc = TRUE; } else if (o == Py_False) { smsc = FALSE; } else if (o == Py_True) { smsc = TRUE; } else { PyErr_SetString(PyExc_TypeError, "use None or boolean as SMSC!"); return NULL; } GSM_SetDefaultSMSData(&sms); error = GSM_DecodePDUFrame(NULL, &sms, pdu, pdulen, &parse_len, smsc); if (!checkError(error, "DecodePDUFrame")) return NULL; result = SMSToPython(&sms); return result; } static char gammu_EncodePDU__doc__[] = "EncodePDU(SMS, Layout = Submit)\n\n" "Creates PDU packet.\n\n" "@param SMS: SMS dictionary\n" "@type SMS: dict\n" "@param Layout: Layout (one of Submit, Deliver, StatusReport), Submit is default\n" "@type Layout: string\n" "@return: Message data\n" "@rtype: string\n" ; static PyObject * gammu_EncodePDU(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"SMS", "Layout", NULL}; GSM_Error error; PyObject *value; unsigned char buffer[1000]; char req[1000]; int length = 0, current = 0, i; GSM_SMSMessage sms; char *layout = NULL; GSM_SMSMessageLayout *msg_layout; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|s", kwlist, &PyDict_Type, &(value), &layout)) return NULL; if (!SMSFromPython(value, &sms, 0, 1, 0)) return NULL; if (layout == NULL || strcmp(layout, "Submit") == 0) { msg_layout = &PHONE_SMSSubmit; } else if(strcmp(layout, "Deliver") == 0) { msg_layout = &PHONE_SMSDeliver; } else if(strcmp(layout, "StatusReport") == 0) { msg_layout = &PHONE_SMSStatusReport; } else { PyErr_Format(PyExc_ValueError, "Wrong value for SMS layout: %s", layout); return NULL; } error = GSM_EncodeSMSFrame(NULL, &sms, buffer, *msg_layout, &length, TRUE); if (!checkError(error, "EncodeSMSFrame")) return NULL; if (msg_layout == &PHONE_SMSDeliver) { length = length - PHONE_SMSDeliver.Text; for (i = 0;i < buffer[PHONE_SMSDeliver.SMSCNumber]+1;i++) { req[current++]=buffer[PHONE_SMSDeliver.SMSCNumber+i]; } req[current++]=buffer[PHONE_SMSDeliver.firstbyte]; for (i = 0;i<((buffer[PHONE_SMSDeliver.Number]+1)/2+1)+1;i++) { req[current++]=buffer[PHONE_SMSDeliver.Number+i]; } req[current++]=buffer[PHONE_SMSDeliver.TPPID]; req[current++]=buffer[PHONE_SMSDeliver.TPDCS]; for(i = 0;i < 7;i++) { req[current++]=buffer[PHONE_SMSDeliver.DateTime+i]; } req[current++]=buffer[PHONE_SMSDeliver.TPUDL]; for(i = 0;i < length;i++) { req[current++]=buffer[PHONE_SMSDeliver.Text+i]; } } else if (msg_layout == &PHONE_SMSSubmit) { length = length - PHONE_SMSSubmit.Text; for (i = 0;i < buffer[PHONE_SMSSubmit.SMSCNumber]+1;i++) { req[current++]=buffer[PHONE_SMSSubmit.SMSCNumber+i]; } req[current++]=buffer[PHONE_SMSSubmit.firstbyte]; req[current++]=buffer[PHONE_SMSSubmit.TPMR]; for (i = 0;i<((buffer[PHONE_SMSSubmit.Number]+1)/2+1)+1;i++) { req[current++]=buffer[PHONE_SMSSubmit.Number+i]; } req[current++]=buffer[PHONE_SMSSubmit.TPPID]; req[current++]=buffer[PHONE_SMSSubmit.TPDCS]; req[current++]=buffer[PHONE_SMSSubmit.TPVP]; req[current++]=buffer[PHONE_SMSSubmit.TPUDL]; for(i = 0;i < length;i++) { req[current++]=buffer[PHONE_SMSSubmit.Text+i]; } req[current+1]='\0'; } return PyBytes_FromStringAndSize(req, current); } /* List of methods defined in the module */ static struct PyMethodDef gammu_methods[] = { {"Version", (PyCFunction)gammu_Version, METH_NOARGS, gammu_Version__doc__}, {"SetDebugFile", (PyCFunction)gammu_SetDebugFile, METH_VARARGS|METH_KEYWORDS, gammu_SetDebugFile__doc__}, {"SetDebugLevel", (PyCFunction)gammu_SetDebugLevel, METH_VARARGS|METH_KEYWORDS, gammu_SetDebugLevel__doc__}, {"LinkSMS", (PyCFunction)gammu_LinkSMS, METH_VARARGS|METH_KEYWORDS, gammu_LinkSMS__doc__}, {"DecodeSMS", (PyCFunction)gammu_DecodeSMS, METH_VARARGS|METH_KEYWORDS, gammu_DecodeSMS__doc__}, {"EncodeSMS", (PyCFunction)gammu_EncodeSMS, METH_VARARGS|METH_KEYWORDS, gammu_EncodeSMS__doc__}, {"DecodeVCARD", (PyCFunction)gammu_DecodeVCARD, METH_VARARGS|METH_KEYWORDS, gammu_DecodeVCARD__doc__}, {"EncodeVCARD", (PyCFunction)gammu_EncodeVCARD, METH_VARARGS|METH_KEYWORDS, gammu_EncodeVCARD__doc__}, {"DecodeVCS", (PyCFunction)gammu_DecodeVCS, METH_VARARGS|METH_KEYWORDS, gammu_DecodeVCS__doc__}, {"DecodeICS", (PyCFunction)gammu_DecodeICS, METH_VARARGS|METH_KEYWORDS, gammu_DecodeICS__doc__}, {"EncodeVCALENDAR", (PyCFunction)gammu_EncodeVCALENDAR, METH_VARARGS|METH_KEYWORDS, gammu_EncodeVCALENDAR__doc__}, {"EncodeICALENDAR", (PyCFunction)gammu_EncodeICALENDAR, METH_VARARGS|METH_KEYWORDS, gammu_EncodeICALENDAR__doc__}, {"EncodeVTODO", (PyCFunction)gammu_EncodeVTODO, METH_VARARGS|METH_KEYWORDS, gammu_EncodeVTODO__doc__}, {"EncodeITODO", (PyCFunction)gammu_EncodeITODO, METH_VARARGS|METH_KEYWORDS, gammu_EncodeITODO__doc__}, {"SaveRingtone", (PyCFunction)gammu_SaveRingtone, METH_VARARGS|METH_KEYWORDS, gammu_SaveRingtone__doc__}, #ifdef GSM_ENABLE_BACKUP {"SaveBackup", (PyCFunction)gammu_SaveBackup, METH_VARARGS|METH_KEYWORDS, gammu_SaveBackup__doc__}, {"ReadBackup", (PyCFunction)gammu_ReadBackup, METH_VARARGS|METH_KEYWORDS, gammu_ReadBackup__doc__}, {"SaveSMSBackup", (PyCFunction)gammu_SaveSMSBackup, METH_VARARGS|METH_KEYWORDS, gammu_SaveSMSBackup__doc__}, {"ReadSMSBackup", (PyCFunction)gammu_ReadSMSBackup, METH_VARARGS|METH_KEYWORDS, gammu_ReadSMSBackup__doc__}, #endif {"SMSCounter", (PyCFunction)gammu_SMSCounter, METH_VARARGS|METH_KEYWORDS, gammu_SMSCounter__doc__}, {"DecodePDU", (PyCFunction)gammu_DecodePDU, METH_VARARGS|METH_KEYWORDS, gammu_DecodePDU__doc__}, {"EncodePDU", (PyCFunction)gammu_EncodePDU, METH_VARARGS|METH_KEYWORDS, gammu_EncodePDU__doc__}, {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ }; /* Initialization function for the module (*must* be called initcore) */ static char gammu_module_documentation[] = "Module wrapping Gammu functions. Gammu is software for communication with GSM phones " "allowing work with most of data stored in them. Most of functionality is hidden in L{StateMachine} " "class which does all phone communication.\n\n" "This documentation describes python-gammu " GAMMU_VERSION ".\n\n" "This python-gammu has been compiled with Gammu " GAMMU_VERSION ".\n\n" "@var Errors: Mapping of text representation of errors to gammu error codes. Reverse to L{ErrorNumbers}.\n" "@var ErrorNumbers: Mapping of gammu error codes to text representation. Reverse to L{Errors}.\n" ; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "gammu", gammu_module_documentation, -1, gammu_methods, NULL, NULL, NULL, NULL }; PyObject * PyInit__gammu(void) { PyObject *module, *d; GSM_Debug_Info *di; /* Create the module and add the functions */ module = PyModule_Create(&moduledef); if (module == NULL) return NULL; DebugFile = NULL; d = PyModule_GetDict(module); if (PyType_Ready(&StateMachineType) < 0) return NULL; Py_INCREF(&StateMachineType); if (PyModule_AddObject(module, "StateMachine", (PyObject *)&StateMachineType) < 0) return NULL; /* SMSD object */ if (!gammu_smsd_init(module)) return NULL; /* Add some symbolic constants to the module */ /* Define errors */ if (!gammu_create_errors(d)) return NULL; /* Define data */ if (!gammu_create_data(d)) return NULL; /* Check for errors */ if (PyErr_Occurred()) { PyErr_Print(); Py_FatalError("Can not initialize module _gammu, see above for reasons"); } /* Reset debugging setup */ di = GSM_GetGlobalDebug(); GSM_SetDebugFileDescriptor(NULL, FALSE, di); GSM_SetDebugLevel("none", di); #if PY_MAJOR_VERSION >= 3 return module; #endif } /* * vim: expandtab sw=4 ts=4 sts=4: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/gammu/src/misc.c0000644000175000017500000000273100000000000016131 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #include "misc.h" #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif char *mystrncpy(char *dest, const char *src, size_t n) { strncpy(dest, src, n); dest[n] = 0; return dest; } PRINTF_STYLE(1, 2) int pyg_error(const char *format, ...) { va_list ap; int ret; printf("python-gammu: ERROR: "); va_start(ap, format); ret = vprintf(format, ap); va_end(ap); return ret; } PRINTF_STYLE(1, 2) int pyg_warning(const char *format, ...) { va_list ap; int ret; printf("python-gammu: WARNING: "); va_start(ap, format); ret = vprintf(format, ap); va_end(ap); return ret; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134699.0 python-gammu-3.2.4/gammu/src/smsd.c0000644000175000017500000001734300000000000016151 0ustar00nijelnijel/* * python-gammu - Phone communication libary, SMSD part * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ /* Python-gammu configuration */ #define PY_SSIZE_T_CLEAN /* Python includes */ #include /* Gammu includes */ #include #include /* Locales */ #include /* For locking */ #ifdef WITH_THREAD #include "pythread.h" #endif /* Convertors between Gammu and Python types */ #include "convertors.h" /* Error objects */ #include "errors.h" const char program_name[] = "python-gammu"; /* ----------------------------------------------------- */ /* Declarations for objects of type SMSD */ typedef struct { PyObject_HEAD GSM_SMSDConfig *config; } SMSDObject; /* ---------------------------------------------------------------- */ static char SMSD_MainLoop__doc__[] = "Runs SMS daemon."; static PyObject *Py_SMSD_MainLoop(SMSDObject * self, PyObject * args, PyObject * kwds) { GSM_Error error; int max_failures = 0; static char *kwlist[] = { "MaxFailures", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", kwlist, &max_failures)) return NULL; Py_BEGIN_ALLOW_THREADS error = SMSD_MainLoop(self->config, FALSE, max_failures); Py_END_ALLOW_THREADS if (!checkError(error, "SMSD_MainLoop")) return NULL; Py_RETURN_NONE; } static char SMSD_Shutdown__doc__[] = "Signals SMS daemon to stop."; static PyObject *Py_SMSD_Shutdown(SMSDObject * self, PyObject * args, PyObject * kwds) { GSM_Error error; if (!PyArg_ParseTuple(args, "")) return NULL; Py_BEGIN_ALLOW_THREADS error = SMSD_Shutdown(self->config); Py_END_ALLOW_THREADS if (!checkError(error, "SMSD_Shutdown")) return NULL; Py_RETURN_NONE; } static char SMSD_GetStatus__doc__[] = "Returns SMSD status."; static PyObject *Py_SMSD_GetStatus(SMSDObject * self, PyObject * args, PyObject * kwds) { GSM_Error error; GSM_SMSDStatus status; if (!PyArg_ParseTuple(args, "")) return NULL; Py_BEGIN_ALLOW_THREADS error = SMSD_GetStatus(self->config, &status); Py_END_ALLOW_THREADS if (!checkError(error, "SMSD_GetStatus")) return NULL; return Py_BuildValue("{s:s,s:s,s:s,s:i,s:i,s:i,s:i,s:i}", "Client", status.Client, "PhoneID", status.PhoneID, "IMEI", status.IMEI, "Sent", status.Sent, "Received", status.Received, "Failed", status.Failed, "BatterPercent", status.Charge.BatteryPercent, "NetworkSignal", status.Network.SignalPercent); } static char SMSD_InjectSMS__doc__[] = "Injects a message to the SMSD queue"; static PyObject *Py_SMSD_InjectSMS(SMSDObject * self, PyObject * args, PyObject * kwds) { GSM_MultiSMSMessage smsin; static char *kwlist[] = { "Message", NULL }; PyObject *value; GSM_Error error; char newid[200]; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyList_Type, &(value))) return NULL; if (!MultiSMSFromPython(value, &smsin)) return NULL; Py_BEGIN_ALLOW_THREADS error = SMSD_InjectSMS(self->config, &smsin, newid); Py_END_ALLOW_THREADS if (!checkError(error, "SMSD_InjectSMS")) return NULL; return Py_BuildValue("s", newid); } static struct PyMethodDef SMSD_methods[] = { {"MainLoop", (PyCFunction) Py_SMSD_MainLoop, METH_VARARGS | METH_KEYWORDS, SMSD_MainLoop__doc__}, {"Shutdown", (PyCFunction) Py_SMSD_Shutdown, METH_VARARGS | METH_KEYWORDS, SMSD_Shutdown__doc__}, {"GetStatus", (PyCFunction) Py_SMSD_GetStatus, METH_VARARGS | METH_KEYWORDS, SMSD_GetStatus__doc__}, {"InjectSMS", (PyCFunction) Py_SMSD_InjectSMS, METH_VARARGS | METH_KEYWORDS, SMSD_InjectSMS__doc__}, {NULL, NULL, 0, NULL} /* sentinel */ }; /* ---------- */ #if 0 static PyObject *SMSD_getattr(SMSDObject * self, char *name) { /* XXXX Add your own getattr code here */ return -1; // Py_FindMethod(SMSD_methods, (PyObject *)self, name); } static int SMSD_setattr(SMSDObject * self, char *name, PyObject * v) { /* Set attribute 'name' to value 'v'. v==NULL means delete */ /* XXXX Add your own setattr code here */ return -1; } #endif #if 0 static int SMSD_compare(SMSDObject * v, SMSDObject * w) { /* XXXX Compare objects and return -1, 0 or 1 */ } static PyObject *SMSD_repr(SMSDObject * self) { PyObject *s; /* XXXX Add code here to put self into s */ return s; } static PyObject *SMSD_str(SMSDObject * self) { PyObject *s; /* XXXX Add code here to put self into s */ return s; } #endif static void SMSD_dealloc(SMSDObject * self) { SMSD_FreeConfig(self->config); Py_TYPE(self)->tp_free((PyObject *) self); } static PyObject *SMSD_new(PyTypeObject * type, PyObject * args, PyObject * kwds) { SMSDObject *self; self = (SMSDObject *) type->tp_alloc(type, 0); self->config = SMSD_NewConfig(program_name); if (self->config == NULL) return NULL; return (PyObject *) self; } static int SMSD_init(SMSDObject * self, PyObject * args, PyObject * kwds) { char *s = NULL; static char *kwlist[] = { "Config", NULL }; GSM_Error error; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &s)) return -1; error = SMSD_ReadConfig(s, self->config, TRUE); if (!checkError(error, "SMSD_ReadConfig")) return -1; return 0; } static char SMSDType__doc__[] = "SMSD object, that is used for communication with phone."; static PyTypeObject SMSDType = { PyVarObject_HEAD_INIT(NULL, 0) "_gammu.SMSD", /*tp_name */ sizeof(SMSDObject), /*tp_basicsize */ 0, /*tp_itemsize */ /* methods */ (destructor) SMSD_dealloc, /*tp_dealloc */ (printfunc) 0, /*tp_print */ #if 0 (getattrfunc) SMSD_getattr, /*tp_getattr */ (setattrfunc) SMSD_setattr, /*tp_setattr */ #endif 0, /*tp_getattr */ 0, /*tp_setattr */ 0, #if 0 (cmpfunc) SMSD_compare, /*tp_compare */ #endif 0, #if 0 (reprfunc) SMSD_repr, /*tp_repr */ #endif 0, /*tp_as_number */ 0, /*tp_as_sequence */ 0, /*tp_as_mapping */ (hashfunc) 0, /*tp_hash */ (ternaryfunc) 0, /*tp_call */ 0, #if 0 (reprfunc) SMSD_str, /*tp_str */ #endif 0, /*tp_getattro */ 0, /*tp_setattro */ 0, /*tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags */ SMSDType__doc__, /* Documentation string */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SMSD_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc) SMSD_init, /* tp_init */ 0, /* tp_alloc */ SMSD_new, /* tp_new */ NULL, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ #ifdef Py_TPFLAGS_HAVE_FINALIZE 0, /* tp_finalize */ #endif }; /* End of code for SMSD objects */ /* -------------------------------------------------------- */ gboolean gammu_smsd_init(PyObject * m) { if (PyType_Ready(&SMSDType) < 0) return FALSE; Py_INCREF(&SMSDType); if (PyModule_AddObject(m, "SMSD", (PyObject *) & SMSDType) < 0) return FALSE; return TRUE; } /* * vim: noexpandtab sw=8 ts=8 sts=8: */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1635678883.0 python-gammu-3.2.4/gammu/worker.py0000644000175000017500000002415000000000000016125 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ Asynchronous communication to phone. Mostly you should use only L{GammuWorker} class, others are only helpers which are used by this class. """ import queue import threading import gammu class InvalidCommand(Exception): """ Exception indicating invalid command. """ def __init__(self, value): """ Initializes exception. @param value: Name of wrong command. @type value: string """ super().__init__() self.value = value def __str__(self): """ Returns textual representation of exception. """ return f'Invalid command: "{self.value}"' def check_worker_command(command): """ Checks whether command is valid. @param command: Name of command. @type command: string """ if hasattr(gammu.StateMachine, command): return raise InvalidCommand(command) class GammuCommand: """ Storage of single command for gammu. """ def __init__(self, command, params=None, percentage=100): """ Creates single command instance. """ check_worker_command(command) self._command = command self._params = params self._percentage = percentage def get_command(self): """ Returns command name. """ return self._command def get_params(self): """ Returns command params. """ return self._params def get_percentage(self): """ Returns percentage of current task. """ return self._percentage def __str__(self): """ Returns textual representation. """ if self._params is not None: return f"{self._command} {self._params}" else: return f"{self._command} ()" class GammuTask: """ Storage of taks for gammu. """ def __init__(self, name, commands): """ Creates single command instance. @param name: Name of task. @type name: string @param commands: List of commands to execute. @type commands: list of tuples or strings """ self._name = name self._list = [] self._pointer = 0 for i in range(len(commands)): if isinstance(commands[i], tuple): cmd = commands[i][0] try: params = commands[i][1] except IndexError: params = None else: cmd = commands[i] params = None percents = round(100 * (i + 1) / len(commands)) self._list.append(GammuCommand(cmd, params, percents)) def get_next(self): """ Returns next command to be executed as L{GammuCommand}. """ result = self._list[self._pointer] self._pointer += 1 return result def get_name(self): """ Returns task name. """ return self._name def gammu_pull_device(state_machine): state_machine.ReadDevice() class GammuThread(threading.Thread): """ Thread for phone communication. """ def __init__(self, queue, config, callback, pull_func=gammu_pull_device): """ Initialises thread data. @param queue: Queue with events. @type queue: queue.Queue object. @param config: Gammu configuration, same as L{StateMachine.SetConfig} accepts. @type config: hash @param callback: Function which will be called upon operation completing. @type callback: Function, needs to accept four params: name of completed operation, result of it, error code and percentage of overall operation. This callback is called from different thread, so please take care of various threading issues in other modules you use. """ super().__init__() self._kill = False self._terminate = False self._sm = gammu.StateMachine() self._callback = callback self._queue = queue self._sm.SetConfig(0, config) self._pull_func = pull_func def _do_command(self, name, cmd, params, percentage=100): """ Executes single command on phone. """ func = getattr(self._sm, cmd) error = "ERR_NONE" result = None try: if params is None: result = func() elif isinstance(params, dict): result = func(**params) else: result = func(*params) except gammu.GSMError as info: errcode = info.args[0]["Code"] error = gammu.ErrorNumbers[errcode] self._callback(name, result, error, percentage) def run(self): """ Thread body, which handles phone communication. This should not be used from outside. """ start = True while not self._kill: try: if start: task = GammuTask("Init", ["Init"]) start = False else: # Wait at most ten seconds for next command task = self._queue.get(True, 10) try: while True: cmd = task.get_next() self._do_command( task.get_name(), cmd.get_command(), cmd.get_params(), cmd.get_percentage(), ) except IndexError: try: if task.get_name() != "Init": self._queue.task_done() except (AttributeError, ValueError): pass except queue.Empty: if self._terminate: break # Read the device to catch possible incoming events try: self._pull_func(self._sm) except Exception as ex: self._callback("ReadDevice", None, ex, 0) def kill(self): """ Forces thread end without emptying queue. """ self._kill = True def join(self, timeout=None): """ Terminates thread and waits for it. """ self._terminate = True super().join(timeout) class GammuWorker: """ Wrapper class for asynchronous communication with Gammu. It spaws own thread and then passes all commands to this thread. When task is done, caller is notified via callback. """ def __init__(self, callback, pull_func=gammu_pull_device): """ Initializes worker class. @param callback: See L{GammuThread.__init__} for description. """ self._thread = None self._callback = callback self._config = {} self._lock = threading.Lock() self._queue = queue.Queue() self._pull_func = pull_func def enqueue_command(self, command, params): """ Enqueues command. @param command: Command(s) to execute. Each command is tuple containing function name and it's parameters. @type command: tuple of list of tuples @param params: Parameters to command. @type params: tuple or string """ self._queue.put(GammuTask(command, [(command, params)])) def enqueue_task(self, command, commands): """ Enqueues task. @param command: Command(s) to execute. Each command is tuple containing function name and it's parameters. @type command: tuple of list of tuples @param commands: List of commands to execute. @type commands: list of tuples or strings """ self._queue.put(GammuTask(command, commands)) def enqueue(self, command, params=None, commands=None): """ Enqueues command or task. @param command: Command(s) to execute. Each command is tuple containing function name and it's parameters. @type command: tuple of list of tuples @param params: Parameters to command. @type params: tuple or string @param commands: List of commands to execute. When this is not none, params are ignored and command is taken as task name. @type commands: list of tuples or strings """ if commands is not None: self.enqueue_task(command, commands) else: self.enqueue_command(command, params) def configure(self, config): """ Configures gammu instance according to config. @param config: Gammu configuration, same as L{StateMachine.SetConfig} accepts. @type config: hash """ self._config = config def abort(self): """ Aborts any remaining operations. """ raise NotImplementedError def initiate(self): """ Connects to phone. """ self._thread = GammuThread( self._queue, self._config, self._callback, self._pull_func ) self._thread.start() def terminate(self, timeout=None): """ Terminates phone connection. """ self.enqueue("Terminate") self._thread.join(timeout) self._thread = None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8703601 python-gammu-3.2.4/include/0000755000175000017500000000000000000000000014555 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/include/convertors.h0000644000175000017500000002431000000000000017132 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #ifndef __pyg_convertors_h__ #define __pyg_convertors_h__ /* Python includes */ #include /* Gammu includes */ #include #include #include "misc.h" /* Needed for Python 2.3, 2.4 has same included */ #ifndef Py_RETURN_NONE # define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif /** * Invalid value for gboolean. */ #define BOOL_INVALID ((gboolean)-1) /** * Invalid value for integer (possibly signed). */ #define INT_INVALID (INT_MAX) /** * Invalid value for enums (can not be negative). */ #define ENUM_INVALID (99999) /** * Creates Python datetime.datetime from GSM_DateTime. */ PyObject *BuildPythonDateTime(const GSM_DateTime * dt); /** * Creates Python datetime.time from GSM_DateTime. */ PyObject *BuildPythonTime(const GSM_DateTime * dt); /** * Creates GSM_DateTime from Python datetime.time. */ int BuildGSMDateTime(PyObject * pydt, GSM_DateTime * dt); /** * Creates GSM_DateTime from Python datetime.date. */ int BuildGSMDate(PyObject * pydt, GSM_DateTime * dt); /** * Creates GSM_DateTime from Python datetime.time. */ int BuildGSMTime(PyObject * pydt, GSM_DateTime * dt); /** * Convert Python unicode string to Gammu unicode string. */ unsigned char *strPythonToGammu(const Py_UNICODE * src, const size_t len); /** * Converts either object to unicode and returns its value. */ unsigned char *StringPythonToGammu(PyObject * o); /** * Convert Gammu unicode string to unicode string that can be read by Python. */ Py_UNICODE *strGammuToPython(const unsigned char *src); /** * Convert Gammu unicode string with defined length to unicode string that can be read by Python. */ Py_UNICODE *strGammuToPythonL(const unsigned char *src, const int len, size_t *out_len); /** * Convert Gammu unicode string to python unicode object. */ PyObject *UnicodeStringToPython(const unsigned char *src); /** * Convert Gammu unicode string with defined length to python unicode object. */ PyObject *UnicodeStringToPythonL(const unsigned char *src, const Py_ssize_t len); /** * Converts locale encoded string to python unicode string. */ PyObject *LocaleStringToPython(const char *src); /** * Converts string to CategoryType. */ GSM_CategoryType StringToCategoryType(const char *s); /** * Converts string to MemoryType. */ GSM_MemoryType StringToMemoryType(const char *s); /** * Converts MemoryType to string. */ char *MemoryTypeToString(const GSM_MemoryType t); /** * Builds Python object containing all GSM_MemoryEntry values. */ PyObject *MemoryEntryToPython(const GSM_MemoryEntry * entry); /** * Fills GSM_MemoryEntry from Pythons dictionary:. */ int MemoryEntryFromPython(PyObject * dict, GSM_MemoryEntry * entry, int needs_location); /** * Gets integer from dictionary dict with key key. */ int GetIntFromDict(PyObject * dict, const char *key); /** * Gets gboolean from dictionary dict with key key. */ gboolean GetBoolFromDict(PyObject * dict, const char *key); /** * Converts object to boolean value. It accepts boolean * objects, integers and strings (yes, no, true, false). */ gboolean BoolFromPython(PyObject * o, const char *key); /** * Returns C string with length from dictionary dict with key key. * * Returns newly allocated memory. */ char *GetCStringLengthFromDict(PyObject * dict, const char *key, Py_ssize_t * length); /** * Gets gammu unicode string from dictionary dict with key key. */ unsigned char *GetStringFromDict(PyObject * dict, const char *key); /** * Copies unicode string from Python dictionary to Gammu string with length checking */ int CopyStringFromDict(PyObject * dict, const char *key, size_t len, unsigned char *dest); /** * Gets GSM_DateTime from dictionary dict with key key. */ GSM_DateTime GetDateTimeFromDict(PyObject * dict, const char *key); /** * Gets GSM_DateTime from dictionary dict with key key. */ GSM_DateTime GetDateFromDict(PyObject * dict, const char *key); /** * Gets char* from dictionary dict with key key. (does allocate it!) */ char *GetCharFromDict(PyObject * dict, const char *key); /** * Gets char* with length (may contain NULs) from dictionary dict with key key. (doesn't allocate it!) */ char *GetDataFromDict(PyObject * dict, const char *key, Py_ssize_t * len); /** * Gets GSM_MemoryType from dictionary dict with key key. */ GSM_MemoryType GetMemoryTypeFromDict(PyObject * dict, const char *key); /** * Coverts cell broadcast message to Python object. */ PyObject *CBToPython(GSM_CBMessage * cb); /** * Coverts USSD message to Python object. */ PyObject *USSDToPython(GSM_USSDMessage * ussd); /** * Converts SMSValidity to string. */ char *SMSValidityToString(GSM_SMSValidity Validity); /** * Creates SMSValidity from string. */ GSM_SMSValidity StringToSMSValidity(char *s); /** * Converts SMSFormat to string. */ char *SMSFormatToString(GSM_SMSFormat f); /** * Converts string to SMSFormat. */ GSM_SMSFormat StringToSMSFormat(char *s); /** * Builds python object from GSM_SMSC. */ PyObject *SMSCToPython(GSM_SMSC * smsc); /** * Parses python object into GMS_SMSC. */ int SMSCFromPython(PyObject * dict, GSM_SMSC * smsc, gboolean complete); /** * Converts SMS to python object. */ PyObject *SMSToPython(GSM_SMSMessage * sms); /** * Creates SMS from python object. */ int SMSFromPython(PyObject * dict, GSM_SMSMessage * sms, int needslocation, int needsfolder, int needsnumber); /** * Converts MultiSMS to list of python object. */ PyObject *MultiSMSToPython(GSM_MultiSMSMessage * sms); /** * Converts MultiSMS from list of python objects. */ int MultiSMSFromPython(PyObject * list, GSM_MultiSMSMessage * sms); /** * Converts MultiSMS list from list of python objects. */ int MultiSMSListFromPython(PyObject * list, GSM_MultiSMSMessage *** sms); /** * Converts MultiSMS list to list of python objects. */ PyObject *MultiSMSListToPython(GSM_MultiSMSMessage ** sms); #ifdef GSM_ENABLE_BACKUP /** * Converts SMS backup to list of Python objects. */ PyObject *SMSBackupToPython(GSM_SMS_Backup * sms); /** * Converts SMS backup from list of Python objects. */ int SMSBackupFromPython(PyObject * list, GSM_SMS_Backup * sms); #endif /** * Converts Todo to Python object. */ PyObject *TodoToPython(const GSM_ToDoEntry * entry); /** * Converts Todo from Python object. */ int TodoFromPython(PyObject * dict, GSM_ToDoEntry * entry, int needs_location); /** * Convert calendar type to string. */ char *CalendarTypeToString(GSM_CalendarNoteType p); /** * Convert string to calendar type. */ GSM_CalendarNoteType StringToCalendarType(const char *s); /** * Converts Calendar to Python object. */ PyObject *CalendarToPython(const GSM_CalendarEntry * entry); /** * Converts Calendar from Python object. */ int CalendarFromPython(PyObject * dict, GSM_CalendarEntry * entry, int needs_location); /** * Converts SMSInfo to Python object. */ PyObject *SMSInfoToPython(GSM_MultiPartSMSInfo * smsinfo); /** * Converts SMSInfo from Python object. */ int SMSInfoFromPython(PyObject * dict, GSM_MultiPartSMSInfo * entry); /** * Converts Bitmap to Python object. */ PyObject *BitmapToPython(GSM_Bitmap * bitmap); /** * Converts multiple Bitmaps to list of Python objects. */ PyObject *MultiBitmapToPython(GSM_MultiBitmap * bmp); /** * Converts Bitmap from Python object. */ int BitmapFromPython(PyObject * data, GSM_Bitmap * bitmap); /** * Converts multiple Bitmaps from list of Python objects. */ int MultiBitmapFromPython(PyObject * list, GSM_MultiBitmap * bmp); /** * Converts SMS folders structure to list of Python objects. */ PyObject *SMSFoldersToPython(GSM_SMSFolders * folders); /** * Converts ringtone to Python object. */ PyObject *RingtoneToPython(GSM_Ringtone * ring); /** * Converts ringtone from Python object. */ int RingtoneFromPython(PyObject * dict, GSM_Ringtone * ring); #ifdef GSM_ENABLE_BACKUP /** * Converts backup to Python object. */ PyObject *BackupToPython(GSM_Backup * backup); /** * Converts backup from Python object. */ int BackupFromPython(PyObject * dict, GSM_Backup * backup); /** * Converts backup format from string to Gammu. */ int BackupFormatFromString(const char *s, GSM_BackupFormat * format); #endif /** * Converts file to Python object. */ PyObject *FileToPython(GSM_File * file); /** * Converts file from Python object. */ int FileFromPython(PyObject * dict, GSM_File * file, gboolean check); /** * Converts call to Python object. */ PyObject *CallToPython(GSM_Call * call); /** * Converts call type to Python object. */ char *CallStatusToString(GSM_CallStatus ct); /** * Converts MMS indicator to Python object. */ PyObject *MMSIndicatorToPython(GSM_MMSIndicator * mms); /** * Converts MMS indicator from Python object. */ int MMSIndicatorFromPython(PyObject * dict, GSM_MMSIndicator * mms); /** * Converts WAP bookmark to Python object. */ PyObject *WAPBookmarkToPython(GSM_WAPBookmark * wap); /** * Converts WAP bookmark from Python object. */ int WAPBookmarkFromPython(PyObject * dict, GSM_WAPBookmark * wap); /** * Converts UDH type string to value. */ GSM_UDH StringToUDHType(const char *s);; /** * Converts GSM coding string to value. */ GSM_Coding_Type StringToSMSCoding(const char *s); GSM_Divert_CallTypes DivertCallTypeFromString(const char *str); char *DivertCallTypeToString(GSM_Divert_CallTypes ct); GSM_Divert_DivertTypes DivertTypeFromString(const char *str); char *DivertTypeToString(GSM_Divert_DivertTypes ct); PyObject *CallDivertsToPython(GSM_MultiCallDivert *cd); #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/include/data.h0000644000175000017500000000173400000000000015644 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #ifndef __pyg_data_h__ #define __pyg_data_h__ #include #include int gammu_create_data(PyObject * d); #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/include/errors.h0000644000175000017500000000512700000000000016247 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #ifndef __pyg_errors_h__ #define __pyg_errors_h__ #include #include extern PyObject *GammuError; extern PyObject *PyERR_DEVICEOPENERROR; extern PyObject *PyERR_DEVICELOCKED; extern PyObject *PyERR_DEVICENOTEXIST; extern PyObject *PyERR_DEVICEBUSY; extern PyObject *PyERR_DEVICENOPERMISSION; extern PyObject *PyERR_DEVICENODRIVER; extern PyObject *PyERR_DEVICENOTWORK; extern PyObject *PyERR_DEVICEDTRRTSERROR; extern PyObject *PyERR_DEVICECHANGESPEEDERROR; extern PyObject *PyERR_DEVICEWRITEERROR; extern PyObject *PyERR_DEVICEREADERROR; extern PyObject *PyERR_DEVICEPARITYERROR; extern PyObject *PyERR_TIMEOUT; extern PyObject *PyERR_FRAMENOTREQUESTED; extern PyObject *PyERR_UNKNOWNRESPONSE; extern PyObject *PyERR_UNKNOWNFRAME; extern PyObject *PyERR_UNKNOWNCONNECTIONTYPESTRING; extern PyObject *PyERR_UNKNOWNMODELSTRING; extern PyObject *PyERR_SOURCENOTAVAILABLE; extern PyObject *PyERR_NOTSUPPORTED; extern PyObject *PyERR_EMPTY; extern PyObject *PyERR_SECURITYERROR; extern PyObject *PyERR_INVALIDLOCATION; extern PyObject *PyERR_NOTIMPLEMENTED; extern PyObject *PyERR_FULL; extern PyObject *PyERR_UNKNOWN; extern PyObject *PyERR_CANTOPENFILE; extern PyObject *PyERR_MOREMEMORY; extern PyObject *PyERR_PERMISSION; extern PyObject *PyERR_EMPTYSMSC; extern PyObject *PyERR_INSIDEPHONEMENU; extern PyObject *PyERR_NOTCONNECTED; extern PyObject *PyERR_WORKINPROGRESS; extern PyObject *PyERR_PHONEOFF; extern PyObject *PyERR_FILENOTSUPPORTED; extern PyObject *PyERR_BUG; extern PyObject *PyERR_CANCELED; extern PyObject *PyERR_NEEDANOTHERANSWER; extern PyObject *PyERR_OTHERCONNECTIONREQUIRED; extern PyObject *PyERR_WRONGCRC; extern PyObject *PyERR_INVALIDDATETIME; int checkError(GSM_Error error, const char *where); int gammu_create_errors(PyObject * d); #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1515144525.0 python-gammu-3.2.4/include/misc.h0000644000175000017500000000332000000000000015657 0ustar00nijelnijel/* * python-gammu - Phone communication libary * Copyright (C) 2003 - 2018 Michal Čihař * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * vim: expandtab sw=4 ts=4 sts=4: */ #ifndef __pyg_misc_h__ #define __pyg_misc_h__ /* Python includes */ #include /* PRINTF_STYLE definition */ #include #include #define STR1(x) #x #define STR(x) STR1(x) #define PYTHON_GAMMU_VERSION STR(PYTHON_GAMMU_MAJOR_VERSION) "." STR(PYTHON_GAMMU_MINOR_VERSION) #ifndef HAVE_STRCASECMP #ifdef HAVE_STRICMP #define strcasecmp _stricmp #endif #endif /** * Copies at most n chars from src to dest, dest will be \0 terminated. */ char *mystrncpy(char *dest, const char *src, size_t n); PRINTF_STYLE(1, 2) int pyg_warning(const char *format, ...); PRINTF_STYLE(1, 2) int pyg_error(const char *format, ...); /* Compatiblity with older python releases */ #if PY_VERSION_HEX < 0x02050000 typedef int Py_ssize_t; #define PY_FORMAT_SIZE_T "" #endif /** * Initialisation of SMSD object. */ gboolean gammu_smsd_init(PyObject * m); #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8703601 python-gammu-3.2.4/python_gammu.egg-info/0000755000175000017500000000000000000000000017333 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637135469.0 python-gammu-3.2.4/python_gammu.egg-info/PKG-INFO0000644000175000017500000001072200000000000020432 0ustar00nijelnijelMetadata-Version: 2.1 Name: python-gammu Version: 3.2.4 Summary: Gammu bindings Home-page: https://wammu.eu/python-gammu/ Author: Michal Cihar Author-email: michal@cihar.com License: GPLv2+ Download-URL: https://wammu.eu/download/python-gammu/ Keywords: mobile,phone,SMS,contact,gammu,calendar,todo Platform: Linux Platform: Mac OSX Platform: Windows XP/2000/NT Platform: Windows 95/98/ME Classifier: Development Status :: 6 - Mature Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Telecommunications Industry Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+) Classifier: Operating System :: MacOS Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: Unix Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Communications :: Telephony Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Hardware Requires-Python: >=3.6 Description-Content-Type: text/x-rst License-File: COPYING License-File: AUTHORS python-gammu ============ Python bindings for the `Gammu library `_. .. image:: https://github.com/gammu/python-gammu/actions/workflows/test.yml/badge.svg :target: https://github.com/gammu/python-gammu/actions/workflows/test.yml .. image:: https://api.codacy.com/project/badge/Grade/c7e87df480fb4609aa48482873f5c46b :target: https://www.codacy.com/app/Gammu/python-gammu .. image:: https://coveralls.io/repos/gammu/python-gammu/badge.svg :target: https://coveralls.io/r/gammu/python-gammu .. image:: https://scan.coverity.com/projects/4837/badge.svg :target: https://scan.coverity.com/projects/4837 .. image:: https://img.shields.io/liberapay/receives/Gammu.svg :alt: Liberapay :target: https://liberapay.com/Gammu/donate .. image:: https://www.bountysource.com/badge/team?team_id=23177&style=bounties_received :alt: Bountysource :target: https://www.bountysource.com/teams/gammu/issues?utm_source=Gammu&utm_medium=shield&utm_campaign=bounties_received .. image:: https://img.shields.io/pypi/v/python-gammu.svg :alt: PyPI :target: https://pypi.python.org/pypi/python-gammu/ Homepage ======== License ======= Copyright (C) 2003 - 2018 Michal Cihar This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Installing ========== You can install in a usual way for Python modules using distutils, so use ``setup.py`` which is placed in the top level directory:: ./setup.py build sudo ./setup.py install You can also install it using pip installer:: pip install python-gammu Requirements ============ To compile python-gammu, you need Gammu development files (usually shipped as ``libgammu-dev`` or ``gammu-devel`` in Linux distributions). The location of the libraries is discovered using ``pkg-config``, ``GAMMU_PATH`` environment variable and falls back to generic locations. In case it does not work, either install ``pkg-config`` or set ``GAMMU_PATH``. On Linux something like this should work:: GAMMU_PATH=/opt/gammu python setup.py build On Windows:: SET GAMMU_PATH="C:\Gammu" python setup.py build Documentation ============= Please see included python documentation:: >>> import gammu >>> help(gammu) Alternatively you can use Sphinx to generate browsable version, which is also available on-line at . Feedback and bug reports ======================== Any feedback is welcome, see for information how to contact developers. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637135469.0 python-gammu-3.2.4/python_gammu.egg-info/SOURCES.txt0000644000175000017500000000542200000000000021222 0ustar00nijelnijelAUTHORS COPYING MANIFEST.in NEWS.rst README.rst setup.cfg setup.py examples/__init__.py examples/addcontacts.py examples/addfile.py examples/async.py examples/backup_convertor.py examples/batteryinfo.py examples/debugging.py examples/dialvoice.py examples/doc-exceptions.py examples/dummy_phone.py examples/filesystem_test.py examples/getallcalendar.py examples/getallmemory.py examples/getallmemory_nonext.py examples/getallsms.py examples/getallsms_decode.py examples/getalltodo.py examples/getdiverts.py examples/incoming.py examples/listfilesystem.py examples/mass_sms.py examples/pdu_decoder.py examples/read_sms_backup.py examples/savesmspercontact.py examples/sendlongsms.py examples/sendsms.py examples/service_numbers.py examples/setdiverts.py examples/sms_replier.py examples/smsbackup.py examples/smsd_inject.py examples/smsd_state.py examples/vcs.py examples/worker.py examples/data/cgi.jpg gammu/__init__.py gammu/asyncworker.py gammu/data.py gammu/exception.py gammu/smsd.py gammu/worker.py gammu/src/data.c gammu/src/errors.c gammu/src/gammu.c gammu/src/misc.c gammu/src/smsd.c gammu/src/convertors/backup.c gammu/src/convertors/base.c gammu/src/convertors/bitmap.c gammu/src/convertors/calendar.c gammu/src/convertors/call.c gammu/src/convertors/diverts.c gammu/src/convertors/file.c gammu/src/convertors/memory.c gammu/src/convertors/misc.c gammu/src/convertors/ringtone.c gammu/src/convertors/sms.c gammu/src/convertors/string.c gammu/src/convertors/time.c gammu/src/convertors/todo.c gammu/src/convertors/wap.c include/convertors.h include/data.h include/errors.h include/misc.h python_gammu.egg-info/PKG-INFO python_gammu.egg-info/SOURCES.txt python_gammu.egg-info/dependency_links.txt python_gammu.egg-info/top_level.txt test/__init__.py test/test_asyncworker.py test/test_backup.py test/test_config.py test/test_data.py test/test_dummy.py test/test_errors.py test/test_sms.py test/test_smsd.py test/test_worker.py test/data/02.vcs test/data/UK32Holidays.ics test/data/bug-779.vcf test/data/gammu.vcf test/data/k770.vcs test/data/rrule.ics test/data/sqlite-14.sql test/data/sqlite-15.sql test/data/sqlite-16.sql test/data/sqlite-17.sql test/data/gammu-dummy/calendar/2 test/data/gammu-dummy/calendar/22 test/data/gammu-dummy/fs/file5 test/data/gammu-dummy/fs/dir2/file5 test/data/gammu-dummy/fs/dir2/dir2-5/file1 test/data/gammu-dummy/fs/dir2/dir2-5/file2 test/data/gammu-dummy/fs/dir2/dir2-5/file3 test/data/gammu-dummy/fs/dir2/dir2-5/file4 test/data/gammu-dummy/pbk/ME/1 test/data/gammu-dummy/pbk/ME/101 test/data/gammu-dummy/pbk/ME/103 test/data/gammu-dummy/pbk/SM/1 test/data/gammu-dummy/sms/1/1 test/data/gammu-dummy/sms/2/10 test/data/gammu-dummy/sms/3/42 test/data/gammu-dummy/sms/4/15 test/data/gammu-dummy/sms/4/20 test/data/gammu-dummy/sms/4/21 test/data/gammu-dummy/todo/22 test/data/gammu-dummy/todo/3././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637135469.0 python-gammu-3.2.4/python_gammu.egg-info/dependency_links.txt0000644000175000017500000000000100000000000023401 0ustar00nijelnijel ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637135469.0 python-gammu-3.2.4/python_gammu.egg-info/top_level.txt0000644000175000017500000000000600000000000022061 0ustar00nijelnijelgammu ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8783603 python-gammu-3.2.4/setup.cfg0000644000175000017500000000027100000000000014753 0ustar00nijelnijel[isort] multi_line_output = 3 include_trailing_comma = True force_grid_wrap = 0 use_parentheses = True line_length = 88 known_first_party = gammu [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1637134944.0 python-gammu-3.2.4/setup.py0000755000175000017500000002013300000000000014646 0ustar00nijelnijel#!/usr/bin/env python # vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # """ python-gammu - Phone communication libary """ import codecs import glob import os import platform import subprocess import sys from distutils.version import StrictVersion from setuptools import Extension, setup # some defines VERSION = "3.2.4" GAMMU_REQUIRED = "1.37.90" # readme THIS_DIRECTORY = os.path.abspath(os.path.dirname(__file__)) README_FILE = os.path.join(THIS_DIRECTORY, "README.rst") with open(README_FILE, encoding="utf-8") as readme: LONG_DESCRIPTION = readme.read() class GammuConfig: def __init__(self): self.on_windows = platform.system() == "Windows" self.has_pkgconfig = self.check_pkconfig() self.has_env = "GAMMU_PATH" in os.environ self.path = self.lookup_path() self.use_pkgconfig = self.has_pkgconfig and not self.has_env def check_pkconfig(self): try: subprocess.check_output(["pkg-config", "--help"]) return True except (subprocess.CalledProcessError, OSError): return False def config_path(self, base): return os.path.join(base, "include", "gammu", "gammu-config.h") def lookup_path(self): if self.has_env: paths = [os.environ["GAMMU_PATH"]] elif self.on_windows: paths = [ "C:\\Gammu", "C:\\Program Files\\Gammu", "C:\\Program Files (x86)\\Gammu", ] paths += glob.glob("C:\\Program Files\\Gammu*") paths += glob.glob("C:\\Program Files (x86)\\Gammu*") else: paths = ["/usr/local/", "/usr/"] paths += glob.glob("/opt/gammu*") for path in paths: include = self.config_path(path) if os.path.exists(include): return path def check_version(self): if self.use_pkgconfig: try: subprocess.check_output( [ "pkg-config", "--print-errors", f"--atleast-version={GAMMU_REQUIRED}", "gammu", "gammu-smsd", ] ) return except subprocess.CalledProcessError: print("Can not find supported Gammu version using pkg-config!") sys.exit(100) if self.path is None: print("Failed to find Gammu!") print("Either it is not installed or not found.") print("After install Gammu ensure that setup finds it by any of:") print(" * Specify path to it using GAMMU_PATH in environment.") print(" * Install pkg-config.") sys.exit(101) version = None with open(self.config_path(self.path)) as handle: for line in handle: if line.startswith("#define GAMMU_VERSION "): version = line.split('"')[1] if version is None or StrictVersion(version) < StrictVersion(GAMMU_REQUIRED): print("Too old Gammu version, please upgrade!") sys.exit(100) def get_libs(self): if self.use_pkgconfig: output = subprocess.check_output( ["pkg-config", "--libs-only-l", "gammu", "gammu-smsd"] ).decode("utf-8") return output.replace("-l", "").strip().split() libs = ["Gammu", "gsmsd"] if self.on_windows: libs.append("Advapi32") libs.append("shfolder") libs.append("shell32") else: libs.append("m") return libs def get_cflags(self): if self.use_pkgconfig: return ( subprocess.check_output( ["pkg-config", "--cflags", "gammu", "gammu-smsd"] ) .decode("utf-8") .strip() ) return "-I{}".format(os.path.join(self.path, "include", "gammu")) def get_ldflags(self): if self.use_pkgconfig: return ( subprocess.check_output( ["pkg-config", "--libs-only-L", "gammu", "gammu-smsd"] ) .decode("utf-8") .strip() ) elif self.on_windows: return "/LIBPATH:{}".format(os.path.join(self.path, "lib")) return "-L{}".format(os.path.join(self.path, "lib")) def get_module(): config = GammuConfig() config.check_version() module = Extension( "gammu._gammu", define_macros=[ ("PYTHON_GAMMU_MAJOR_VERSION", VERSION.split(".")[0]), ("PYTHON_GAMMU_MINOR_VERSION", VERSION.split(".")[1]), ], libraries=config.get_libs(), include_dirs=["include/"], sources=[ "gammu/src/errors.c", "gammu/src/data.c", "gammu/src/misc.c", "gammu/src/convertors/misc.c", "gammu/src/convertors/string.c", "gammu/src/convertors/time.c", "gammu/src/convertors/base.c", "gammu/src/convertors/sms.c", "gammu/src/convertors/memory.c", "gammu/src/convertors/todo.c", "gammu/src/convertors/calendar.c", "gammu/src/convertors/bitmap.c", "gammu/src/convertors/ringtone.c", "gammu/src/convertors/backup.c", "gammu/src/convertors/file.c", "gammu/src/convertors/call.c", "gammu/src/convertors/wap.c", "gammu/src/convertors/diverts.c", "gammu/src/gammu.c", "gammu/src/smsd.c", ], ) flags = config.get_cflags() if flags: module.extra_compile_args.append(flags) flags = config.get_ldflags() if flags: module.extra_link_args.append(flags) return module setup( name="python-gammu", version=VERSION, description="Gammu bindings", long_description=LONG_DESCRIPTION, long_description_content_type="text/x-rst", author="Michal Cihar", author_email="michal@cihar.com", platforms=["Linux", "Mac OSX", "Windows XP/2000/NT", "Windows 95/98/ME"], keywords=["mobile", "phone", "SMS", "contact", "gammu", "calendar", "todo"], license="GPLv2+", url="https://wammu.eu/python-gammu/", download_url="https://wammu.eu/download/python-gammu/", classifiers=[ "Development Status :: 6 - Mature", "Intended Audience :: Developers", "Intended Audience :: Telecommunications Industry", "License :: OSI Approved :: " "GNU General Public License v2 or later (GPLv2+)", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: C", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Communications :: Telephony", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Hardware", ], python_requires=">=3.6", test_suite="test", packages=["gammu"], ext_modules=[get_module()], ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/0000755000175000017500000000000000000000000014111 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534398.0 python-gammu-3.2.4/test/__init__.py0000644000175000017500000000155400000000000016227 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/0000755000175000017500000000000000000000000015022 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/02.vcs0000644000175000017500000000045700000000000015766 0ustar00nijelnijelBEGIN:VCALENDAR VERSION:1.0 BEGIN:VTODO SUMMARY:Gorusme DESCRIPTION: X-IRMC-LUID:00010001005E CLASS:PUBLIC DUE: COMPLETED: LAST-MODIFIED:20080312T115041Z DALARM:20080312T141000Z AALARM:20080312T141000Z CATEGORIES:MISCELLANEOUS PRIORITY:2 STATUS:NEEDS ACTION X-SONYERICSSON-DST:0 END:VTODO END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533940.0 python-gammu-3.2.4/test/data/UK32Holidays.ics0000644000175000017500000003300600000000000017705 0ustar00nijelnijelBEGIN:VCALENDAR VERSION:2.0 X-WR-CALNAME:UK Holidays PRODID:-//Apple Computer\, Inc//iCal 2.0//EN X-WR-RELCALID:2D7ED899-1693-4485-9C0C-1151808A6778 X-WR-TIMEZONE:America/Detroit CALSCALE:GREGORIAN METHOD:PUBLISH BEGIN:VEVENT SUMMARY:Boxing Day DTSTART;VALUE=DATE:20021226 DTEND;VALUE=DATE:20021227 UID:DECC1D87-B635-4EF8-B464-2F3812CD4620 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=12 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020214 DTEND;VALUE=DATE:20020215 SUMMARY:Valentine's Day UID:A4ABF8EC-9857-4D07-96A4-5D4BC9705E10 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20100104 DTEND;VALUE=DATE:20100105 SUMMARY:Bank Holiday (Scotland) UID:FB7ECC22-FCF2-47E6-9302-6406CFC93C87 SEQUENCE:3 DTSTAMP:20060123T214307Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20080324 DTEND;VALUE=DATE:20080325 SUMMARY:Easter Monday UID:88B5EBFA-E9B7-48B0-A29C-EF2CB5336AB2 SEQUENCE:3 DTSTAMP:20060123T215730Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060102 DTEND;VALUE=DATE:20060103 SUMMARY:2nd January (Scotland) UID:CD23A318-22D9-48D9-883A-CB043260A52D DTSTAMP:20060123T213943Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=1 SEQUENCE:1 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050103 SUMMARY:New Year's Day (observed) UID:9DD86A12-52CE-4DE1-879A-2C1820FFA796 DTSTAMP:20040707T141033Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060103 DTEND;VALUE=DATE:20060104 SUMMARY:Bank Holiday (Scotland) UID:B5969C4A-5863-495D-85A0-B16573C213C9 SEQUENCE:3 DTSTAMP:20060123T214036Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20100404 DTEND;VALUE=DATE:20100405 SUMMARY:Easter UID:EEE3637D-0BD2-43E8-AF05-E7FF41032700 SEQUENCE:3 DTSTAMP:20060123T220456Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20051227 SUMMARY:Bank Holiday UID:0B125525-42D7-42BD-9E57-0DF8DCE7E2CD DTSTAMP:20040707T141446Z SEQUENCE:1 DESCRIPTION:Substitute in lieu of the 25th DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020213 DTEND;VALUE=DATE:20020214 SUMMARY:Ash Wednesday UID:DCEB803C-E0FD-43F2-9B09-EC3127A87EAE DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20091228 DTEND;VALUE=DATE:20091229 SUMMARY:Bank Holiday UID:CCF9E9C6-8DDC-4B27-BBAD-C1E2D5176A56 SEQUENCE:3 DTSTAMP:20060123T215020Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020805 DTEND;VALUE=DATE:20020806 SUMMARY:Holiday (Scotland) UID:84AAB264-45B2-4F2B-9485-BE52D9F1AB22 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=1MO END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030421 DTEND;VALUE=DATE:20030422 SUMMARY:Easter Monday UID:1B6E4D5C-A601-4FAD-8405-52A8904C2A15 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030305 DTEND;VALUE=DATE:20030306 SUMMARY:Ash Wednesday UID:C97F751C-028B-44DC-BC80-B7167F3C66F6 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020423 DTEND;VALUE=DATE:20020424 SUMMARY:St. George's Day UID:A644107D-5C6B-46C5-8D4F-CEF4A079A34B DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=4 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20090410 DTEND;VALUE=DATE:20090411 SUMMARY:Good Friday UID:C399C5AE-6F0D-46D0-BF40-9D623BCF2BC1 SEQUENCE:3 DTSTAMP:20060124T193249Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20100402 DTEND;VALUE=DATE:20100403 SUMMARY:Good Friday UID:3F5193D3-B5B9-4892-8FE6-28121B9EDBA3 SEQUENCE:3 DTSTAMP:20060124T193311Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20070409 SUMMARY:Easter Monday UID:30D5700D-FC88-4616-BF0D-C7BE70249624 DTSTAMP:20040707T141722Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20070408 SUMMARY:Easter UID:B52B4CE9-0252-468B-B890-41E72905CD10 DTSTAMP:20040707T141714Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20090412 DTEND;VALUE=DATE:20090413 SUMMARY:Easter UID:1468D97A-D54F-44A6-902B-F420FA7CA325 SEQUENCE:3 DTSTAMP:20060123T220407Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060828 DTEND;VALUE=DATE:20060829 SUMMARY:Late Summer Holiday (excl. Scotland) UID:C3C32F32-A01F-4732-948C-8B657E1806A2 DTSTAMP:20060123T213752Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=-1MO END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020616 DTEND;VALUE=DATE:20020617 SUMMARY:Father's Day UID:66D8AB1E-6805-4D64-8877-0B54EA1BDCC7 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=6;BYDAY=3SU END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040412 SUMMARY:Easter Monday UID:E02D75F4-4F0E-45CC-98AF-86228D97B270 DTSTAMP:20040707T140556Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020527 DTEND;VALUE=DATE:20020528 SUMMARY:Spring Holiday UID:47D440C5-A756-45EA-97D9-7FE12BCB2EC3 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=-1MO END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20100405 DTEND;VALUE=DATE:20100406 SUMMARY:Easter Monday UID:8460414D-B206-4246-95DA-2E1254708F51 SEQUENCE:3 DTSTAMP:20060123T220503Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020506 DTEND;VALUE=DATE:20020507 SUMMARY:May Day UID:94179571-8968-49F8-ABAE-28E6EFE117C3 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20040502;BYMONTH=5;BYDAY=1MO END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040411 SUMMARY:Easter UID:2D7ADDBF-E2DB-45F8-9C7F-4DF31A39E53F DTSTAMP:20040707T140551Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20041227 DTEND;VALUE=DATE:20041229 SUMMARY:Bank Holiday UID:34226208-02F0-40C2-BB47-AC26B59A2261 DTSTAMP:20040707T140840Z SEQUENCE:2 DESCRIPTION:Substitute Bank Holiday in lieu of the 25th and 26th END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20080323 DTEND;VALUE=DATE:20080324 SUMMARY:Easter UID:503B2E9C-1C04-4F88-AF67-F065363F9482 SEQUENCE:3 DTSTAMP:20060123T215746Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20101228 DTEND;VALUE=DATE:20101229 SUMMARY:Bank Holiday UID:E88095AD-2C5D-421D-8EDA-9C11AB9FA6E5 SEQUENCE:3 DTSTAMP:20060123T215122Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060102 DTEND;VALUE=DATE:20060103 SUMMARY:Bank Holiday (Great Britain\, Wales\, N. Ireland) UID:8BEBC56D-EEDB-48B0-80B6-3C300AA13B9B SEQUENCE:3 DTSTAMP:20060123T214020Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020826 DTEND;VALUE=DATE:20020827 SUMMARY:Late Summer Holiday\, excl Scotland UID:9030F903-C1AD-40BC-B298-D7947CBDF419 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20060827;BYMONTH=8;BYDAY=-1MO END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20021105 DTEND;VALUE=DATE:20021106 SUMMARY:Guy Fawkes Day UID:9CDC8BAE-710A-4277-A1CB-9CFF31396CB8 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=11 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20021111 DTEND;VALUE=DATE:20021112 SUMMARY:Remembrance Day UID:109B7FA7-EABF-4E68-8EFE-0AE80A504AE1 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=11 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020401 DTEND;VALUE=DATE:20020402 SUMMARY:Easter Monday UID:5F9C76E6-DCF1-466C-B778-744FBB51CE40 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030420 DTEND;VALUE=DATE:20030421 SUMMARY:Easter UID:83FB0916-E13C-4690-8C18-08FF300C12EE DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060417 SUMMARY:Easter Monday UID:4809AA67-9909-4161-BC73-E68720AF6502 DTSTAMP:20040707T141533Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20070406 SUMMARY:Good Friday UID:429543DD-DB2E-42AF-8A53-FB778AB120F4 DTSTAMP:20040707T141706Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20090713 DTEND;VALUE=DATE:20090714 SUMMARY:Bank Holiday (N. Ireland) UID:D49DECA4-0690-4428-B20A-BBB9CC174A1A SEQUENCE:3 DTSTAMP:20060123T214823Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030304 DTEND;VALUE=DATE:20030305 SUMMARY:Shrove Tuesday UID:87C87924-A155-4213-A78B-C3BED059BA15 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20021130 DTEND;VALUE=DATE:20021201 SUMMARY:St. Andrew's Day UID:80B9C8F4-52D5-4D92-9A02-37BB2C1A83AD DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=11 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020331 DTEND;VALUE=DATE:20020401 SUMMARY:Easter UID:C7B19B3C-8DAC-46CE-84BF-C743ED5C1E33 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20090413 DTEND;VALUE=DATE:20090414 SUMMARY:Easter Monday UID:2128AEEF-3E61-439A-8EC4-08937E74944B SEQUENCE:3 DTSTAMP:20060123T220415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050325 SUMMARY:Good Friday UID:8C4BC261-CE58-4674-B642-A5BC4A9B8FAC DTSTAMP:20040707T141107Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20080714 DTEND;VALUE=DATE:20080715 SUMMARY:Bank Holiday (N. Ireland) UID:51511457-1EFC-4AF4-8600-A85B7EA7789F SEQUENCE:3 DTSTAMP:20060123T214748Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20070319 DTEND;VALUE=DATE:20070320 SUMMARY:Bank Holiday (N. Ireland) UID:6EF2BC68-4AA2-4DFB-BB98-9F36E911101C SEQUENCE:3 DTSTAMP:20060123T214454Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20021225 DTEND;VALUE=DATE:20021226 SUMMARY:Christmas Day UID:9B63338E-33C8-4787-ADAB-998D48E015E0 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=12 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20010421 DTEND;VALUE=DATE:20010422 SUMMARY:Queen's Birthday UID:77FF4144-B980-412A-B7D1-3C247B0DD092 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=4 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060414 SUMMARY:Good Friday UID:0DED9FF4-0142-4D2A-83B9-E7697A643CFF DTSTAMP:20040707T141515Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030330 DTEND;VALUE=DATE:20030331 SUMMARY:Mother's Day UID:DE0E412D-CF91-4716-B86D-2ECD4F585DE7 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20021027 DTEND;VALUE=DATE:20021028 SUMMARY:British Summer Time Ends UID:D6228FCC-94EF-49A9-9E11-7B1441EA8353 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=-1SU END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020102 DTEND;VALUE=DATE:20020103 SUMMARY:Bank Holiday (Scotland) UID:CCB51280-17A7-476E-8F16-F2935FBDFAD4 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20060101;BYMONTH=1 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20080321 DTEND;VALUE=DATE:20080322 SUMMARY:Good Friday UID:8B46A824-6871-4A10-ACDC-2B0D5E30F60F SEQUENCE:3 DTSTAMP:20060124T193156Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020329 DTEND;VALUE=DATE:20020330 SUMMARY:Good Friday UID:A425E020-1111-4353-963D-F1C19625087A DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040409 DTEND;VALUE=DATE:20040410 SUMMARY:Good Friday UID:F3DECE54-E0D4-4712-98F5-C8FB69A97D36 SEQUENCE:2 DTSTAMP:20040707T140535Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050328 SUMMARY:Easter Monday UID:5A7D8DF4-936B-4EEC-B0CF-1E92A133DC61 DTSTAMP:20040707T141143Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020101 DTEND;VALUE=DATE:20020102 SUMMARY:New Year's Day UID:861380A2-6403-495B-B585-4CCA38DCA82D DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=1 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20101227 DTEND;VALUE=DATE:20101228 SUMMARY:Bank Holiday UID:D3427758-94D7-44D3-80D0-8EFB2485BEB0 SEQUENCE:3 DTSTAMP:20060123T215112Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030418 DTEND;VALUE=DATE:20030419 SUMMARY:Good Friday UID:E6EB0E7D-8416-422D-9888-BBAF314EC7B1 DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020331 DTEND;VALUE=DATE:20020401 SUMMARY:British Summer Time UID:A11CC9A6-2BBB-40C4-80BF-2981F82791E5 DTSTAMP:20040707T141125Z RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20050326;BYMONTH=3;BYDAY=-1SU SEQUENCE:1 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20060416 SUMMARY:Easter UID:4936E52C-98D4-4B44-9DF3-48836AE8C2CA DTSTAMP:20040707T141522Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20021031 DTEND;VALUE=DATE:20021101 SUMMARY:Halloween UID:42D1B24F-21F9-46D0-B4A2-57122C3460A8 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020712 DTEND;VALUE=DATE:20020713 SUMMARY:Battle of Boyne Day (N. Ireland) UID:AE334EA1-87AA-4E81-84FD-51FFD2E0D456 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=7 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050327 SUMMARY:Easter UID:8C81BBA6-7ECD-45CC-8E9E-D8E583DEC3F8 DTSTAMP:20040707T141149Z SEQUENCE:1 DURATION:P1D END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020310 DTEND;VALUE=DATE:20020311 SUMMARY:Mother's Day UID:5C1382F0-0FD3-4DEC-AF82-EA74B2D4345C DTSTAMP:20040707T140415Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040503 DTEND;VALUE=DATE:20040504 SUMMARY:May Day UID:07FEF6DE-9781-4466-A15C-A02551A3AA7E DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO DESCRIPTION:Early May Bank Holiday END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020317 DTEND;VALUE=DATE:20020318 SUMMARY:St. Patrick's Day (N. Ireland) UID:1E29D9CC-AD09-4C4F-8EBF-EDAE695952C2 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020301 DTEND;VALUE=DATE:20020302 SUMMARY:St. David's Day UID:5B2EAA03-37B0-43C7-AB43-1F4CC705C684 DTSTAMP:20040707T140415Z RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20020212 DTEND;VALUE=DATE:20020213 SUMMARY:Shrove Tuesday UID:3B696187-0973-4B52-A487-3C2532B8280A DTSTAMP:20040707T140415Z END:VEVENT END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/bug-779.vcf0000644000175000017500000001537300000000000016634 0ustar00nijelnijelBEGIN:VCARD VERSION:2.1 N:DECHAMBRE;Christelle TEL;CELL:+33685733244 EMAIL;INTERNET;PREF:christelle.dechambre@intervet.com EMAIL;INTERNET: EMAIL;INTERNET: X-IRMC-LUID:00020000001B PHOTO;ENCODING=BASE64;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgGBgcGBQgH BwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDI BCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMv/AABEIAHgAoAMBIgACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGB wgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNi coIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4S FhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5e bn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEB AABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkq NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZq io6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2g AMAwEAAhEDEQA/APIuFB65HGKnuCTAjgZyVJ/EUSyWvmsykjJyMnvn/wDXSSyq9q23IwAc/QmuR 66j6kQJ3YXGfeo3gYhm8xOecZp1sj3MoRZDnB60pmeNtvmHIFA4s6LQ8/2WgPUEitBunFUNCmae 0cu24h8fpWiy5AHeu+n8CMJfEzBvcTatbo33YwXNOWQysJjy80m0H0Wo79hHd3TqeVURqfrVqwh 3T2ybSQibsD/P0rKpKyZW9izEf+JgrAf8tVUfQV17r+69siuVWBoZLfzflYvk/nXerZbLUz5DKS FHY85xxXBUZtFGWkJ8sPjgnAqRVI4xWreWrQWqwrAxI53AE7vp7Vz+qXV7Z2yyW9sC3JIlUgfhU RethyiaIGafsDDkcVxaeJteZ8Lptufm28bv8a7fT0mls0a5CLMfvqnRT6VuotmT0I/ssJ6xJ+Qo +yQcfuk/75FXvJ9MEUogB69fanyyM20Zxs7fvDGf+AimNYWxHNvGf+AitZ4IkTc5IHuarv5bRF0 zjdjJpuMkTcypNNsyObaL/vgVALS3t93kxKhPUqMZrSk5qpN0PrUNva4zyRYAZVV2IB6kdqtCJl DoQpiC/K2eTTjNpe7Ja4P0QH+ZqrNcRmU+RvMXbfwf0JrTmR0WbLWmiJNUVpsCMg9/aopYFMzuJ B9BzVXcM9BS7h2UVF9blqmzpPDYVIZl35OQeePWtp1BU4ZTz0Brg1YA5Kg1IkzIcx/K3qOtbxxK irWE8PJ63Na5tDPOdrokfmknLDoBgV01p9hhIdZowxGPvVw6+e5B2sx9dua9G+H2gR3SS6lfRMw g+aONl2gsP8j/ADmsKuIuaRw9tWWb/SbW1jhub66EchG9IVGWx6n0rrPAlzBcXXmXEEZcnERlVc Z9juzn8K4bWNH1y/upr27tpPLY5Pyfdz061peEr/7Es9lfW7PZvgMjLh4z6j/PpXI582pr7Kx3H jfXZdGJb95BIBlSUDRkfUcj8Qa80PjmbUHa3uyjRvwyrzkexxg/Qium8TyXP9lzW6y/bI4EEyI5 OWjP8SHqCM9umMdxjx24gjeTfbykZ+ZWHDIffH8xVQtLUzcbHSPqsVtfLm2SWAnH7o4OO3XmvRY DbW9rBl2WSdQ4V8bjmvDRfzBys3EinDHoa6XSvE0ge1jumkligwEDNnaPbPb2rdJx2MZJM9SkgM uCH2/QVLFD5aYJyPXpUNnNBd2YngXep6EKKuiP5QQNn4Ct7nO0RTIjJhipHvzVK5AFuQCOCMADp WjMQpGXNUbxZPKlyy7cdNvP55ob0ZHUzHPGapTHjmrDNxVO4brzWC1LZxn9g2ajLdPdqlXQbUYJ iyPxreVYScZGenSnyRcAA4IbPSup0bDVVsxF0SzH/LFfyqdNJsh/ywjP/ABWsI3I27xz35FRC38 sfu0UFiSSD1/Sp9jfqUqrKyaXbD7sKj/gIFTizjQ4EfFTCQqfmDDBxUr58suP1FROhNK5caibsR x2yg/6tcfWu0jZ9P8AAxuLdP3hkxhfXoK5OF9/8Nd/4RNvdabNY3eBGrrLlugAPJ/lXFVTcTqpt KWp6JaWSjTIYLhA7eWokzzlsc/rWVq/hKy1HdIpMMhxllUdq1rTUba9P+jXMNwn96JwcUy41W3h uhbNuZzxtXrmrrey5bR3KoKpz67HCXvhnyYJUE24qpEb4wV9vpXi2taSsV6+xBEzklB2Vu6/Sve PGdxd2NjJcpCEXqMyDIrxbW9Qt72ed3UhJ/mH+y3cf59K5INxlodNWCkrnDX0G6QuF2OOo9PY0W P3lOBx2rQhZZ55oZQGdc/N3YVQh2iR4xyp6V3p6WPPaPV/Bd0t1AUiYRsgw6Acfj712LRgoN434 NcT4Btw0RuCFLbTG3y8/wD167oKPLO1dv4VpHY55rUhkXaFCjbx025rPu0TMh2MWwTnHtWlPtCg vlvoM1TlUyZ2napXptqjJo5hnxmqNxJwealmfaWz2rNupwqk5rGBo0SICJio6Y6ircgzNgdCM1U z/pSN0J49aulQ0kROfu44FerNaHPEcsZ3j2FOSI4HHNO2c8BiMVIsJAwGx+FQWiAW7NkOoxnPFO uUxanHUnFTpCy/xZFJdD5Il7lqmq7U2aQXvIZaxbUFdh4JQzeIIYiA0ZVtwPIIx0rlEIB2jiup8 E3SW3iW339JA0f4kcV5zS6nWrs9PFhZWmJ47dE8oEjaMY+leSaPe3Hiv4lSvLNLHboT8kTlQQOB Xqiyz3OmXUzoSHDeVGo5wOB+deBQDxDoPiAana6beQzpIeDE21gTyD7VhLVrsehhoWjJN67Hqvi XwNa3NtLKuo3VvHj5l8wsp/A8GvC9dsY4FuYIpDKiN8rGvoDxBqY1Dwet9GkkPmRbij8MhxyDXh MiJPHIvciocrSKjT9xX3Oc060xc2c8rkfaN0WTxhv84rNjsZZbx1T5XQ/1q7qdz5L2UILAQtv/A B/yKXT7lJNTYvkFuAPWumN3r3OColE9J8K6mmn6d5ciF5z1BYAfnWy3iOQKytYAL2Ik3A/XjiuH jcMODVldQngXrvHo1bum1szi503qbFz4p1ESbI7W3RM9TmiXX7poQQwL4GVRe/sazU1V5BloBjO M7jj+VPa+jIOQv/fX+IrN8w7rsV7lnYs+CT9KwNRuNkbDoau3Ou3EUhWO2sQP78l4CPyABqn4lu FfTbEkwtLKWJeJSBjjpnkjmnFWFe5rvON6MApGcEkZxRczNiF1dlGSPlYj+VODKrZAAP0qG+fdb g+jA16VW/IzGG5ZS4fA/eSH6ualWd8ffbP1rKEvyipFuMdTXC2zpSRqCd8ffb86UzbipLFivTNZ v2oetIboAE5/Gpbb0KSRsrKOuavWlw9vPHPG2HjYMPqK46bV9hCxjc3tXomkaTFpGiLrOvvGN4B RGPyICON3qfapcS1Kx6rpuopqum299acBj+8jz0PcfnXO+LmmU7ReSoTjZlFI79up5xWL4I+Idj e66+liJILSRR5MuNoaT0x2BHT6V2/iG70/T7Fru/KqiDI9WPoK560OWCsduGnedmjFsbeNPCN62 pztcAISS4CgcdgOleEhsTSlfujOMVveIPFmoat51tblobKQ8pnrj1rjdRvvs0JghOW/iNYxi2dU pWuc7rVwf7QIYgn26CrejSwzyfZ24nZl8lvQ56Vg3DtJcMzHJzSJvJJUH8K9KMEopHj1J3k2ex3 NnCE3yssbAffBwf8A69YL3aSFlVhIgOBIRgGuMTWrtIzby7ZR0y4ywrctplFmY45RICAThdu3J6 YrWTVtDmUZX1NyEjPRB78GrbTAJ8rIAF5Kpx+OKzoH+QZNTPIVjYguOOqjJrCRVjFd4Ptq7JdPU 548q2Lv+Axir2vRG5+yK5dyseSZAAeT6DpUCSXEtyAr6g+T0WMRL+LHmtK8TfOoxyqgdc/r3qWx rcwX8WFm2w2v0Lt/QVFLrWoXAMeFX2VP8a54HDAjqK1ZbhlvYnB+VwDXW6jejEoJbD0uLm5iLNe rGoOMPJg/kBVyw1Am0AZuV461gTqEuJFGCA3b0q3pkmJmj7EZH4VlJXRaNlr6Zs+WjGo2a7k6/K Pc1ZiQ4yan2Ukii34P02O+8W6bDeAPCZgSK7j4j6dJPBNaWNx5sKr9oe3YnK7c8j8M/rXG+HULe JtOjRijefGc5x/EK7i5KJ4m1ifUnMdnFCYjuOOo6D1pS3DY8xlmW3gyh5I4rrfhVe6lqvjO2TUL ue6swrxeRPIXTlfQ8elcHevshIBzjIyfSu7+B95BF4sjiunC+ajmDPdumP50pxudFKW/oe0ap8P 9C1GFlW1ELnnMfFcVr3gbQNB0W8u5LJHeOMkFyTz2/WvYK8x+NN7Ha+GIbUOBNdzjIzzsUEn9dt c08O4yVtjSliG4tSep83X0aByiRquTzgU6CABQMcd6knU+cSeTmpMbIS/+yTXacbFtPDGqXVmdV jsppbdnba6KSOPpVJzLBcEjcjDgivbvh1O8PgCyKEbd0hYljwc+1cj4ns7HULu6u52igZskOpHJ 96jm1syDkbXWyRsmcRkd9uc/rWpFciYfLd5z2GBXIzIqswD5x6d6iWVkJKMRTcbhY7pc7uXdvq1 Tg4PtXG2uszwkAuSvvzW3bazFMPn+Vv0qHGwHLrDI4+WNjVpNP1C4ChYWIHAJzxXfWMFkIN0MUe F4LYHH41TvdWErta6bskdRl5D9yMeprqUFa7ZHM+iOSbRp4pUinJ8xuRGvXHr7CrN1bnSo0MSHe 3VsZFdZpWl27RvPJMZ5ScySHua03sbV1+ZVIqlBNBzM85g1i4jk3Phx/dbp+lX08TSxkGO0twfd Sf5mu0WwsVPFrGT7qKTVGTTNHuLmO3iVkTjtyeBS5LFXZkeEtQk1XxZaSTMPNHz4HH3MnH8ql8Q 39zLdTxSuwVpN7J0GQMDj25/M1xWjzTQ6vavBN5UhlCh89MnHPtzXRaney3d5LcTNudjycVk1qa GHqUuIyDwTWjoDxtp4CEiVCckcEH2rB1KXe4Gavaakjw7rdgo43KT1Pei1y4Ozuju7fx/4tsYBZ jV5mthwrcFx7ZPNYmq6vearcF7+7nuHC/K00hcgenJ96rByV5Qq3uciszUppYBHKgz1Uk9qm3Q0 lO4pXLn/ADmrEFlNfyLZWqmS4m+VEXqTWdcXcLTQeUXCYHmD1PevZYYtG8K6db31jZJDczQhg7A tIcjpz060N2MGzIsdRt/Cfh2LRru2naRXPmnOPmPXAPavONZv2ubiRs4UkkLnOK6nxZrj30y7pA xUZyB1P/1q89uXZpDRFdSUNLF3OKQZB5qykQjQHuRUB+8fSqAjPDEVJG7KcgkGo34ahTSA6a9k1 XT4DbNJExkyG2D5iP8AJq1oGmTTI0U80kEDYyqrhnP1/Otn+zdftdMS+juLj7G6B1maOVkK9iGK HHBrCdpb2ZpDe6ZI5PzM8Ckn6kw1s7boi3Q7q1tIbO2W3gXbGo4qQRKOuT+NcJPE6RRvbvo4dB8 /+pyxz1XdGmOPc/0rSu9Rsrq3K2Wmpby4GXa9tJl/752j+dWprsTyNdTrRtToAK5vxxdtHoYjQ4 8yUK3TkYJ/pWTbW1xKjsbXTJCvJzHb4H1wT/PtUN0oI8l9P0kMp6q8cbZ/4DKppOV+hSjbqcvbs ftEYH98fzrdvLgRQ7s8kcVoWljNLE2dOUryFMNyWBbHA/1/H+eDV2xitEtZU1HSr+K6VyE8i1kn Qj3YyD36ZrPlZfMjgJGLyEnvW5owdEZW4VuV+tawgeScq+jSvHzghblCfzOB+dSS2aFVWbQbqWN c7V86c4z6daLDUirI204xg+1QXASWIxyAlW61p2N/rOn232K0PiK2szn9zFO4T/vnysVAsenwaq kd99ogil5N3MCqjjPTyQx54PBpOI+a5V0jQm/4TLSbGVt1vcToUkxw6Z/+tgiu9+LF99g8W2kUE qsowxVenauI1IaNBKBbXKXkZ/jhuFX8xJGDTYoNLiKzRrdFiD2hYcj3TFS492SUb6RmJLEnmsqG IzzFgPlXk10Nrf2ujXpudPu5gxXaRc20FwMZz0Z8dh2p2p3dpqHl3l3dWxYnbi3soozx6pHIMD3 xiq5QuY03oB9KpScGnlmbcXacMSTnOfqetRq/zf6xueMsuakCKTsaQVMxwf8AWJ/3x/8AWpWwQC FhP0b/AOvQB//Z END:VCARD ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8623602 python-gammu-3.2.4/test/data/gammu-dummy/0000755000175000017500000000000000000000000017261 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/calendar/0000755000175000017500000000000000000000000021032 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/calendar/20000644000175000017500000000037500000000000021123 0ustar00nijelnijelBEGIN:VCALENDAR VERSION:1.0 BEGIN:VEVENT SUMMARY:Tester CLASS:PUBLIC LOCATION:C/S/007 DTSTAMP:20040120T140801Z DTSTART:20040123T120000 DTEND:20040123T123000 TRANSP:OPAQUE SEQUENCE:2 RRULE:W1 FR #9 LAST-MODIFIED:20040120T140828Z END:VEVENT END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/calendar/220000644000175000017500000000027600000000000021205 0ustar00nijelnijelBEGIN:VCALENDAR METHOD:PUBLISH VERSION:2.0 BEGIN:VEVENT SUMMARY:Coffee with Jason DTSTART:20021028 DTSTAMP:20021028T011706Z UID:EC9439B1-FF65-11D6-9973-003065F99D04 END:VEVENT END:VCALENDAR ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/fs/0000755000175000017500000000000000000000000017671 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/0000755000175000017500000000000000000000000020531 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/dir2-5/0000755000175000017500000000000000000000000021533 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/dir2-5/file10000644000175000017500000000002600000000000022454 0ustar00nijelnijelThis is testing file1!././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/dir2-5/file20000644000175000017500000000002600000000000022455 0ustar00nijelnijelThis is testing file2!././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/dir2-5/file30000644000175000017500000000002600000000000022456 0ustar00nijelnijelThis is testing file3!././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/dir2-5/file40000644000175000017500000000002600000000000022457 0ustar00nijelnijelThis is testing file4!././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/fs/dir2/file50000644000175000017500000000002600000000000021456 0ustar00nijelnijelThis is testing file6!././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/fs/file50000644000175000017500000000002600000000000020616 0ustar00nijelnijelThis is testing file5!././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8623602 python-gammu-3.2.4/test/data/gammu-dummy/pbk/0000755000175000017500000000000000000000000020035 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/pbk/ME/0000755000175000017500000000000000000000000020336 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/pbk/ME/10000644000175000017500000000012200000000000020414 0ustar00nijelnijelBEGIN:VCARD VERSION:2.1 N: Nikdo;Nikdovic X-CALLER-GROUP:10 X-PRIVATE:1 END:VCARD ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/pbk/ME/1010000644000175000017500000000075700000000000020573 0ustar00nijelnijelBEGIN:VCARD VERSION:2.1 SOURCE:Yahoo! AddressBook (http://address.yahoo.com) PRODID:-//Yahoo!/AddressBook/YAB3/2007 FN;CHARSET=utf-8:ACENET N;CHARSET=utf-8:;ACENET;;; TEL;HOME;PREF;CHARSET=utf-8:(07) 3899-5174 TEL;WORK;CHARSET=utf-8:(07) 3899-1411 NOTE;CHARSET=utf-8:ISP Ph 019833206\n\n UID;CHARSET=utf-8:59fd7826c3be2b3646a08c008e5fc669 X-CID;CHARSET=utf-8:26 X-CREATED;CHARSET=utf-8:1189935222 X-MODIFIED;CHARSET=utf-8:1189935222 REV;CHARSET=utf-8:1 X-PRIMARY-PHONE;CHARSET=utf-8:0 END:VCARD ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/pbk/ME/1030000644000175000017500000003576500000000000020604 0ustar00nijelnijelBEGIN:VCARD VERSION:2.1 N:Amore; TEL;CELL:+393123456789 BDAY:19770324 X-IRMC-LUID:000200000012 PHOTO;ENCODING=BASE64;TYPE=JPEG:/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAIBAQICBAUG AQEBAgMGBgYBAQICBAYHBgECAgMFCQgGAgIEBgcLCggCBAYGCAoLCQUGCAkKDAwKBwkKCgsKCgr /2wBDAQICAgUKCgoKAgIDBwoKCgoCAwYKCgoKCgUHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg oKCgoKCgoKCgoKCgr/wAARCAB4AKADACIAAREBAhEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECA wQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0Kx wRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R 1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19 jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/ 8QAtREAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2Jy ggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIW Gh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5u fo6erx8vP09fb3+Pn6/9oADAMAAAEAAgAAPwD8/ItZv7GIm3ltJVb5GWVB+6kH/wAVXmHjLQ783 +/SeLY7byVEY/uROORj/er1262/ZsXtqs2ejjhojn+//wDWry+/8VJFP5VzBdHn91IF5nhPTC+z 5q+x96uuP72a9B+HVpnP+h6dj/WzTT9LUf7TGuyS5uLn5bCT7PD96a7VAGv8f88FHQfrWH8PtJm vhj7Kdv8ArbW1QcIfWU98Cv0W/ZQ/4Jpw6PHpmr/GT4gfs1+II2njuh8PZNWjP/CQ2bR7turavb eaqbvTbIOz4rNmm9frV1I/730FfDgtp34869b0QseR/u1b8G+D5teuPK8OS+Hodv73WNUv/uWQH 8Nuh6s35V+/a/BP9mbxuVtPHP7Ovwj8OalKuLHRNStIIJNXjHbQdasm2Sj1+z3Uv+3g5FfJ37ev 7D+g+G78R/BLwX4ei02OFLSK2trWEeRMSfvyQIucZ6nJ9TVC9uNoy7ewqeykDHEan1r8/ZvgUnl 7f+EksxJ0kvLHy8/9slx3+lHgT4OaT4fJOl2bzXB/4/NQuuXn3f7dev6r8NWtf9fosMB77FxyK5 Lxtq1l4fhMmtSGKNfmk/8Asf8AerAF+38Ep9PrW19mHdfes6eMp0/z9aoXmT1WvBPix+2/dq23w B4Y/wBuee99T/cRa4uL9uTxMg/0vR9EZv7+0/uf+A57VpxaZL/zxqhJex/36+mrm3B6/iKy7ywz 2/D6eleJ/Dj9sx7u5EfjX7GsDfJHdhdv2Fv+muOxr3iO4WRc28qSKf31nKv/AC2U+9I8DL/rR9K ElB/1be1cxq9i39zNYzOy9B/k12t2v+z/APWrE1XS4/8AP9akV/UmmPH/AHawbi8WMfvYoz/CvP Vvao7SzI5fbzyKztKtTq90558iD/Qrdl/5fLvvkf8ATHpXZQ6ST6/h/WrgPv8AWqwHrWfb2xY/c z/n1rSg02RvuW6/59quQWO30/D/ABrWsYW/5ZJ+lSpL/jQVqtpvh6c/xqv+ArVtNEkj/wBeg/Ps K09L8L3s33RJ7/j61pXHh5oh+9mP09fxqYN71ERXjUraN4gvJX8MX2lX9m+27sWtcFY8w8hV9m+ leXX3gi286TNlasRII4GYf6pRL/CTXT/sW+F9Rsw0XiDQtQsZQzt5F0uN6lBymfWtO60kfaJ8x/ 8ALYD85vWleXH8WaaRnnb/ALVfZH/BNv42a78I7PV7z4a/DX9njUvssc3xF8V6n4itn+3aZpWkI m+Lw9qi5GLpH+6VTn+LmvbIf+CrXhT9oe5trXR/AHho6hGrap9h+yhH11jjJhkm3Z8r+6JPf6fK Oha02i+HfFO/5N9hc6amf4heTWScn6mvjb9mv4m3XhrWrS48Pz/vEfMQU/68Mp4m/wBmbofUcVQ ji3Z/eOOdnH0BplxLg/6pTxu5/Gv2++I3w08NeH7S2n+JvwK0HTrSdksdIvHsof3s9z93f9nww8 312r9a5SfwKbOYnwV4o8TJETiTQ9R1C6CQFe1ncq+5Sv8AtpKPavm34y/tQap48htV/wCE81S8i RP9EFwWlOl3EDtnY1z5n3V4+83v6VP4B0b4peM7+xsf2ZfiLbwaldL/AGFbLrfywQy6fbs2Xkli fb9lt4zjCZ7L6VDdeH3x+4v3PchuQada6yuf39mnpkdRX0Pq/hTw9eKR4u8TePPD1z/ywh1YQSR ag4/59NXEXO/080N6rX5ff8FD/idB/bDWeg+KhfWVufLvpIBj+077vuwT/qOlffXx4/4J4/tIfB 7T7rUvib+0B4i8a2CWk3iT4iadpMUNxY6XFEPu311qVzayL/ezDpr4r8d/Grz380j3fVibq6Pu5 7Uuj6EwObmWI9wB6/kD9Ov1q7e6ypGIUk98+n5kVBqHiFJz/oYVf4Vf+57n61TvLCGTi3jwO7n/ AJafU/7NZnm7T8owOlaNnelv5fh/sr/tV1BrE3+tUbuFIdpjj29SB/n0ru/hj8d9d8HzqPECXs+ mSYvGs5f+WMTfx2ZP92ul+DH7PV34jdX1ywnhtP8AWxr/ABX6/wCyP9uvUv2tvghbro0broUlrL CVktGZcbrOXg4/3eKrTuvSUZ7VYjibrG3+1XY6fqVvfxrJpk/nQuBd2ci/xxv/AI1meI4y6bYZJ Fkb/RbQp1R37r/u1zH7Nv2iHSYv7SjuCgZoLaXHEMO7ufY16J4C0+LUJDIVEm3/AIl9uEP+qk78 e1c7LFgnJ6VsRtkDA61Q8K+AIdOiVLCN+Pvsf+W0h7sf9s1u2/hsn7x969C0TwMZfuWkz/0+ldJ a/CO6l/1WmXLdgAKq/af75q0Lb+6teSL4VbP7sfWun8B/D6W/njjj4Z3Wy3N/yz81uvH92vQbD4 VFWxOnzdUjGdx/3YhXo3wt+Ed2Jl8jwN8RnkH74OunXHO3+5KYx19s1ajn9B7VBJD6mvvP4R/sS /DLQNKWDWPA8V23l/atS1K7jQnX5WXrHfNGCOewkwK/Lf8AaT06zstUuY/CQkktEka109yf9ZEj +uT296+9/EvjDxqlso8W+PfEfh+32CwSHVLa5j8yHH/LIfZ+w9zXhXiz4DaPeNu0zSfE97nlGWx nT7U7/wDPKW7SLqa1GuB/yygl/KseCE/8t7hPzr5L8f8AwH1jwVqVr/bsNqFmSeOymt3yJms1X+ QavG5nAnuN0HPnKc/7SzV13w3/AGx/F/xYu4oviVa+DJ3td/iKwvdOt/Lkuo7140YXAVsYiUg/6 tTXMarZn7Vc9v3wH/keqEcbf8vmzPU4+tXE6fu81618T/DEmo6Pc26am9mbuBojdKu77MBrY/5Z ZH3xDjrXzBrv7LA8KFJvD39ua9tIvLiaYbf7N8r+LyUc/d+lfeng/UrHSr/Tv7duYYY/sTN+86e ZcahddZSPT6V3uv6d4D8SxXEME2gSTSQyWltN5ACRyzRH7mp7Ov8AwL6VS/tYocLbM3/LY/kKjl td38X/AEy/U18S/CfxnFOB52srCB++mjnHE3+43q/XpX6H/wDBIXwfY614it5JPEHkPb7/ABLpe 3/mKyrGRt2/9N0J/DpX5Q+CtZ+zjEkON37qcn+F4z6e1e+/s3ftd6v8PrqO48B3sUNxGy30MzdJ Wi7PF7139sy9/wAK5mcf3frX7qf8FQrKS5+H3iJbaKN91i9vOHONlu8ibjuP/PGPJr+Vz4naKIZ CsEi474r+i3/gsJ+1tdWvws+1eDNAuLlNVjsrfWLu3Usng3TNZhjlLTSj/nt8kXP971xX85PifX hdTMxI+n+NQaeBg7v92rJ/+vXN2vhsyOAOc9vYV3/wt0O6hvo1EdhZWpyLy/li3/ZPLQ485F5xM +Bx064NaHwQ8P21xMx1gf8ATHcf+WYI9K9H1rwepjkHhJ9z43NtwN4H+0ajuJFrSt7Y44pf2ffj M9lqT/2dp4WEbl0wBh/x+mI/cf8A36W2+O2v+KIr/wD4WP4S06axzJpeo7/9dpi/ZpDvgZucR7c EjjPWnfsmLolrer/wnvh2+1I7ZPsOmiM7WvGBCtc3HpASG9+le0+OfA9pJp+oyWubOMW7zRoEwd VubmMhcJ6l6pqy5+4fWtEQNgbZV9MVi+FfgR4y0PSbIah4e0zTLSa1j1T7TqFs7GV9Utg+0SB1G VjfkHJHeu8/ZZ+EelHSF/4Uld6qFkk+3XF5q6s2Jk3Bwzhrf+IDG2NguMc9u1/4JGf8FAvDPw50 9tO+PPhWfxZocs8euRaW5B/4RHULKUfvYbJ+GDAk7ScZAPHOfvPwbdfDLw54Gk1bRtL8H6VDZom u3Gt+H9KtJp7eW5ub+FNthc7QSrTJkPIhx3Bwap3sHXaevzflzVWO5xjzYzx8tePfstfsd614mR Fe/ubmdf3uuSWBwrs3+1KTwOK9N8efsk/8I/NBDr/h3WJ55Sbbw5Gspcag6MM7QXx+7JHXFekeC v8AgoH4c8OkJ4U0PxL4ntJo4/EfhnWZ8QnVYJrZf+XQRnHmH/ZGOlW/id8cW8UXvhueK2ttO86W 5VbVmLfZvstxEDlsLndj0FUv7J9X/EYqX+2Dn5YvwJJrwD4s/ATxf4RuYZNE+CHxC1KFU+3Xep6 PeW//ABS6eawI8hupjAycZGO9dX4a0q6jYf8ACS6Z8TSxP+p1yeSEReb/AAtZq0SnZ7/rX3R/wj On6vHLHr62dxC26w1CFT/yym6gyg/xg+x9Kuab4K0WymJ0rw5Yxlx++MKjank+qf7dXPsEPHnJI cdP8/4VlPqUv/LPyhmvmjx9br4LuhbeCtJ8CWLm1TxXfXBsORPcGb5G8mZdxjMfrXh/7T3inVdN vWi0ufUNQULHe3N98kYFxcW6krFEAf8AU57uxr1H9pf4qw6jrs32FjbeSieGpQ+PnaCa8BKEf3q +eviR4X1LxB4t0f8AsrxDe2llqLQeCp50bcPKtrjaTJZnj+L61q6ZpaFhvj9RzVC9v32nZJ9K/H n9gH4owt4kgiu9L8kTRzeGbVlb/lrJasR5nH95a9x1ay/0q7z/AM9wB/4E/wBK+MP2Wddl03xFp UsitHi8giuGP/PKecA5Pspr7W175Lq7/wCvjof+vmsnUl54btt/Wt/TX4OfrXpXxs+K1loGsaVD qmmahdC5sv7Asfsx/wCQfc3UvytNF3CSN0ryL4n/ABh1yC5VUm0uwliu08I6hBZxrsuStztcSqw 5z839K6D48a9AvjrwqLy0nuQsWn3d1awBS2+a7/5ZLJxzgdcCvFPiR4yW71ORTeCWb+0mu2f/AJ 7f8TE/ePuas2lou0F19KoyXJydrev8/wD69c7rE0WnX97Fp0vyR3E1ppqt12W1w4G8+4Ao03xbJ zvjdj/yzx3x7GvtP4ZfsjfDXw1e6jcfErxToeuJcmKTwPaapD+80Rby2RpXvLNgdpuLp3VePuDd 3rd8d/8ABPn4basjN4VtNT0G4K+bZXWmSFk8xhwZbSbjA/2Sn1rOk8SQg4Yyf3S2OM1uW/hG4Zd 0Xk8/Mq55/wA/jVPx7+3rL4k+GEGiatr94J/sR8NLbx4xPYaFfW21b0n0METDGT+tfmJrejzwl9 ueDtY+lfVX7QP7L+peGIIx4Z1+51W9iLchRGus2Vw3Zdx5jJ/vV83Q+HNRuJm/tvQ9Tsl/1rvNn 70fY5rWsbhOTDcf9NDWZdWDji5iINdJ8C9U+Ui75k7/APTRB/hXda3fsI3FlJIjHEmB/wAtgOzf WuA0HTRbNutVZAT+7Ydz/s12mj/a7pv9HtZJT9wEY6n2ol+tW7fpzW98IbrV7ScNZaZCf+WNw20 n5fds/wBK9U+JXiyeK28m/wAR3UkVx4ljhi/55aRbll3Jk/66fZ39a1/2ffhH4jWMT33g02tnkw 3Or6rNFDDAYI2J33tw6j5UU9yT0HPFeIfE/Wteudfnm09LDUf3MmkpbWp3R+HrG4tG+SSTu9uGO 7qN/ANMA9frVkyj19q8q8Bavq2kzt/aH26OTduKSDm3PuD/AHhX2p4L/aC1efQbvT/Dfir7JY6h Etl4ttZxlL68sZA0b+T620gxxjjIryf46eKfh/DeLNYeBzd2Aih1zV443ZX+zmyhzA3o2lqSu7+ JvUYrjvC/jnRtSkkl+GZ11LQSGfRLTUseZpEDHhJyrN/qh33HNTSJVBSOkn1r1bwd+2h8RPC99Z RfHC38P6nppMHgTTrOyhVW8ELFgL9l2ffDLyd24t2Nfd3gf44eNbzUtEg+Ivwe1PwlZW95LpXgK a/hZH8bRXkqFmlifp9mYp0UDmvzU+PPgTxL4i1DRrn4VeGdZ1GVttkUtEONMvtLuVIa7uf4dwbq SvSv0N8b6rqNpq/h6TxdbapbGZ11Wx+2zb8kTx5Bk3N/qvwonbjlOv6VS8vn73T5h71+jHj74/W a2DNa67DvuBJp/huOCPd/ahU4PzRqfue+2vR/gA2oXFq0niGRnMhE9nkY/cKnaP39wK/MiP4F+N Yr/wAzTvgJ9s+ZpIPtMUf+nZ9ZD7V9u/8ABOi21izXVYfFvhm30kpLbXtnbRoox9rtGzwn91lrT Np8hKr/ALbfmBWOOo3Sj0FfC37Y/wATpbPxJqq6dLLGRM0C27dEEGo3Y4f6j8q474MfEHVLvxR4 UP2+48v+1rTSHi3f8s5r+3z8vvmue/4KE+JTH4r1jy2iGLmWD90eBs1K66H2ryTw38Xn0DWPDdz /AKdL5OqWnix7G3bH9q/YLy2bBk/6abcc1t2kWNpjf0b9KilHqPavjXwhqOnaZMk2q3ljDaBsWF w3/LeZP+fcjuK+iPFWqRNc3LW8m5WnW6t2P8aSSg8g+tfPmr6x/wAI3q5ksPDVtqVhJEJ9V0kwB omtb6Io8iQkhQ6hRg/K3oa9Fk8ajUrYzLlNxjvmCf8ALIgDgr/smuFvOQCPpXSacMbsmtT9ojxd b6d4202bWn8uKGLRLm4uXPy6ZGFjJ8457L/9eua/Zo+Al74tvvt2ra54QOmi6aRrBLpPtVxcRtu UvpPXy3/vYx2619GeJdD8L6k1y/izwt8ILS8hsLPU7HxD4mSMpcyxW8ACXM05xx0Fcv8AAfxZZX OW0bwN8JNKAJtFufCNvGia8oPWSWDr5X9adPcEJ+7/ANyrNjpmWHnMME+YfpX0xrujx6XpoaMJE G9P+Wjerk/3q8dsv2j/APhGJ9k1/vtH/dSI/TT5H7xr71t/GH4jztp8arOxxx+Jr4v+KPiWaebm RvXFcVpthuz9pr0TWNUxj7OP9mvsHxX4qtdcTE4j3H59Dm/59p/7rH0nFfK/x40e6839xY+Xz9l ucfwN9P8Aar1HRNZuJtNie0/1oQXMef43g/8Aiqi1T7Pr8aywLCd37rVIj1gnT/4qtnT1wep/uV zd1PuHX3ryrQPD1vPb/vEyy/vVA/vVs+G9XtLSRVSBbm/Y+XZRdrH/AG7oj/niOazvG8reFRcfd O4D+xc/xSzH/wBpCvMPB/jsWcspvNxkeKTTbGZv+XW6uF65reA96xGevrz9gH9pC88GXOpTxD/h LNKurj/hG9P8K69+8g1u6+TM0dnJkK07jrt+7wcjiu1/aE1vw9NBql3Y/DiPUtcvdn/CvNK8O2/ l2/gXStIu3eTyLVd/zaxcGJFHVFBP8eK+bvgFeNZaPaG22CT50sGP/QR1S8Man/t1Ulq6Lwj8Z7 6Qy/Z9s0Df8S+0WT/lz+0yvh7f/at40qsztnrx9yhYx3H+1VPxv+zBqep2d3Fofw416KdobLxDJ qVyxlFvYSlNs8BXO0XcTIGA3fKu5eMhfSPjJ8A/B/gbTbGD4U3dheyeY2mx+Un+k+O0+z5e4uoF 5xCU9wvQYAr2n9kLxFewSG2+I3xh/tyyvI00DRNVFsxb4eRsZdkE9uQG/dXEkm7Esqc/IcV5/wD 8FBPgr4d8UXNn/wAKB1XUDFZ248GatfSRbE8XsXZneHzDuGZZJTznsqqAvNw3P99h6VUFqc/uoy f4h715x8BP2kZfDt0bSEaasqSm81V7kM6m105WMkdt9nDfPMgbafuA8u22vvLwvJomvraTalbST xK0fi7w1J0e23bTmJm7ygDjp9a+GPgd8C20i6+0T6uizj95Zy26nMTbccXXGOPSvWtO1KTS0RI/ GWrLGo+yWduJm/cRqPc+lRf2xCOG3t61b/4R25bkiNf4Rmv1V+IX7fngDwx/yMvi++lZJT4X1uH SLSac6ZqEUSkpK1ujcwK67ufl6Ng147o//BWfwl4H1XUp7jwl4w1jT7yS2uLO6gwrafb6dakMTa TbeWY/3l+tfn1rXxDnDf6DZz3J/wBZPIZBl2Pcg/3jXlH7RHxX8UWtuu3RoI7U/wDH9OOfKb0kN Jb6hn7lsnPynJ7UN4YjX/j4vnP8XA//AF19q/tJn9mD4g3E9/4Q+Pf7QEWp3cz+I/EenXcMXl6H JeTO2218u2b/AFbuf+W78d89fnBtA8CR3Fo3ie98XvbwzDU4/sl6qPp32fbzdzyWDLi6IXoCRzk dK+T/AAn4vm3N/ZOvSWDH55hjKsx9I66DWtWneFmv/GcE5A3iHyn/ANKx/cZN364rpV1IjqkZ7L nPTHtgVjtpyd5Z/Tt/8Tmuq+P/AO0z8AvDG618H/AqPWrmNB4d3rdXEq2yxY+WS5nuMfu/9x6+Z /FP7T81ynl+Dvhp4e0GA82zSSys0A/2TI4H/jlecWHgvW73m10e7VevnTYQMD/dZ8f1rZ0/4IXc 3/H9rtlF32QAsfzO3+dc95S/xMx/iqy92x/1UKjt/k10eu/FXW/FMbnx7+0HoER436ZcrdD+0hb gYEaWNo6fugONzrX11+zV4ffTLOFGuPNO1bstz863FtGc7T/fzXyVpP7PmnD/AI+tS1eb6FQHRe uFPdfrzX3n4V0m3t5E8i3lTEcdid/9yCLA3D/ZFUdRuRjCL/tVq6DbfNmU/wCwK3vH3h2W4sl5H 0r5S+L/AIUNs+7cvXydvru/wr7O8SndAPlx2r5k/aDso+qx5wQ+D/Hz3NYWmTc/rXW6zbjFWtA8 a6Zp9nDFqGvaeZFj8278s52yM3T5fTJrH+GfxKsLWedL+4/cbibSQD7ysePl/wBmvOdI8lZWN5b +Yu3ykBP+udeuR9a6Px1ZDy4b3wzbQpgC21qGPsg6Er/sVreX6seefxrmFl9B/s1n/tNeMoNSMX 2KyvIF5nzN/wAvYY9Ux9K8G1/U3+7AcE/u8jtmvTvjXKdQ/faWq4Ki/EcXaLHO1B/zxfNeefD/A MHPrt2qSXsVoDl0llBPnyAcLFGB1lbitmF/7/41lXHX5f8AdFel/C3xJeCxeEXB8tM6tZ5/5c3S 1n+63uxzXXeAbHV/E1wsHwi0u4u4Yz5mv6lJ8sVrtGB5lwR/AoJ9eeK6n4R/sgyxR7viXrf2a3b /AI+tMsm+a+jGeLi67bx6fnXtFpremaLbrB4J06x0y2X93BDbDH4sfVqyLnUB/wAsFz39q37LSG P/AB9HaP1qXwxpJ0QRq2otc3Sn7QbmIlVs5h/zyX/ZrVvfFSDO6/WST3/5Zfh7Vwmt+MbW1BbUd XjiXq5PVv8AdWvPdc+NzzjZ4Wswin5XuJfvT/7q1m+Wzf6xjW99ojT/AFagV2/iP4nzWJb7ZryA fwhT93/gNcnqHxShmH/IclB+8WHrXK33hPV9T51BOvMJmPMp/wDr1PbfAnxG8e6PwtqMqfdBgwx ZvaFDn9K1YbVfWsG41F/7prR0+V7ps2PjWX2DHnJrlvih4x1YP5Wt+IWuYetu4frx/GvtUV14Sv tNP/Exsr+39VmQj+dYNxZR6sm6wklkznHmggsYW54P91q0IYf734cVlS3f9xv1rKt9Gmik3QXHl j+If3s+lW/7fzxNL5R7Sjvv9veotJlubP5NURpoz9z1tv8Ad+tKvh65B/0ANNEeGXruU+qGtDf/ ALVZwH92rf8AY0S9fMkbr85yZN/pIfWo7S3A/ur7DuF7xH0i/nUXw/1wajaxMzjdjyLhVH+raPq d3q1bMNtnrx2x2Vl9f+vfvWW4qWM+lXPDWkSXEyJEu3c6WXlk/eYt/GP+mXWvqPT7v96+/sRHj1 C+v1r57+E8Wb637DeJHz1xGc4P/XYjNe2adqpkuZsHP8P0YrWPdpzx9a39Mb/Cu51bXQYMJn0z/ wDXr5k+O2uyAMPyNe4X2oEJjcfcV5J43+HGoa85Wy2xj+KeXpCD7VVs4cdf96tnUJCR8v0rytMe nv8AnXcfDrRZ9Xi8i2tb2eLIuJmgU/8ALE9C/wDtV3vhT4HaDpy/8VDJ9vYffMv3eP8ApkPT8a6 K/wDidZ6amzQIIIE/1arEP8PSrkl1/wA8FzWTDp//AD8SAVUX4KaHcxxP4s0iKx1BD59w9i423E OOlzagYJbua+ZPi01r4Xu5Y1lngUPu8PxWi4861XvNP7g17h4h+IkrdJX/AMfrXgHx88/V8OEzI P3AHeUN6fjU1nG3/LVzVfVPLx+5j565r2/wh8epdXtozcXCE7fKvSv/AD1T+7/v03WPFVyyn+yd xb7/AOArwL4B69I0wg1OdYsn7Nbbv4pc9K+gfFuoad4Xtf8AiYTFriX/AIl+l28fLTyMp6Rj+4M 1YayX+Ffeq6aoxHzSf7Oa80uLy91B86ldSv3wf4PoKp6bqWp3N1EvhjSr0wq6z6tOo/10cbc7m9 KxNG13xSbnfdeHntrTPMF18v7lT1LH0+lfRfhTxvpT23/Ejt7JT01GOP8Ahce9TTpjpD/s0y1YM ebjHeoPEGtplT5u3vJ7V7J8EPHWgThYzrw+0EgRJtbkf7/0r5v8V63u+593+HPvWt8HNWdLmNop /usLjA/jAb+tRWcHpVvUJv8ACvs/UPCVlP8A63VPDvptuHPf1GztXz7+2x8Ign2Obwy2lcE6Jdi xdelxypMQOeobtXpiaw1vhde8V6BayfL9mtUhIkvRIuf9Ggl2bvI5z8/41Z1zTdOvImFwmrT7vm +1TscWMoPBgsc/8sW92rfMP+H+ea4xZv8AGvi/Qofs93jxTpGGU4cuOJV9x7ivVPFv7KFvPC2o/ s2eMXvrYfN4h8OXZHmaZ5S/M9pH3jjbjn5h7ivqDwd+z18MvFeu6AdT8eW+npdj/hGPjNazYQ+E dZtX25glbgpq6bGU89w3NfVfxC/4JBeAPBujancQ+N9a0rUYr938GasL3Yv9hyQxbbfWEnGw7Tv bKojdskVydzqHOH8xSBvbjjv1/AGtOO9Tpcxn+8jjtX8//wCzprEmJImkRjxqVqp9/f8A6Z9a9O t/l6b27KP+egY/8tVx/wAvDcniv2ib40ePrF/tvi/4W/b9Iuf9D8KaT4Esrp7zwRbeKfKh/wCKr v8AWv7NmT+yL+41KeQDw5zZRhrr7HNGYpsf4L6R4A8XE/2b/wAE/NS8BQIn9p6dceL9Asbf/hFZ INFtriGFLbiTfYGOytx5ds0cU1jskaPyIM9hcy6UFgOq+IxbtNJ5s8ctzoq/Y9OMrRrdu/8Abfl uCI5i0MDSvE1vOs2wIHa1oOoaa0Mk+qahqSQxeRHc3MZ0u4jWS6b9wrPHq2Ik8nMs1zP5VrH5cm 2eWMRyy/k78IpiuoQ5SI/efPpuj6j/AHz+leieALh3uLn5j9/fHk9hX6M3dz4T8NTwjTP+CcnxI 0u4dTa6LL4e0HS5v+ELt/OsYcX15o9zMIxoQe03fNjytPlki3Q20DPr6D+0h4W8R3qr4gtvi/4Z 1iSKfWLP4farYCS9VZbe2kc+KPD+jJeS20ng6TULBJEuns2RXed0ezVbheOi8W+HmUSHxlHCu+M SedcaKj/YZd2LpE/tpiwR/KWWI7XXzMp5m01sx6npCz3dveeLMNbXcHg23ffp4F41zEJIsCXUop S5z/qoY52I/wBXvZZEj/PObeW449PbNZut6z9iX94R9B7epr76svjz4WtH367+z7+0F4KmuWhlj sPHT2enT65cakumxKw0vUtShlm/4R+W9s7aYxrceXPFLbOTM1vHcdZ4U1DwDrc4i+GH7TknimfY /iDRbfSL6CZvEOn6ZaQy+aLaKHJR7RrCVztA2XG7gOm3vrbwLL5jR6p4Y8X/AOt+yaI8Kaa8d7b tNbQQSNLNq1tBG9w93F5UPmyb87Ud3WVI/S9Z8FSLJB/wjTXGo2kn+i6pqluI2TS5C/3ZQZgpby t37qKV7n7T5VsLci4gmf8AJDxH49urjiKVlXpWIdUb+OTP94n1r9gLbxf8Mjj+yP2v/DN9nb/Y2 NasG/t/zPI8rZtHP9seZpvT732tdn+uhrstJ8G/20sdz4AuNM1PQ5opPE+h6xpV9NMmo2qLMYjp VwoKyR36Wkp3+eOOQH3PjAl0G+RUOpfDbxlHuD6y5CWkqJaLM8XnAwX0jy7s2xCwRSf8fK87Dby XPJR+H59qrqei6+l0ZJPD1zbbbN4rS4QtGiyTi+37Z7lGtYCLctLPhFQl4vM/EyKC4uT+7WtDVf gtJq0RDGPzP+Xc+9frVonxI8Jbv3X7YXwjvYn2Nodvb6xGw2SwWwRNKVLldy629xbldzSk/a4sZ Eyq/o+pfDfVLUuLzxvqpZN6XiS/aAZXtvtWfMVro/6/7PJ6/fOc/Nv5y8udTSTb/wAKf+IcifaX 8M4jsZjdGIMPKufsziMRwzqw2faZ7dvOzEAwiuJIfNJddGwveeGPFsXTRrQSW6pnUGM8UcEq+cZ YI5riApDdPF5JjEzyGKWBrev5+PDv7OPir7eqWWkTWkgP2lbm6yBFEX++8n6V75qumeG4Lrbqvx F0pL1FW01aYo7JfTmJc7L8Z/iz9Olfrxr3w9uZ4yniqd9Xtw6arc2GrQefHPf6RcStHLJYT3Ug3 6ZcwPIjbWaJ8yIdw3ScJ4C/Z60fwTatp3w7+HlsdMlktvGV/pOqWs80D3HgGztIIZp5dQlnRJdA s7RDH+8EhaPfHukRnrQXXInkSPTfB/xJb/TT8P8AVnOnbEsZwofyCxuDuvtroPsaD5pN6wzy7Ua XKh8Vp5Y/s74T/Gya6G4a3pa6M3m6UwEXl+dvuU4nM6NGU3MIj5jouQp/Mu18beBdNkX+1/GUd8 VYeYltC+ApPO6b2HtWjrXwq0HUbkT+BNd01YzulkOmSIFuI3OR9otNpz6feXHav0I1j9mfw9emE +Mv2Zvh5pItWitvCH/COwvbrC0dzpLhrzT9Pmt1zp95pVoi5SYLFbIn+r3xP0UXhqyjeMf8ITcC 2i8u28NeHj9pbTvBIsDZeV/YXgxr5raIeG5Y45IPLth5EitLBh2nab1HWfh7cQyImo6D41xNJPp OlbNNupT+6uI4VacKnlxCVDNdJslnK20OX2yyCIepWPhrfAk9kusZltf7YsLaSwvopnvcjEWwwZ +xyhgYtU5tRyLn7McBvyr+LXw91ZQv9m+HLC3Q/Mk/mgC/K/7LY/qPeuX8OJ4htA6W/hvdK6m1t ZYZUxAXHVpN38Ffqzpn7Pfgu3uPtPhr4MaRoF2Whngn0a0UJoaw/wBjYj0/wvfSXFukca6Xpy/L p4kg8kPZyQXAM7cZ4s/Z08X+InS4+L/xx0C/u2uLH4g+Ktft/B+lW954q13R9Q8My77nWrOSOVf 7YvNKm3/vcBZERldLK1SsfXvC89uJGvvDvilgs/8AY2nL9gu/MvRm3OFTy+Jyj3OyHJSR7ZFScx 3ltO8/ifw6kPy313raS/Zx4ovYpNOvo1hO5lMHmtB5ZnkK+XZ5ZILy6/0ZJ1dojL8DeC/g78QpY Ct/46nu7dvv2MsvmeQyH+GX59ph6j7h/u16jpfjaPwZbBbrxZ/wkN4zAPBf+arW6ufvLI6H8m/C vq3wv8AtKt9N0O08A+KPCGnz6TbWXgrx14h1DwnpzXHxt1HQ77Q5Yrk6vfTM6GPTrKC1/dXEwX9 224yWVsD674M8a+L4tRaf4gfGnR9a06RLiJvCmnaVBbxade6xp9ksbafqR1K4lC6PefbZlVprgn 7SY3dxBAXs+HdImfP/AAlPhnxVaNG0uh64n2G6kWyuY/LYlphEsf2T7Oz3X2hzHI8CAw20zzQo/ kWqaoq7fsOh+KZWZJJHX+z7355YXk81Lfy4ZDcqsVvO/wBoiH2cMbVZ5IEmmltfnf8AZv8AgVJ4 wLDWNU8aabeMf7LxDCnlael2P+YnJ2jY9d0fTnkV2Xw5b/hI3Fh4zs9Ktbdd3jjx1YXUVxbLY3l q0aD+z5Gu5oX+3bPvGEFlP3Rxt9W8F+J/FNtPcLqHx9t9XtJGF14dufGGjWrzaXaQ6bApj/tLQt TsV369PNeSbv7OKrNMu1RBbrFeeCaB8Tv2mblNM/tS4kW48u0/4XnLqN7oLR+Lb2a58Lm5bSra2 hhMSGzufEcewT3DM+Xt3Aeyij4Nr9i7x3VtZRSRpJqGsW7i6WWxSMQbZtktjHcPbzGSURFYPPnM QSC2lmYwx51xdaiqW5vPCN9C8wQCGe21WP7PIzGMlymmSqYN6MI3jLzOr28jW0SNcG0//9kA END:VCARD ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/pbk/SM/0000755000175000017500000000000000000000000020354 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/pbk/SM/10000644000175000017500000000035600000000000020443 0ustar00nijelnijelBEGIN:VCARD N:firstname lastname NOTE:Test1 NOTE:Test2 NOTE:Test3 NOTE:Test4 NOTE:Test5 NOTE:Test6 NOTE:Test7 NOTE:Test8 NOTE:Test9 NOTE:Test10 NOTE:Test11 NOTE:Test12 NOTE:Test13 NOTE:Test14 NOTE:Test15 NOTE:Test16 VERSION:2.1 END:VCARD ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8623602 python-gammu-3.2.4/test/data/gammu-dummy/sms/0000755000175000017500000000000000000000000020063 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/sms/1/0000755000175000017500000000000000000000000020223 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/sms/1/10000644000175000017500000000017100000000000020305 0ustar00nijelnijel [SMSBackup000] SMSC = "1234" State = Read Number = "1234" Coding = Default Folder = 1 Text00 = 003100320033003400350036 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/sms/2/0000755000175000017500000000000000000000000020224 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/sms/2/100000644000175000017500000000027100000000000020367 0ustar00nijelnijel [SMSBackup000] SMSC = "800123456" State = Sent Number = "+41761234567" Coding = Default Folder = 2 Sent = 20070605T135630 Text00 = 005a006b006f00750161006b0061002000730069007200e9006e ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/sms/3/0000755000175000017500000000000000000000000020225 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/sms/3/420000644000175000017500000000020200000000000020367 0ustar00nijelnijel [SMSBackup000] SMSC = "+420800123456" State = Read Number = "1234" Coding = Unicode Folder = 1 Text00 = 003100320033003400350036 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8743603 python-gammu-3.2.4/test/data/gammu-dummy/sms/4/0000755000175000017500000000000000000000000020226 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/sms/4/150000644000175000017500000000027200000000000020377 0ustar00nijelnijel [SMSBackup000] SMSC = "800123456" State = Sent Number = "+420800123456" Coding = Unicode Folder = 2 Sent = 20070605T135630 Text00 = 005a006b006f00750161006b0061002000730069007200e9006e ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/sms/4/200000644000175000017500000000151600000000000020375 0ustar00nijelnijel; This file format was designed for Gammu and is compatible with Gammu+ ; See for more info ; Saved 20100114T220009 (Čt 14. leden 2010, 22:00:09 ) [SMSBackup000] SMSC = "+420603052000" SMSCUnicode = 002B003400320030003600300033003000350032003000300030 PDU = Deliver DateTime = 20100114T204215 State = Read Number = "5574" NumberUnicode = 0035003500370034 Name = "" NameUnicode = UDH = 0B05040B8423F00003AA0201 Text00 = 1106246170706C69636174696F6E2F766E642E7761702E6D6D732D6D65737361676500AF84B4878C82986D3564613561396A6E3231306D61353671323040008D908919802B3432303737373737373737372F545950453D504C4D4E009641008A808E0218 Text01 = 1E88058103083D5F83687474703A2F2F6D6D73637A2F3F6D3D6D35 Coding = 8bit Folder = 3 Length = 127 Class = 1 ReplySMSC = False RejectDuplicates = False ReplaceMessage = 0 MessageReference = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu-dummy/sms/4/210000644000175000017500000000115200000000000020372 0ustar00nijelnijel; This file format was designed for Gammu and is compatible with Gammu+ ; See for more info ; Saved 20100114T220009 (Čt 14. leden 2010, 22:00:09 ) [SMSBackup000] SMSC = "+420603052000" SMSCUnicode = 002B003400320030003600300033003000350032003000300030 PDU = Deliver DateTime = 20100114T204216 State = Read Number = "5574" NumberUnicode = 0035003500370034 Name = "" NameUnicode = UDH = 0B05040B8423F00003AA0202 Text00 = 64613561396A6E3231306D61353671323000 Coding = 8bit Folder = 3 Length = 18 Class = 1 ReplySMSC = False RejectDuplicates = False ReplaceMessage = 0 MessageReference = 0 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1637135469.8783603 python-gammu-3.2.4/test/data/gammu-dummy/todo/0000755000175000017500000000000000000000000020226 5ustar00nijelnijel././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/todo/220000644000175000017500000000032300000000000020372 0ustar00nijelnijelBEGIN:VCALENDAR VERSION:2.0 BEGIN:VTODO DTSTAMP:20080217T221408Z DTSTART:20080217 DURATION:PT1S SUMMARY:Wammu Bug erforschen UID:4937@thinkingrock.com.au DESCRIPTION:None LOCATION:None END:VTODO END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/gammu-dummy/todo/30000644000175000017500000000045700000000000020321 0ustar00nijelnijelBEGIN:VCALENDAR VERSION:1.0 BEGIN:VTODO SUMMARY:Gorusme DESCRIPTION: X-IRMC-LUID:00010001005E CLASS:PUBLIC DUE: COMPLETED: LAST-MODIFIED:20080312T115041Z DALARM:20080312T141000Z AALARM:20080312T141000Z CATEGORIES:MISCELLANEOUS PRIORITY:2 STATUS:NEEDS ACTION X-SONYERICSSON-DST:0 END:VTODO END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/gammu.vcf0000644000175000017500000000040700000000000016631 0ustar00nijelnijelBEGIN:VCARD VERSION:3.0 TEL;CHARSET="utf-8";TYPE=OTHER,VOICE:123465789 N:Nikdo-ME X-GAMMU-MEMORY:ME X-GAMMU-LOCATION:99 END:VCARD BEGIN:VCARD VERSION:3.0 TEL;CHARSET="utf-8";TYPE=OTHER,VOICE:123465789 N:Nikdo-SIM X-GAMMU-MEMORY:SM X-GAMMU-LOCATION:42 END:VCARD ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/k770.vcs0000644000175000017500000000107500000000000016232 0ustar00nijelnijelBEGIN:VCALENDAR VERSION:1.0 BEGIN:VEVENT DTSTART:19811227T230000Z DTEND:19811228T225900Z DESCRIPTION:1981 SUMMARY:John Doe RRULE:YM1 #0 DALARM:19811227T090000Z AALARM:19811227T090000Z LAST-MODIFIED:20080113T144844Z X-SONYERICSSON-DST:0 X-IRMC-LUID:0000000000D9 END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION:1.0 BEGIN:VEVENT DTSTART:19850519T230000Z DTEND:19850520T225900Z DESCRIPTION:1985 SUMMARY:John Doe2 RRULE:YM1 #0 DALARM:19850519T090000Z AALARM:19850519T090000Z LAST-MODIFIED:20080113T145744Z X-SONYERICSSON-DST:0 X-IRMC-LUID:0000000000DD END:VEVENT END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1426837250.0 python-gammu-3.2.4/test/data/rrule.ics0000644000175000017500000000163700000000000016662 0ustar00nijelnijelBEGIN:VCALENDAR CALSCALE:GREGORIAN X-WR-TIMEZONE;VALUE=TEXT:US/Pacific METHOD:PUBLISH PRODID:-//Apple Computer\, Inc//iCal 1.0//EN X-WR-CALNAME;VALUE=TEXT:Example VERSION:2.0 BEGIN:VEVENT SEQUENCE:5 SUMMARY:Coffee with Jason DESCRIPTION:Event reminder\, with comma\nand line feed DTSTART;TZID=US/Pacific:20021028T140000 RRULE:FREQ=Weekly;COUNT=10 DTSTAMP:20021028T011706Z UID:EC9439B1-FF65-11D6-9973-003065F99D04 DTEND;TZID=US/Pacific:20021028T150000 BEGIN:VALARM TRIGGER;VALUE=DURATION:-P1D ACTION:DISPLAY END:VALARM END:VEVENT BEGIN:VTIMEZONE X-LIC-LOCATION:Random location TZID:US/Pacific LAST-MODIFIED:19870101T000000Z BEGIN:STANDARD DTSTART:19671029T020000 RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 TZOFFSETFROM:-0700 TZOFFSETTO:-0800 TZNAME:PST END:STANDARD BEGIN:DAYLIGHT DTSTART:19870405T020000 RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4 TZOFFSETFROM:-0800 TZOFFSETTO:-0700 TZNAME:PDT END:DAYLIGHT END:VTIMEZONE END:VCALENDAR ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/sqlite-14.sql0000644000175000017500000001160300000000000017267 0ustar00nijelnijelCREATE TABLE daemons ( Start TEXT NOT NULL, Info TEXT NOT NULL ); CREATE TABLE gammu ( Version INTEGER NOT NULL DEFAULT '0' ); INSERT INTO gammu (Version) VALUES (14); CREATE TABLE inbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), ReceivingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), Text TEXT NOT NULL, SenderNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, RecipientID TEXT NOT NULL, Processed TEXT NOT NULL DEFAULT 'false', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) ); CREATE TRIGGER update_inbox_time UPDATE ON inbox BEGIN UPDATE inbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), SendBefore time NOT NULL DEFAULT '23:59:59', SendAfter time NOT NULL DEFAULT '00:00:00', Text TEXT, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, MultiPart TEXT NOT NULL DEFAULT 'false', RelativeValidity INTEGER DEFAULT '-1', SenderID TEXT, SendingTimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryReport TEXT DEFAULT 'default', CreatorID TEXT NOT NULL, CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), CHECK (DeliveryReport IN ('default','yes','no')) ); CREATE INDEX outbox_date ON outbox(SendingDateTime, SendingTimeOut); CREATE INDEX outbox_sender ON outbox(SenderID); CREATE TRIGGER update_outbox_time UPDATE ON outbox BEGIN UPDATE outbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox_multipart ( Text TEXT, Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT DEFAULT NULL, ID INTEGER, SequencePosition INTEGER NOT NULL DEFAULT '1', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), PRIMARY KEY (ID, SequencePosition) ); CREATE TABLE pbk ( ID INTEGER PRIMARY KEY AUTOINCREMENT, GroupID INTEGER NOT NULL DEFAULT '-1', Name TEXT NOT NULL, Number TEXT NOT NULL ); CREATE TABLE pbk_groups ( Name TEXT NOT NULL, ID INTEGER PRIMARY KEY AUTOINCREMENT ); CREATE TABLE phones ( ID TEXT NOT NULL, UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), TimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), Send TEXT NOT NULL DEFAULT 'no', Receive TEXT NOT NULL DEFAULT 'no', IMEI TEXT PRIMARY KEY NOT NULL, NetCode TEXT DEFAULT 'ERROR', NetName TEXT DEFAULT 'ERROR', Client TEXT NOT NULL, Battery INTEGER NOT NULL DEFAULT -1, Signal INTEGER NOT NULL DEFAULT -1, Sent INTEGER NOT NULL DEFAULT 0, Received INTEGER NOT NULL DEFAULT 0 ); CREATE TRIGGER update_phones_time UPDATE ON phones BEGIN UPDATE phones SET UpdatedInDB = datetime('now') WHERE IMEI = old.IMEI; END; CREATE TABLE sentitems ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryDateTime NUMERIC NULL, Text TEXT NOT NULL, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER, SenderID TEXT NOT NULL, SequencePosition INTEGER NOT NULL DEFAULT '1', Status TEXT NOT NULL DEFAULT 'SendingOK', StatusError INTEGER NOT NULL DEFAULT '-1', TPMR INTEGER NOT NULL DEFAULT '-1', RelativeValidity INTEGER NOT NULL DEFAULT '-1', CreatorID TEXT NOT NULL, CHECK (Status IN ('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending', 'DeliveryUnknown','Error')), CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) , PRIMARY KEY (ID, SequencePosition) ); CREATE INDEX sentitems_date ON sentitems(DeliveryDateTime); CREATE INDEX sentitems_tpmr ON sentitems(TPMR); CREATE INDEX sentitems_dest ON sentitems(DestinationNumber); CREATE INDEX sentitems_sender ON sentitems(SenderID); CREATE TRIGGER update_sentitems_time UPDATE ON sentitems BEGIN UPDATE sentitems SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/sqlite-15.sql0000644000175000017500000001164200000000000017273 0ustar00nijelnijelCREATE TABLE daemons ( Start TEXT NOT NULL, Info TEXT NOT NULL ); CREATE TABLE gammu ( Version INTEGER NOT NULL DEFAULT '0' ); INSERT INTO gammu (Version) VALUES (15); CREATE TABLE inbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), ReceivingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), Text TEXT NOT NULL, SenderNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, RecipientID TEXT NOT NULL, Processed TEXT NOT NULL DEFAULT 'false', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) ); CREATE TRIGGER update_inbox_time UPDATE ON inbox BEGIN UPDATE inbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), SendBefore time NOT NULL DEFAULT '23:59:59', SendAfter time NOT NULL DEFAULT '00:00:00', Text TEXT, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, MultiPart TEXT NOT NULL DEFAULT 'false', RelativeValidity INTEGER DEFAULT '-1', SenderID TEXT, SendingTimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryReport TEXT DEFAULT 'default', CreatorID TEXT NOT NULL, Retries INTEGER DEFAULT '0', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), CHECK (DeliveryReport IN ('default','yes','no')) ); CREATE INDEX outbox_date ON outbox(SendingDateTime, SendingTimeOut); CREATE INDEX outbox_sender ON outbox(SenderID); CREATE TRIGGER update_outbox_time UPDATE ON outbox BEGIN UPDATE outbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox_multipart ( Text TEXT, Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT DEFAULT NULL, ID INTEGER, SequencePosition INTEGER NOT NULL DEFAULT '1', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), PRIMARY KEY (ID, SequencePosition) ); CREATE TABLE pbk ( ID INTEGER PRIMARY KEY AUTOINCREMENT, GroupID INTEGER NOT NULL DEFAULT '-1', Name TEXT NOT NULL, Number TEXT NOT NULL ); CREATE TABLE pbk_groups ( Name TEXT NOT NULL, ID INTEGER PRIMARY KEY AUTOINCREMENT ); CREATE TABLE phones ( ID TEXT NOT NULL, UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), TimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), Send TEXT NOT NULL DEFAULT 'no', Receive TEXT NOT NULL DEFAULT 'no', IMEI TEXT PRIMARY KEY NOT NULL, NetCode TEXT DEFAULT 'ERROR', NetName TEXT DEFAULT 'ERROR', Client TEXT NOT NULL, Battery INTEGER NOT NULL DEFAULT -1, Signal INTEGER NOT NULL DEFAULT -1, Sent INTEGER NOT NULL DEFAULT 0, Received INTEGER NOT NULL DEFAULT 0 ); CREATE TRIGGER update_phones_time UPDATE ON phones BEGIN UPDATE phones SET UpdatedInDB = datetime('now') WHERE IMEI = old.IMEI; END; CREATE TABLE sentitems ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryDateTime NUMERIC NULL, Text TEXT NOT NULL, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER, SenderID TEXT NOT NULL, SequencePosition INTEGER NOT NULL DEFAULT '1', Status TEXT NOT NULL DEFAULT 'SendingOK', StatusError INTEGER NOT NULL DEFAULT '-1', TPMR INTEGER NOT NULL DEFAULT '-1', RelativeValidity INTEGER NOT NULL DEFAULT '-1', CreatorID TEXT NOT NULL, CHECK (Status IN ('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending', 'DeliveryUnknown','Error')), CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) , PRIMARY KEY (ID, SequencePosition) ); CREATE INDEX sentitems_date ON sentitems(DeliveryDateTime); CREATE INDEX sentitems_tpmr ON sentitems(TPMR); CREATE INDEX sentitems_dest ON sentitems(DestinationNumber); CREATE INDEX sentitems_sender ON sentitems(SenderID); CREATE TRIGGER update_sentitems_time UPDATE ON sentitems BEGIN UPDATE sentitems SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/sqlite-16.sql0000644000175000017500000001125500000000000017274 0ustar00nijelnijelCREATE TABLE gammu ( Version INTEGER NOT NULL DEFAULT '0' PRIMARY KEY ); INSERT INTO gammu (Version) VALUES (16); CREATE TABLE inbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), ReceivingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), Text TEXT NOT NULL, SenderNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, RecipientID TEXT NOT NULL, Processed TEXT NOT NULL DEFAULT 'false', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) ); CREATE TRIGGER update_inbox_time UPDATE ON inbox BEGIN UPDATE inbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), SendBefore time NOT NULL DEFAULT '23:59:59', SendAfter time NOT NULL DEFAULT '00:00:00', Text TEXT, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, MultiPart TEXT NOT NULL DEFAULT 'false', RelativeValidity INTEGER DEFAULT '-1', SenderID TEXT, SendingTimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryReport TEXT DEFAULT 'default', CreatorID TEXT NOT NULL, Retries INTEGER DEFAULT '0', Priority INTEGER DEFAULT '0', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), CHECK (DeliveryReport IN ('default','yes','no')) ); CREATE INDEX outbox_date ON outbox(SendingDateTime, SendingTimeOut); CREATE INDEX outbox_sender ON outbox(SenderID); CREATE TRIGGER update_outbox_time UPDATE ON outbox BEGIN UPDATE outbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox_multipart ( Text TEXT, Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT DEFAULT NULL, ID INTEGER, SequencePosition INTEGER NOT NULL DEFAULT '1', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), PRIMARY KEY (ID, SequencePosition) ); CREATE TABLE phones ( ID TEXT NOT NULL, UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), TimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), Send TEXT NOT NULL DEFAULT 'no', Receive TEXT NOT NULL DEFAULT 'no', IMEI TEXT PRIMARY KEY NOT NULL, IMSI TEXT NOT NULL, NetCode TEXT DEFAULT 'ERROR', NetName TEXT DEFAULT 'ERROR', Client TEXT NOT NULL, Battery INTEGER NOT NULL DEFAULT -1, Signal INTEGER NOT NULL DEFAULT -1, Sent INTEGER NOT NULL DEFAULT 0, Received INTEGER NOT NULL DEFAULT 0 ); CREATE TRIGGER update_phones_time UPDATE ON phones BEGIN UPDATE phones SET UpdatedInDB = datetime('now') WHERE IMEI = old.IMEI; END; CREATE TABLE sentitems ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryDateTime NUMERIC NULL, Text TEXT NOT NULL, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER, SenderID TEXT NOT NULL, SequencePosition INTEGER NOT NULL DEFAULT '1', Status TEXT NOT NULL DEFAULT 'SendingOK', StatusError INTEGER NOT NULL DEFAULT '-1', TPMR INTEGER NOT NULL DEFAULT '-1', RelativeValidity INTEGER NOT NULL DEFAULT '-1', CreatorID TEXT NOT NULL, CHECK (Status IN ('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending', 'DeliveryUnknown','Error')), CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) , PRIMARY KEY (ID, SequencePosition) ); CREATE INDEX sentitems_date ON sentitems(DeliveryDateTime); CREATE INDEX sentitems_tpmr ON sentitems(TPMR); CREATE INDEX sentitems_dest ON sentitems(DestinationNumber); CREATE INDEX sentitems_sender ON sentitems(SenderID); CREATE TRIGGER update_sentitems_time UPDATE ON sentitems BEGIN UPDATE sentitems SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628533974.0 python-gammu-3.2.4/test/data/sqlite-17.sql0000644000175000017500000001236100000000000017274 0ustar00nijelnijelCREATE TABLE gammu ( Version INTEGER NOT NULL DEFAULT '0' PRIMARY KEY ); INSERT INTO gammu (Version) VALUES (17); CREATE TABLE inbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), ReceivingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), Text TEXT NOT NULL, SenderNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, RecipientID TEXT NOT NULL, Processed TEXT NOT NULL DEFAULT 'false', Status INTEGER NOT NULL DEFAULT '-1', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) ); CREATE TRIGGER update_inbox_time UPDATE ON inbox BEGIN UPDATE inbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), SendBefore time NOT NULL DEFAULT '23:59:59', SendAfter time NOT NULL DEFAULT '00:00:00', Text TEXT, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER PRIMARY KEY AUTOINCREMENT, MultiPart TEXT NOT NULL DEFAULT 'false', RelativeValidity INTEGER DEFAULT '-1', SenderID TEXT, SendingTimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryReport TEXT DEFAULT 'default', CreatorID TEXT NOT NULL, Retries INTEGER DEFAULT '0', Priority INTEGER DEFAULT '0', Status TEXT NOT NULL DEFAULT 'Reserved', StatusCode INTEGER NOT NULL DEFAULT '-1', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), CHECK (DeliveryReport IN ('default','yes','no')), CHECK (Status IN ('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending', 'DeliveryUnknown','Error','Reserved')) ); CREATE INDEX outbox_date ON outbox(SendingDateTime, SendingTimeOut); CREATE INDEX outbox_sender ON outbox(SenderID); CREATE TRIGGER update_outbox_time UPDATE ON outbox BEGIN UPDATE outbox SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; CREATE TABLE outbox_multipart ( Text TEXT, Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT, Class INTEGER DEFAULT '-1', TextDecoded TEXT DEFAULT NULL, ID INTEGER, SequencePosition INTEGER NOT NULL DEFAULT '1', Status TEXT NOT NULL DEFAULT 'Reserved', StatusCode INTEGER NOT NULL DEFAULT '-1', CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')), CHECK (Status IN ('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending', 'DeliveryUnknown','Error','Reserved')), PRIMARY KEY (ID, SequencePosition) ); CREATE TABLE phones ( ID TEXT NOT NULL, UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), TimeOut NUMERIC NOT NULL DEFAULT (datetime('now')), Send TEXT NOT NULL DEFAULT 'no', Receive TEXT NOT NULL DEFAULT 'no', IMEI TEXT PRIMARY KEY NOT NULL, IMSI TEXT NOT NULL, NetCode TEXT DEFAULT 'ERROR', NetName TEXT DEFAULT 'ERROR', Client TEXT NOT NULL, Battery INTEGER NOT NULL DEFAULT -1, Signal INTEGER NOT NULL DEFAULT -1, Sent INTEGER NOT NULL DEFAULT 0, Received INTEGER NOT NULL DEFAULT 0 ); CREATE TRIGGER update_phones_time UPDATE ON phones BEGIN UPDATE phones SET UpdatedInDB = datetime('now') WHERE IMEI = old.IMEI; END; CREATE TABLE sentitems ( UpdatedInDB NUMERIC NOT NULL DEFAULT (datetime('now')), InsertIntoDB NUMERIC NOT NULL DEFAULT (datetime('now')), SendingDateTime NUMERIC NOT NULL DEFAULT (datetime('now')), DeliveryDateTime NUMERIC NULL, Text TEXT NOT NULL, DestinationNumber TEXT NOT NULL DEFAULT '', Coding TEXT NOT NULL DEFAULT 'Default_No_Compression', UDH TEXT NOT NULL, SMSCNumber TEXT NOT NULL DEFAULT '', Class INTEGER NOT NULL DEFAULT '-1', TextDecoded TEXT NOT NULL DEFAULT '', ID INTEGER, SenderID TEXT NOT NULL, SequencePosition INTEGER NOT NULL DEFAULT '1', Status TEXT NOT NULL DEFAULT 'SendingOK', StatusError INTEGER NOT NULL DEFAULT '-1', TPMR INTEGER NOT NULL DEFAULT '-1', RelativeValidity INTEGER NOT NULL DEFAULT '-1', CreatorID TEXT NOT NULL, StatusCode INTEGER NOT NULL DEFAULT '-1', CHECK (Status IN ('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending', 'DeliveryUnknown','Error')), CHECK (Coding IN ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')) , PRIMARY KEY (ID, SequencePosition) ); CREATE INDEX sentitems_date ON sentitems(DeliveryDateTime); CREATE INDEX sentitems_tpmr ON sentitems(TPMR); CREATE INDEX sentitems_dest ON sentitems(DestinationNumber); CREATE INDEX sentitems_sender ON sentitems(SenderID); CREATE TRIGGER update_sentitems_time UPDATE ON sentitems BEGIN UPDATE sentitems SET UpdatedInDB = datetime('now') WHERE ID = old.ID; END; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_asyncworker.py0000644000175000017500000000757100000000000020103 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import asyncio import gammu.asyncworker from .test_dummy import DummyTest WORKER_EXPECT = [ ("Init", None), ("GetIMEI", "999999999999999"), ("GetManufacturer", "Gammu"), ( "GetNetworkInfo", { "CID": "FACE", "GPRS": "Attached", "LAC": "B00B", "NetworkCode": "999 99", "NetworkName": "", "PacketCID": "DEAD", "PacketLAC": "BEEF", "PacketState": "HomeNetwork", "State": "HomeNetwork", }, ), ("GetModel", ("unknown", "Dummy")), # ('GetFirmware', ('1.41.0', '20150101', 1.41)), # Mock is returning different values between the local workstation on the CI build ( "GetSignalQuality", {"BitErrorRate": 0, "SignalPercent": 42, "SignalStrength": 42}, ), ("SendSMS", 255), ("SetIncomingCallback", None), ("SetIncomingSMS", None), ("pull_func", 1), ("Terminate", None), ] def async_test(coro): def wrapper(*args, **kwargs): loop = asyncio.new_event_loop() return loop.run_until_complete(coro(*args, **kwargs)) return wrapper class AsyncWorkerDummyTest(DummyTest): results = [] def callback(self, name, result, error, percents): self.results.append((name, result, error, percents)) def my_pull_func(self, sm): self.results.append(("pull_func", sm.ReadDevice())) @async_test async def test_worker_async(self): self.results = [] worker = gammu.asyncworker.GammuAsyncWorker(self.my_pull_func) worker.configure(self.get_statemachine().GetConfig()) self.results.append(("Init", await worker.init_async())) self.results.append(("GetIMEI", await worker.get_imei_async())) self.results.append(("GetManufacturer", await worker.get_manufacturer_async())) self.results.append(("GetNetworkInfo", await worker.get_network_info_async())) self.results.append(("GetModel", await worker.get_model_async())) # self.results.append(('GetFirmware', await worker.get_firmware_async())) self.results.append( ("GetSignalQuality", await worker.get_signal_quality_async()) ) message = { "Text": "python-gammu testing message", "SMSC": {"Location": 1}, "Number": "555-555-1234", } self.results.append(("SendSMS", await worker.send_sms_async(message))) with self.assertRaises(TypeError): await worker.send_sms_async(42) with self.assertRaises(Exception): await worker.send_sms_async(dict(42)) self.results.append( ( "SetIncomingCallback", await worker.set_incoming_callback_async(self.callback), ) ) self.results.append(("SetIncomingSMS", await worker.set_incoming_sms_async())) await asyncio.sleep(15) self.results.append(("Terminate", await worker.terminate_async())) self.maxDiff = None self.assertEqual(WORKER_EXPECT, self.results) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_backup.py0000644000175000017500000001017200000000000016770 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import glob import os import os.path import tempfile import unittest import gammu TEST_DIR = os.path.join(os.path.dirname(__file__), "data") TEST_FILES_CALENDAR = glob.glob(os.path.join(TEST_DIR, "*.ics")) + glob.glob( os.path.join(TEST_DIR, "*.vcs") ) TEST_FILES_CONTACTS = glob.glob(os.path.join(TEST_DIR, "*.vcf")) TEST_CONTACTS = (".lmb", ".vcf", ".backup") TEST_CALENDAR = (".vcs", ".ics", ".backup") class BackupTest(unittest.TestCase): def perform_test(self, filename, extensions): out_files = [ tempfile.NamedTemporaryFile(suffix=extension, delete=False) for extension in extensions ] out_backup = tempfile.NamedTemporaryFile(suffix=".backup", delete=False) # Close all files (needed on Windows) for handle in out_files: handle.close() out_backup.close() try: backup = gammu.ReadBackup(filename) for out in out_files: # Save to new format gammu.SaveBackup(out.name, backup) # Parse created file backup_2 = gammu.ReadBackup(out.name) # Check content length self.assertEqual( len(backup["Calendar"]), len(backup_2["Calendar"]), f"Failed to compare calendar in {filename}", ) self.assertEqual( len(backup["PhonePhonebook"]) + len(backup["SIMPhonebook"]), len(backup_2["PhonePhonebook"]) + len(backup_2["SIMPhonebook"]), f"Failed to compare phonebook in {filename}", ) # Try converting to .backup gammu.SaveBackup(out_backup.name, backup) finally: for handle in out_files: os.unlink(handle.name) os.unlink(out_backup.name) def test_convert_contacts(self): for filename in TEST_FILES_CONTACTS: self.perform_test(filename, TEST_CONTACTS) def test_convert_calendar(self): for filename in TEST_FILES_CALENDAR: self.perform_test(filename, TEST_CALENDAR) def test_calendar(self): entry = gammu.ReadBackup(os.path.join(TEST_DIR, "rrule.ics"))["Calendar"][0] # Convert it to vCard vc_entry = gammu.EncodeVCALENDAR(entry) ic_entry = gammu.EncodeICALENDAR(entry) # Convert it back to entry entry2 = gammu.DecodeVCS(vc_entry) entry3 = gammu.DecodeICS(ic_entry) self.assertEqual(entry2["Type"], entry3["Type"]) def test_todo(self): entry = gammu.ReadBackup(os.path.join(TEST_DIR, "02.vcs"))["ToDo"][0] # Convert it to vCard vt_entry = gammu.EncodeVTODO(entry) it_entry = gammu.EncodeITODO(entry) # Convert it back to entry entry2 = gammu.DecodeVCS(vt_entry) entry3 = gammu.DecodeICS(it_entry) self.assertEqual(entry2["Type"], entry3["Type"]) def test_contact(self): entry = gammu.ReadBackup(os.path.join(TEST_DIR, "gammu.vcf"))["PhonePhonebook"][ 0 ] # Convert it to vCard vc_entry = gammu.EncodeVCARD(entry) # Convert it back to entry entry2 = gammu.DecodeVCARD(vc_entry) self.assertEqual(entry, entry2) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_config.py0000644000175000017500000001077000000000000016774 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import os import tempfile import unittest import gammu from .test_sms import PDU_DATA class ConfigTest(unittest.TestCase): def test_config_bool(self): state_machine = gammu.StateMachine() state_machine.SetConfig( 0, { "StartInfo": True, "UseGlobalDebugFile": True, "DebugFile": None, "SyncTime": True, "Connection": "at", "LockDevice": True, "DebugLevel": "textalldate", "Device": "", "Model": "", }, ) cfg = state_machine.GetConfig(0) self.assertEqual(cfg["StartInfo"], 1) def test_config_string(self): state_machine = gammu.StateMachine() state_machine.SetConfig( 0, { "StartInfo": "yes", "UseGlobalDebugFile": "no", "DebugFile": "dbg.log", "SyncTime": "true", "Connection": "fbus", "LockDevice": "FALSE", "DebugLevel": "textall", "Device": "", "Model": "", }, ) cfg = state_machine.GetConfig(0) self.assertEqual(cfg["StartInfo"], 1) def test_config_none(self): state_machine = gammu.StateMachine() state_machine.SetConfig( 0, { "StartInfo": None, "UseGlobalDebugFile": None, "DebugFile": "dbg.log", "SyncTime": "true", "Connection": "dlr3", "LockDevice": "NO", "DebugLevel": "binary", "Device": "", "Model": "", }, ) cfg = state_machine.GetConfig(0) self.assertEqual(cfg["StartInfo"], 0) def test_init_error(self): self.assertRaises(TypeError, gammu.StateMachine, Bar=1) class DebugTest(unittest.TestCase): def setUp(self): gammu.SetDebugLevel("textall") def check_operation(self, filename, handle=None): """ Executes gammu operation which causes debug logs. """ gammu.DecodePDU(PDU_DATA) gammu.SetDebugFile(None) if handle: handle.close() if filename is not None: with open(filename) as handle: self.assertTrue("SMS type: Status report" in handle.read()) def test_file(self): testfile = tempfile.NamedTemporaryFile(suffix=".debug", delete=False) testfile.close() try: handle = open(testfile.name, "w") gammu.SetDebugFile(handle) self.check_operation(testfile.name, handle) finally: gammu.SetDebugFile(None) os.unlink(testfile.name) def test_filename(self): testfile = tempfile.NamedTemporaryFile(suffix=".debug", delete=False) testfile.close() try: gammu.SetDebugFile(testfile.name) self.check_operation(testfile.name) finally: gammu.SetDebugFile(None) os.unlink(testfile.name) def test_none(self): gammu.SetDebugFile(None) self.check_operation(None) def test_nothing(self): gammu.SetDebugLevel("nothing") testfile = tempfile.NamedTemporaryFile(suffix=".debug", delete=False) testfile.close() try: gammu.SetDebugFile(testfile.name) self.check_operation(None) with open(testfile.name) as handle: self.assertEqual("", handle.read()) finally: gammu.SetDebugFile(None) os.unlink(testfile.name) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_data.py0000644000175000017500000000227100000000000016435 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import unittest import gammu.data class DataTest(unittest.TestCase): def test_connections(self): self.assertTrue("at" in gammu.data.Connections) def test_errors(self): self.assertTrue("ERR_INSTALL_NOT_FOUND" in gammu.data.Errors) self.assertEqual(gammu.data.ErrorNumbers[73], "ERR_NETWORK_ERROR") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_dummy.py0000644000175000017500000003062700000000000016665 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import datetime import os.path import platform import shutil import tempfile import unittest import gammu DUMMY_DIR = os.path.join(os.path.dirname(__file__), "data", "gammu-dummy") TEST_FILE = os.path.join(os.path.dirname(__file__), "data", "sqlite-14.sql") CONFIGURATION = """ # Configuration for Gammu testsuite [gammu] model = dummy connection = none port = {path}/gammu-dummy gammuloc = /dev/null logformat = none [smsd] commtimeout = 1 debuglevel = 255 logfile = stderr service = sql driver = sqlite3 sql = sqlite database = smsd.db dbdir = {path} """ class DummyTest(unittest.TestCase): test_dir = None config_name = None dummy_dir = None _called = False _state_machine = None def setUp(self): self.test_dir = tempfile.mkdtemp() self.dummy_dir = os.path.join(self.test_dir, "gammu-dummy") self.config_name = os.path.join(self.test_dir, ".gammurc") shutil.copytree(DUMMY_DIR, self.dummy_dir) with open(self.config_name, "w") as handle: handle.write(CONFIGURATION.format(path=self.test_dir)) def tearDown(self): if self._state_machine: self._state_machine.Terminate() shutil.rmtree(self.test_dir) def get_statemachine(self): state_machine = gammu.StateMachine() state_machine.ReadConfig(Filename=self.config_name) state_machine.Init() self._state_machine = state_machine return state_machine def fake_incoming_call(self): """Fake incoming call""" filename = os.path.join(self.dummy_dir, "incoming-call") with open(filename, "w") as handle: handle.write("\n") def check_incoming_call(self): """Checks whether incoming call faking is supported""" current = tuple(int(x) for x in gammu.Version()[2].split(".")) if current < (1, 37, 91): raise unittest.SkipTest(f"Not supported in version {gammu.Version()[2]}") def call_callback(self, state_machine, response, data): """ Callback on USSD data. """ self._called = True self.assertEqual(response, "Call") self.assertEqual(data["Number"], "+800123456") class BasicDummyTest(DummyTest): def test_model(self): state_machine = self.get_statemachine() self.assertEqual(state_machine.GetModel()[1], "Dummy") def test_diverts(self): state_machine = self.get_statemachine() diverts = state_machine.GetCallDivert() self.assertEqual( diverts, [{"CallType": "All", "Timeout": 0, "Number": "", "DivertType": "AllTypes"}], ) state_machine.SetCallDivert("AllTypes", "All", "123456789") diverts = state_machine.GetCallDivert() self.assertEqual( diverts, [ { "CallType": "All", "Timeout": 0, "Number": "123456789", "DivertType": "AllTypes", } ], ) def test_dial(self): state_machine = self.get_statemachine() state_machine.DialVoice("123456") def test_battery(self): state_machine = self.get_statemachine() status = state_machine.GetBatteryCharge() self.assertEqual( status, { "BatteryVoltage": 4200, "PhoneTemperature": 22, "BatteryTemperature": 22, "ChargeState": "BatteryConnected", "ChargeVoltage": 4200, "BatteryCapacity": 2000, "BatteryPercent": 100, "ChargeCurrent": 0, "PhoneCurrent": 500, }, ) def test_memory(self): state_machine = self.get_statemachine() status = state_machine.GetMemoryStatus(Type="ME") remain = status["Used"] self.assertEqual(status["Used"], 3) start = True while remain > 0: if start: entry = state_machine.GetNextMemory(Start=True, Type="ME") start = False else: entry = state_machine.GetNextMemory( Location=entry["Location"], Type="ME" ) remain = remain - 1 def test_getmemory(self): state_machine = self.get_statemachine() location = state_machine.AddMemory( { "MemoryType": "SM", "Entries": [ {"Type": "Number_Mobile", "Value": "123456"}, {"Type": "Text_Name", "Value": "Jmeno"}, ], } ) read = state_machine.GetMemory("SM", location) self.assertEqual(len(read["Entries"]), 2) def test_calendar(self): state_machine = self.get_statemachine() status = state_machine.GetCalendarStatus() remain = status["Used"] self.assertEqual(status["Used"], 2) start = True while remain > 0: if start: entry = state_machine.GetNextCalendar(Start=True) start = False else: entry = state_machine.GetNextCalendar(Location=entry["Location"]) remain = remain - 1 def test_sms(self): state_machine = self.get_statemachine() status = state_machine.GetSMSStatus() remain = status["SIMUsed"] + status["PhoneUsed"] + status["TemplatesUsed"] self.assertEqual(remain, 6) start = True sms = [] while remain > 0: if start: sms.append(state_machine.GetNextSMS(Start=True, Folder=0)) start = False else: sms.append( state_machine.GetNextSMS(Location=sms[-1][0]["Location"], Folder=0) ) remain = remain - len(sms) data = gammu.LinkSMS(sms) for item in data: message = gammu.DecodeSMS(item) if message is None: self.assertEqual(item[0]["UDH"]["Type"], "NoUDH") def test_todo(self): state_machine = self.get_statemachine() status = state_machine.GetToDoStatus() remain = status["Used"] self.assertEqual(status["Used"], 2) start = True while remain > 0: if start: entry = state_machine.GetNextToDo(Start=True) start = False else: entry = state_machine.GetNextToDo(Location=entry["Location"]) remain = remain - 1 def test_sms_folders(self): state_machine = self.get_statemachine() folders = state_machine.GetSMSFolders() self.assertEqual(len(folders), 5) def ussd_callback(self, state_machine, response, data): """ Callback on USSD data. """ self._called = True self.assertEqual(response, "USSD") self.assertEqual(data["Text"], "Reply for 1234") self.assertEqual(data["Status"], "NoActionNeeded") def test_ussd(self): self._called = False state_machine = self.get_statemachine() state_machine.SetIncomingCallback(self.ussd_callback) state_machine.SetIncomingUSSD() state_machine.DialService("1234") self.assertTrue(self._called) def test_sendsms(self): state_machine = self.get_statemachine() message = { "Text": "python-gammu testing message", "SMSC": {"Location": 1}, "Number": "123456", } state_machine.SendSMS(message) def test_sendsms_long(self): state_machine = self.get_statemachine() text = ( "Very long python-gammu testing message sent " "from example python script. " ) * 10 smsinfo = { "Class": -1, "Unicode": False, "Entries": [{"ID": "ConcatenatedTextLong", "Buffer": text}], } # Encode messages encoded = gammu.EncodeSMS(smsinfo) self.assertEqual(len(encoded), 5) # Send messages for message in encoded: # Fill in numbers message["SMSC"] = {"Location": 1} message["Number"] = "123456" # Actually send the message state_machine.SendSMS(message) def test_filesystem(self): state_machine = self.get_statemachine() fs_info = state_machine.GetFileSystemStatus() self.assertEqual( fs_info, { "UsedImages": 0, "Used": 1000000, "UsedThemes": 0, "Free": 10101, "UsedSounds": 0, }, ) def test_deletefile(self): state_machine = self.get_statemachine() self.assertRaises( gammu.ERR_FILENOTEXIST, state_machine.DeleteFile, "testfolder/nonexisting.png", ) state_machine.DeleteFile("file5") def test_deletefolder(self): state_machine = self.get_statemachine() self.assertRaises( gammu.ERR_FILENOTEXIST, state_machine.DeleteFolder, "testfolder" ) state_machine.AddFolder("", "testfolder") state_machine.DeleteFolder("testfolder") @unittest.skipIf(platform.system() == "Windows", "Not supported on Windows") def test_emoji_folder(self): state_machine = self.get_statemachine() name = "test-😘" self.assertRaises(gammu.ERR_FILENOTEXIST, state_machine.DeleteFolder, name) self.assertEqual(name, state_machine.AddFolder("", name)) # Check the folder exists as expected on filesystem self.assertTrue(os.path.exists(os.path.join(self.dummy_dir, "fs", name))) state_machine.DeleteFolder(name) def test_addfile(self): state_machine = self.get_statemachine() file_stat = os.stat(TEST_FILE) ttime = datetime.datetime.fromtimestamp(file_stat[8]) with open(TEST_FILE, "rb") as handle: content = handle.read() file_f = { "ID_FullName": "testfolder", "Name": "sqlite.sql", "Modified": ttime, "Folder": 0, "Level": 1, "Used": file_stat[6], "Buffer": content, "Type": "Other", "Protected": 0, "ReadOnly": 0, "Hidden": 0, "System": 0, "Handle": 0, "Pos": 0, "Finished": 0, } state_machine.AddFolder("", "testfolder") while not file_f["Finished"]: file_f = state_machine.AddFilePart(file_f) def test_fileattributes(self): state_machine = self.get_statemachine() state_machine.SetFileAttributes( "file5", ReadOnly=1, Protected=0, System=1, Hidden=1 ) def test_getnextfile(self): state_machine = self.get_statemachine() file_f = state_machine.GetNextFileFolder(1) folders = 0 files = 0 while 1: if file_f["Folder"]: folders += 1 else: files += 1 try: file_f = state_machine.GetNextFileFolder(0) except gammu.ERR_EMPTY: break self.assertEqual(folders, 3) self.assertEqual(files, 6) def test_incoming_call(self): self.check_incoming_call() self._called = False state_machine = self.get_statemachine() state_machine.SetIncomingCallback(self.call_callback) state_machine.SetIncomingCall() state_machine.GetSignalQuality() self.fake_incoming_call() state_machine.GetSignalQuality() self.assertTrue(self._called) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534398.0 python-gammu-3.2.4/test/test_errors.py0000644000175000017500000000217700000000000017045 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import unittest import gammu.exception def error_function(): raise gammu.exception.ERR_WRONGCRC() class ErrorTest(unittest.TestCase): def test_catching(self): self.assertRaises( gammu.exception.GSMError, error_function, ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_sms.py0000644000175000017500000001435000000000000016327 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import binascii import datetime import os import sys import unittest import gammu PDU_DATA = binascii.unhexlify( b"079124602009999002AB098106845688F8907080517375809070805183018000" ) MESSAGE = ( ".........1.........2.........3.........4.........5.........6.........7" ".........8.........9........0.........1.........2.........3.........4" ".........5.........6.........7.........8.........9........0.........1" ".........2.........3.........4.........5.........6.........7.........8" ".........9........0" ) UNICODE = ( ".........1ě........2..ř......3...žš....4....ý....5....á....6....á....7" ".........8.........9........0.........1.........2.........3.........4" ".........5.........6.........7.........8.........9........0.........1" ".........2.........3.........4.........5.........6.........7.........8" ".........9....č...0" ) GSM = ( ".........1$........2..Ø......3...åÅ....4....Λ....5....Æ....6....ñ....7" ".........8.........9........0.........1.........2.........3.........4" ".........5.........6.........7.........8.........9........0.........1" ".........2.........3.........4.........5.........6.........7.........8" ".........9....¥€..0" ) class PDUTest(unittest.TestCase): def setUp(self): if "GAMMU_DEBUG" in os.environ: gammu.SetDebugFile(sys.stderr) gammu.SetDebugLevel("textall") def test_decode(self): sms = gammu.DecodePDU(PDU_DATA) self.assertEqual(sms["Number"], "604865888") self.assertEqual(sms["Text"], "Delivered") def do_smstest(self, smsinfo, expected): # encode SMSes sms = gammu.EncodeSMS(smsinfo) # decode back SMSes decodedsms = gammu.DecodeSMS(sms) # compare text self.assertEqual(decodedsms["Entries"][0]["Buffer"], expected) # do conversion to PDU pdu = [gammu.EncodePDU(s) for s in sms] # Convert back pdusms = [gammu.DecodePDU(p) for p in pdu] # decode back SMS from PDU decodedsms = gammu.DecodeSMS(pdusms) # compare PDU results self.assertEqual(decodedsms["Entries"][0]["Buffer"], expected) def test_encode_plain(self): smsinfo = {"Entries": [{"ID": "ConcatenatedTextLong", "Buffer": MESSAGE}]} self.do_smstest(smsinfo, MESSAGE) def test_encode_gsm(self): smsinfo = {"Entries": [{"ID": "ConcatenatedTextLong", "Buffer": GSM}]} self.do_smstest(smsinfo, GSM) def test_encode_unicode(self): smsinfo = { "Entries": [{"ID": "ConcatenatedTextLong", "Buffer": UNICODE}], "Unicode": True, } self.do_smstest(smsinfo, UNICODE) def test_link(self): # SMS info about message smsinfo = {"Entries": [{"ID": "ConcatenatedTextLong", "Buffer": MESSAGE}]} # encode SMS sms = gammu.EncodeSMS(smsinfo) # link SMS linked = gammu.LinkSMS([[sms[0]], [sms[1]]], True) # decode back SMS decodedsms = gammu.DecodeSMS(linked[0]) # compare results self.assertTrue(decodedsms["Entries"][0]["Buffer"], MESSAGE) def test_mms_decode(self): message = [ { "RejectDuplicates": 0, "SMSCDateTime": datetime.datetime(2010, 7, 22, 17, 4, 11), "Class": -1, "Name": "", "InboxFolder": 0, "Text": ( b"\x04\x06\x03\xbe\xaf\x84\x8c\x82\x981277970059\x00\x8d\x92" b"\x89\x19\x80\x16\x0433707520030/TYPE=PLMN\x00\x96yBO\x00" b'\x8a\x80\x8e\x01"\x88\x04\x81\x02\x0b\xb8\x83' b"http://mmsc.labmctel.fr:9090/m33\x00" ), "SMSC": { "DefaultNumber": "", "Format": "Text", "Number": "+33700065030", "Validity": "NA", "Location": 0, "Name": "", }, "ReplaceMessage": 0, "Coding": "8bit", "Number": "33707520030", "DateTime": datetime.datetime(2010, 7, 1, 9, 40, 21), "DeliveryStatus": 0, "State": "UnSent", "MessageReference": 0, "Length": 99, "Location": 0, "Memory": "", "ReplyViaSameSMSC": 0, "UDH": { "Text": b"\x06\x05\x04\x0b\x84#\xf0", "ID16bit": -1, "AllParts": -1, "ID8bit": -1, "PartNumber": -1, "Type": "UserUDH", }, "Type": "Deliver", "Folder": 2, } ] decoded = gammu.DecodeSMS(message) self.assertEqual( decoded["Entries"][0]["MMSIndicator"]["Address"], "http://mmsc.labmctel.fr:9090/m33", ) def test_counter(self): self.assertEqual(gammu.SMSCounter("foobar"), (1, 154)) def test_counter_long(self): self.assertEqual( gammu.SMSCounter( "foobar fjsa;kjfkasdjfkljsklfjaskdljfkljasdfkljqilui143uu51o2" "3rjhskdf jasdklfjasdklf jasdfkljasdlkfj;asd;lfjaskdljf431ou9" "83jdfaskljfklsdjdkljasfl sdfjasdfkl jafklsda" ), (2, 156), ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_smsd.py0000644000175000017500000000740100000000000016472 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import os import os.path import platform import sqlite3 import threading import time import unittest import gammu.smsd from .test_dummy import DummyTest MESSAGE_1 = { "Text": "python-gammu testing message", "SMSC": {"Location": 1}, "Number": "1234567890", } MESSAGE_2 = { "Text": "python-gammu second testing message", "SMSC": {"Location": 1}, "Number": "1234567890", } def get_script(): """Returns SQL script to create database It returns correct script matching used Gammu version. """ version = tuple(int(x) for x in gammu.Version()[0].split(".")) if version < (1, 36, 7): dbver = 14 elif version < (1, 37, 90): dbver = 15 elif version < (1, 38, 5): dbver = 16 else: dbver = 17 print(f"Gammu version {version}, SMSD DB version {dbver}") return os.path.join(os.path.dirname(__file__), "data", f"sqlite-{dbver}.sql") class SMSDDummyTest(DummyTest): def setUp(self): if platform.system() == "Windows": raise unittest.SkipTest( "SMSD testing not supported on Windows (no DBI driver)" ) super().setUp() database = sqlite3.connect(os.path.join(self.test_dir, "smsd.db")) with open(get_script()) as handle: database.executescript(handle.read()) def get_smsd(self): return gammu.smsd.SMSD(self.config_name) def test_init_error(self): self.assertRaises(TypeError, gammu.smsd.SMSD, Bar=1) def test_inject(self): smsd = self.get_smsd() smsd.InjectSMS([MESSAGE_1]) def test_smsd(self): smsd = self.get_smsd() # Inject SMS messages # Please note that SMSD is not thread safe, so you can not # use inject and main loop from different threads smsd.InjectSMS([MESSAGE_1]) smsd.InjectSMS([MESSAGE_2]) try: # Start SMSD thread smsd_thread = threading.Thread(target=smsd.MainLoop) smsd_thread.start() # We need to let it run for some time here to finish initialization time.sleep(10) # Show SMSD status retries = 0 while retries < 2: status = smsd.GetStatus() if status["Sent"] >= 2: break time.sleep(10) retries += 1 self.assertEqual( status["Received"], 2, "Messages were not received as expected ({:d})!".format( status["Received"] ), ) self.assertEqual( status["Sent"], 2, "Messages were not sent as expected ({:d})!".format(status["Sent"]), ) time.sleep(1) finally: # Signal SMSD to stop smsd.Shutdown() # Wait for it smsd_thread.join() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1628534540.0 python-gammu-3.2.4/test/test_worker.py0000644000175000017500000002672100000000000017043 0ustar00nijelnijel# vim: expandtab sw=4 ts=4 sts=4: # # Copyright © 2003 - 2018 Michal Čihař # # This file is part of python-gammu # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import gammu.worker from .test_dummy import DummyTest WORKER_EXPECT = [ ("Init", None, "ERR_NONE", 100), ("GetManufacturer", "Gammu", "ERR_NONE", 100), ("GetSIMIMSI", "994299429942994", "ERR_NONE", 100), ("GetIMEI", "999999999999999", "ERR_NONE", 100), ("GetOriginalIMEI", "666666666666666", "ERR_NONE", 100), ("GetManufactureMonth", "April", "ERR_NONE", 100), ("GetProductCode", "DUMMY-001", "ERR_NONE", 100), ("GetHardware", "FOO DUMMY BAR", "ERR_NONE", 100), ("CustomGetInfo", ("unknown", "Dummy"), "ERR_NONE", 50), ( "CustomGetInfo", { "BatteryVoltage": 4200, "PhoneTemperature": 22, "BatteryTemperature": 22, "ChargeState": "BatteryConnected", "ChargeVoltage": 4200, "BatteryCapacity": 2000, "BatteryPercent": 100, "ChargeCurrent": 0, "PhoneCurrent": 500, }, "ERR_NONE", 100, ), ( "GetMemory", { "MemoryType": "SM", "Location": 1, "Entries": [ { "AddError": 1, "Type": "Text_Name", "Location": "Unknown", "Value": "firstname lastname", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test1", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test2", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test3", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test4", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test5", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test6", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test7", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test8", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test9", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test10", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test11", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test12", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test13", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test14", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test15", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test16", }, ], }, "ERR_NONE", 100, ), ( "CustomGetAllMemory", { "MemoryType": "SM", "Location": 1, "Entries": [ { "AddError": 1, "Type": "Text_Name", "Location": "Unknown", "Value": "firstname lastname", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test1", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test2", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test3", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test4", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test5", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test6", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test7", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test8", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test9", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test10", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test11", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test12", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test13", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test14", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test15", }, { "AddError": 1, "Type": "Text_Note", "Location": "Unknown", "Value": "Test16", }, ], }, "ERR_NONE", 20, ), ("CustomGetAllMemory", None, "ERR_EMPTY", 40), ("CustomGetAllMemory", None, "ERR_EMPTY", 60), ("CustomGetAllMemory", None, "ERR_EMPTY", 80), ("CustomGetAllMemory", None, "ERR_EMPTY", 100), ( "GetSMSC", { "DefaultNumber": "", "Format": "Text", "Number": "123456", "Validity": "NA", "Location": 1, "Name": "Default", }, "ERR_NONE", 100, ), ("Terminate", None, "ERR_NONE", 100), ] class WorkerDummyTest(DummyTest): results = [] def callback(self, name, result, error, percents): self.results.append((name, result, error, percents)) def test_worker(self): self.results = [] worker = gammu.worker.GammuWorker(self.callback) worker.configure(self.get_statemachine().GetConfig()) # We can directly invoke commands worker.enqueue("GetManufacturer") worker.enqueue("GetSIMIMSI") worker.enqueue("GetIMEI") worker.enqueue("GetOriginalIMEI") worker.enqueue("GetManufactureMonth") worker.enqueue("GetProductCode") worker.enqueue("GetHardware") worker.enqueue("GetDateTime") # We can create compound tasks worker.enqueue("CustomGetInfo", commands=["GetModel", "GetBatteryCharge"]) # We can pass parameters worker.enqueue("GetMemory", ("SM", 1)) # We can create compound tasks with parameters: worker.enqueue( "CustomGetAllMemory", commands=[ ("GetMemory", ("SM", 1)), ("GetMemory", ("SM", 2)), ("GetMemory", ("SM", 3)), ("GetMemory", ("SM", 4)), ("GetMemory", ("SM", 5)), ], ) worker.initiate() # We can also pass commands with named parameters worker.enqueue("GetSMSC", {"Location": 1}) worker.terminate() # Remove GetDateTime from comparing as the value changes for i in range(len(self.results)): if self.results[i][0] == "GetDateTime": self.assertEqual(self.results[i][2], "ERR_NONE") self.assertEqual(self.results[i][3], 100) del self.results[i] break self.maxDiff = None self.assertEqual(WORKER_EXPECT, self.results) def test_incoming(self): self.check_incoming_call() self.results = [] self._called = False worker = gammu.worker.GammuWorker(self.callback) worker.configure(self.get_statemachine().GetConfig()) worker.initiate() worker.enqueue("SetIncomingCallback", (self.call_callback,)) worker.enqueue("SetIncomingCall") self.fake_incoming_call() worker.terminate() self.assertTrue(self._called)