Repository: vysheng/tgl Branch: master Commit: ffb04caca71d Files: 88 Total size: 1.3 MB Directory structure: gitextract_7j9eshnc/ ├── .gitignore ├── .gitmodules ├── CHANGELOG ├── LICENSE ├── Makefile.in ├── Makefile.tl-parser ├── README.md ├── append.tl ├── auto-static-autocomplete.c ├── auto-static-fetch.c ├── auto-static-print-ds.c ├── auto-static-skip.c ├── auto-static-store.c ├── auto-static.c ├── auto.h ├── binlog.c ├── binlog.tl ├── config.h.in ├── configure ├── configure.ac ├── crypto/ │ ├── aes.h │ ├── aes_altern.c │ ├── aes_openssl.c │ ├── bn.h │ ├── bn_altern.c │ ├── bn_openssl.c │ ├── err.h │ ├── err_altern.c │ ├── err_openssl.c │ ├── md5.h │ ├── md5_altern.c │ ├── md5_openssl.c │ ├── meta.h │ ├── rand.h │ ├── rand_altern.c │ ├── rand_openssl.c │ ├── rsa_pem.h │ ├── rsa_pem_altern.c │ ├── rsa_pem_openssl.c │ ├── sha.h │ ├── sha_altern.c │ └── sha_openssl.c ├── encrypted_scheme.tl ├── errors ├── event-old.h ├── gen_constants_h.awk ├── generate.c ├── generate.h ├── m4_ax_check_openssl.m4 ├── m4_ax_check_zlib.m4 ├── mime-types.c ├── mime.types ├── mtproto-client.c ├── mtproto-client.h ├── mtproto-common.c ├── mtproto-common.h ├── mtproto-key.c ├── mtproto-key.h ├── mtproto-utils.c ├── mtproto-utils.h ├── mtproto.tl ├── no-preview.h ├── queries-encrypted.c ├── queries.c ├── queries.h ├── scheme.tl ├── structures.c ├── tg-mime-types.c ├── tg-mime-types.h ├── tgl-binlog.h ├── tgl-fetch.h ├── tgl-inner.h ├── tgl-layout.h ├── tgl-methods-in.h ├── tgl-net-inner.h ├── tgl-net.c ├── tgl-net.h ├── tgl-queries.h ├── tgl-structures.h ├── tgl-timers.c ├── tgl-timers.h ├── tgl.c ├── tgl.h ├── tools.c ├── tools.h ├── tree.h ├── updates.c └── updates.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ Makefile autom4te.cache config.h config.log config.status .idea/ nbproject/ bin/ objs/ dep/ auto/ libs/ ================================================ FILE: .gitmodules ================================================ [submodule "tl-parser"] path = tl-parser url = https://github.com/vysheng/tl-parser ================================================ FILE: CHANGELOG ================================================ 2.0.3 * updated to layer 31 (bot support) * changed signature of contact_search method 2.0.2 * fixed small bugs * added block/unblock user method 2.0.1 * store error code for last operation in TLS->error/TLS->error_code * make interface more consitent * deleted outdated *_ex functions * fixed bugs * support for layer 28: * support for new pts system * support for new read system * support for passwords * support replies * support photo captions * support group links 1.2.1 * fixed registration/login problem * added extension to downloads 1.2.0 * layer 22 support ================================================ FILE: LICENSE ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the library's name and an idea of what it does. Copyright (C) year name of author This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. signature of Ty Coon, 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: Makefile.in ================================================ srcdir=@srcdir@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ @OPENSSL_LDFLAGS@ CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ DEFS=@DEFS@ COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ LOCAL_LDFLAGS=-rdynamic -ggdb ${EXTRA_LIBS} LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} DEP=dep AUTO=auto OBJ=objs LIB=libs EXE=bin DIR_LIST=${DEP} ${DEP}/crypto ${AUTO} ${EXE} ${OBJ} ${OBJ}/crypto ${LIB} ${DEP}/auto ${OBJ}/auto LIB_LIST=${LIB}/libtgl.a ${LIB}/libtgl.so TGL_OBJECTS=${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/mtproto-key.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/tgl.o ${OBJ}/updates.o ${OBJ}/tg-mime-types.o ${OBJ}/mtproto-utils.o ${OBJ}/crypto/bn_openssl.o ${OBJ}/crypto/bn_altern.o ${OBJ}/crypto/rsa_pem_openssl.o ${OBJ}/crypto/rsa_pem_altern.o ${OBJ}/crypto/md5_openssl.o ${OBJ}/crypto/md5_altern.o ${OBJ}/crypto/sha_openssl.o ${OBJ}/crypto/sha_altern.o ${OBJ}/crypto/aes_openssl.o ${OBJ}/crypto/aes_altern.o @EXTRA_OBJECTS@ TGL_OBJECTS_AUTO=${OBJ}/auto/auto-skip.o ${OBJ}/auto/auto-fetch.o ${OBJ}/auto/auto-store.o ${OBJ}/auto/auto-autocomplete.o ${OBJ}/auto/auto-types.o ${OBJ}/auto/auto-fetch-ds.o ${OBJ}/auto/auto-free-ds.o ${OBJ}/auto/auto-store-ds.o ${OBJ}/auto/auto-print-ds.o TLD_OBJECTS=${OBJ}/dump-tl-file.o GENERATE_OBJECTS=${OBJ}/generate.o COMMON_OBJECTS=${OBJ}/tools.o ${OBJ}/crypto/rand_openssl.o ${OBJ}/crypto/rand_altern.o ${OBJ}/crypto/err_openssl.o ${OBJ}/crypto/err_altern.o OBJ_C=${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS} DEPENDENCE=$(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJ_C})) DEPENDENCE_LIST=${DEPENDENCE} INCLUDE=-I. -I${srcdir} CC=@CC@ .SUFFIXES: .SUFFIXES: .c .h .o all: ${LIB_LIST} create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h create_dirs: ${DIR_LIST} dump-tl: ${EXE}/dump-tl-file include ${srcdir}/Makefile.tl-parser ${DIR_LIST}: @test -d $@ || mkdir -p $@ -include ${DEPENDENCE_LIST} ${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/auto-fetch-ds.h ${AUTO}/auto-free-ds.h ${AUTO}/auto-store-ds.h ${AUTO}/auto-print-ds.h ${OBJ_C}: ${OBJ}/%.o: ${srcdir}/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< ${TGL_OBJECTS_AUTO}: ${OBJ}/auto/%.o: ${AUTO}/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< ${LIB}/libtgl.a: ${TGL_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS_AUTO} rm -f $@ && ar ruv $@ $^ ${LIB}/libtgl.so: ${TGL_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS_AUTO} ${CC} -shared -o $@ $^ ${LINK_FLAGS} ${EXE}/generate: ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${CC} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${LINK_FLAGS} -o $@ ${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tl-parser ${EXE}/tl-parser -e $@ ${AUTO}/scheme.tl ${AUTO}/scheme.tl: ${srcdir}/scheme.tl ${srcdir}/encrypted_scheme.tl ${srcdir}/binlog.tl ${srcdir}/mtproto.tl ${srcdir}/append.tl | ${AUTO} cat $^ > $@ ${AUTO}/scheme2.tl: ${AUTO}/scheme.tl ${EXE}/tl-parser ${EXE}/tl-parser -E ${AUTO}/scheme.tl 2> $@ || ( cat $@ && rm $@ && false ) ${AUTO}/auto.c: ${AUTO}/scheme.tlo ${EXE}/generate ${EXE}/generate ${AUTO}/scheme.tlo > $@ ${AUTO}/auto-%.c: ${AUTO}/scheme.tlo ${EXE}/generate auto/constants.h ${AUTO}/auto-%.h | create_dirs_and_headers ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.c,%,$@) ${AUTO}/scheme.tlo > $@ || ( rm $@ && false ) ${AUTO}/auto-%.h: ${AUTO}/scheme.tlo ${EXE}/generate ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.h,%-header,$@) ${AUTO}/scheme.tlo > $@ || ( rm $@ && false ) ${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/gen_constants_h.awk awk -f ${srcdir}/gen_constants_h.awk < $< > $@ ${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@ clean: rm -rf ${DIR_LIST} distclean: rm -rf ${DIR_LIST} config.h config.log config.status mime-types.c: mime.types @echo "// DO NOT EDIT! SEE MAKE-TARGET 'gen-mime-types'" > mime-types.c # xxd is usually packaged with vim-common xxd -i mime.types >> mime-types.c ================================================ FILE: Makefile.tl-parser ================================================ TL_PARSER_OBJECTS=${OBJ}/tl-parser.o ${OBJ}/tlc.o ${TL_PARSER_OBJECTS}: ${OBJ}/%.o: ${srcdir}/tl-parser/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tl-parser -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< ${EXE}/tl-parser: ${TL_PARSER_OBJECTS} ${CC} $^ ${LINK_FLAGS} -o $@ ================================================ FILE: README.md ================================================ This is library that handles telegram api and protocol. Current versions: - scheme.tl: Layer 38 - encrypted_scheme.tl: Layer 23 ### API, Protocol documentation Documentation for Telegram API is available here: https://core.telegram.org/api Documentation for MTproto protocol is available here: https://core.telegram.org/mtproto ### Installation Clone GitHub Repository git clone --recursive https://github.com/vysheng/tgl.git && cd tgl #### Linux and BSDs Install libs: openssl, zlib if you want to use provided net/timers then install libevent and add --enable-libevent key to configure You can also avoid the OpenSSL dependency: Install gcrypt (>= 1.60, Debian derivates know it as "libgcrypt20-dev"), and add --disable-openssl key to configure Then, ./configure make ### Contacts If you would like to ask a question, you can write to my telegram or to the github (or both). To contact me via telegram, you should use import_card method with argument 000653bf:0738ca5d:5521fbac:29246815:a27d0cda ================================================ FILE: append.tl ================================================ ---types--- decryptedMessageMediaVideoL12#4cee6ef3 str_thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia; decryptedMessageMediaAudioL12#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia; updateMsgUpdate id:int pts:int pts_count:int = Update; messageMediaPhotoL27#c8c45a2a photo:Photo = MessageMedia; messageMediaVideoL27#a2d24290 video:Video = MessageMedia; //messageMediaDocumentL27#2fda2204 document:Document = MessageMedia; //messageMediaAudioL27#c6b68300 audio:Audio = MessageMedia; ---functions--- ================================================ FILE: auto-static-autocomplete.c ================================================ #include #include "config.h" #define IN_AUTOCOMPLETE_H #include "auto-static-store.c" #undef IN_AUTOCOMPLETE_H static int autocomplete_mode; static char *autocomplete_string; static int (*autocomplete_fun)(const char *, int, int, char **); static void set_autocomplete_string (const char *s) { if (autocomplete_string) { free (autocomplete_string); } autocomplete_string = strdup (s); assert (autocomplete_string); autocomplete_mode = 1; } static void set_autocomplete_type (int (*f)(const char *, int, int, char **)) { autocomplete_fun = f; autocomplete_mode = 2; } #define MAX_FVARS 100 static struct paramed_type *fvars[MAX_FVARS]; static int fvars_pos; static void add_var_to_be_freed (struct paramed_type *P) { assert (fvars_pos < MAX_FVARS); fvars[fvars_pos ++] = P; } static void free_vars_to_be_freed (void) { int i; for (i = 0; i < fvars_pos; i++) { tgl_paramed_type_free (fvars[i]); } fvars_pos = 0; } int tglf_extf_autocomplete (struct tgl_state *TLS, const char *text, int text_len, int index, char **R, char *data, int data_len) { #ifdef DISABLE_EXTF (void) free_vars_to_be_freed; assert (0); #else if (index == -1) { buffer_pos = data; buffer_end = data + data_len; autocomplete_mode = 0; local_next_token (); struct paramed_type *P = autocomplete_function_any (); free_vars_to_be_freed (); if (P) { tgl_paramed_type_free (P); } } if (autocomplete_mode == 0) { return -1; } int len = strlen (text); if (autocomplete_mode == 1) { if (index >= 0) { return -1; } index = 0; if (!strncmp (text, autocomplete_string, len)) { *R = strdup (autocomplete_string); assert (*R); return index; } else { return -1; } } else { return autocomplete_fun (text, len, index, R); } #endif } ================================================ FILE: auto-static-fetch.c ================================================ #include #include "config.h" static int multiline_output = 1; static int multiline_offset; static int multiline_offset_size = 2; static int disable_field_names; #define OUT_BUF_SIZE (1 << 25) static char out_buf[OUT_BUF_SIZE]; static int out_buf_pos; #define eprintf(...) \ do { \ out_buf_pos += snprintf (out_buf + out_buf_pos, OUT_BUF_SIZE - out_buf_pos, __VA_ARGS__);\ assert (out_buf_pos < OUT_BUF_SIZE);\ } while (0)\ static int valid_utf8_char (const char *str) { unsigned char c = (unsigned char) *str; int n = 0; if ((c & 0x80) == 0x00) { n = 0; } else if ((c & 0xe0) == 0xc0) { n = 1; } else if ((c & 0xf0) == 0xe0) { n = 2; } else if ((c & 0xf8) == 0xf0) { n = 3; } else if ((c & 0xfc) == 0xf8) { n = 4; } else if ((c & 0xfe) == 0xfc) { n = 5; } else { return -1; } int i; for (i = 0; i < n; i ++) { if ((((unsigned char)(str[i + 1])) & 0xc0) != 0x80) { return -1; } } return n + 1; } static void print_escaped_string (const char *str, int len) { eprintf ("\""); const char *end = str + len; while (str < end) { int n = valid_utf8_char (str); if (n < 0) { eprintf ("\\x%02x", (int)(unsigned char)*str); str ++; } else if (n >= 2) { int i; for (i = 0; i < n; i++) { eprintf ("%c", *(str ++)); } } else if (((unsigned char)*str) >= ' ' && *str != '"' && *str != '\\') { eprintf ("%c", *str); str ++; } else { switch (*str) { case '\n': eprintf("\\n"); break; case '\r': eprintf("\\r"); break; case '\t': eprintf("\\t"); break; case '\b': eprintf("\\b"); break; case '\a': eprintf("\\a"); break; case '\\': eprintf ("\\\\"); break; case '"': eprintf ("\\\""); break; default: eprintf ("\\x%02x", (int)(unsigned char)*str); break; } str ++; } } eprintf ("\""); } static void print_offset (void) { int i; for (i = 0; i < multiline_offset; i++) { eprintf (" "); } } char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T) { #ifdef DISABLE_EXTF assert (0); #else out_buf_pos = 0; if (fetch_type_any (T) < 0) { return 0; } return out_buf; #endif } ================================================ FILE: auto-static-print-ds.c ================================================ #include "config.h" #ifdef DISABLE_EXTF #error "EXTF disabled, so nothing uses auto-print anymore." #endif static int multiline_output = 1; static int multiline_offset; static int multiline_offset_size = 2; static int disable_field_names; #define OUT_BUF_SIZE (1 << 25) static char out_buf[OUT_BUF_SIZE]; static int out_buf_pos; #define eprintf(...) \ do { \ out_buf_pos += snprintf (out_buf + out_buf_pos, OUT_BUF_SIZE - out_buf_pos, __VA_ARGS__);\ assert (out_buf_pos < OUT_BUF_SIZE);\ } while (0)\ static int valid_utf8_char (const char *str) { unsigned char c = (unsigned char) *str; int n = 0; if ((c & 0x80) == 0x00) { n = 0; } else if ((c & 0xe0) == 0xc0) { n = 1; } else if ((c & 0xf0) == 0xe0) { n = 2; } else if ((c & 0xf8) == 0xf0) { n = 3; } else if ((c & 0xfc) == 0xf8) { n = 4; } else if ((c & 0xfe) == 0xfc) { n = 5; } else { return -1; } int i; for (i = 0; i < n; i ++) { if ((((unsigned char)(str[i + 1])) & 0xc0) != 0x80) { return -1; } } return n + 1; } static void print_escaped_string (const char *str, int len) { eprintf ("\""); const char *end = str + len; while (str < end) { int n = valid_utf8_char (str); if (n < 0) { eprintf ("\\x%02x", (int)(unsigned char)*str); str ++; } else if (n >= 2) { int i; for (i = 0; i < n; i++) { eprintf ("%c", *(str ++)); } } else if (((unsigned char)*str) >= ' ' && *str != '"' && *str != '\\') { eprintf ("%c", *str); str ++; } else { switch (*str) { case '\n': eprintf("\\n"); break; case '\r': eprintf("\\r"); break; case '\t': eprintf("\\t"); break; case '\b': eprintf("\\b"); break; case '\a': eprintf("\\a"); break; case '\\': eprintf ("\\\\"); break; case '"': eprintf ("\\\""); break; default: eprintf ("\\x%02x", (int)(unsigned char)*str); break; } str ++; } } eprintf ("\""); } static void print_offset (void) { int i; for (i = 0; i < multiline_offset; i++) { eprintf (" "); } } char *tglf_extf_print_ds (struct tgl_state *TLS, void *DS, struct paramed_type *T) { out_buf_pos = 0; if (print_ds_type_any (DS, T) < 0) { return 0; } return out_buf; } ================================================ FILE: auto-static-skip.c ================================================ ================================================ FILE: auto-static-store.c ================================================ #include #include "config.h" static int cur_token_len; static char *cur_token; static int cur_token_real_len; static int cur_token_quoted; #define expect_token(token,len) \ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \ local_next_token (); #define expect_token_ptr(token,len) \ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \ local_next_token (); #define expect_token_autocomplete(token,len) \ if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return -1; }\ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \ local_next_token (); #define expect_token_ptr_autocomplete(token,len) \ if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return 0; }\ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \ local_next_token (); static int is_int (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; if (strtoll (cur_token, &p, 10)) {} cur_token[cur_token_len] = c; return p == cur_token + cur_token_len; } static long long get_int (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; long long val = strtoll (cur_token, &p, 0); cur_token[cur_token_len] = c; return val; } static int is_double (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; if (strtod (cur_token, &p)) {} cur_token[cur_token_len] = c; return p == cur_token + cur_token_len; } #ifndef IN_AUTOCOMPLETE_H static double get_double (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; double val = strtod (cur_token, &p); cur_token[cur_token_len] = c; return val; } #endif static char *buffer_pos, *buffer_end; static int is_wspc (char c) { return c <= 32 && c > 0; } static void skip_wspc (void) { while (buffer_pos < buffer_end && is_wspc (*buffer_pos)) { buffer_pos ++; } } static int is_letter (char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-'; } static char exp_buffer[1 << 25];; static int exp_buffer_pos; static inline int is_hex (char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); } static inline int hex2dec (char c) { if (c >= '0' && c <= '9') { return c - '0'; } else { return c - 'a' + 10; } } static void expand_backslashed (char *s, int len) { int backslashed = 0; exp_buffer_pos = 0; int i = 0; while (i < len) { assert (i + 3 <= (1 << 25)); if (backslashed) { backslashed = 0; switch (s[i ++]) { case 'n': exp_buffer[exp_buffer_pos ++] = '\n'; break; case 'r': exp_buffer[exp_buffer_pos ++] = '\r'; break; case 't': exp_buffer[exp_buffer_pos ++] = '\t'; break; case 'b': exp_buffer[exp_buffer_pos ++] = '\b'; break; case 'a': exp_buffer[exp_buffer_pos ++] = '\a'; break; case '\\': exp_buffer[exp_buffer_pos ++] = '\\'; break; case 'x': if (i + 2 > len || !is_hex (s[i]) || !is_hex (s[i + 1])) { exp_buffer_pos = -1; return; } exp_buffer[exp_buffer_pos ++] = hex2dec (s[i]) * 16 + hex2dec (s[i + 1]); i += 2; break; default: break; } } else { if (s[i] == '\\') { backslashed = 1; i ++; } else { exp_buffer[exp_buffer_pos ++] = s[i ++]; } } } } static void local_next_token (void) { skip_wspc (); cur_token_quoted = 0; if (buffer_pos >= buffer_end) { cur_token_len = -3; cur_token_real_len = 0; return; } char c = *buffer_pos; if (is_letter (c)) { cur_token = buffer_pos; while (buffer_pos < buffer_end && is_letter (*buffer_pos)) { buffer_pos ++; } if (buffer_pos < buffer_end) { cur_token_len = buffer_pos - cur_token; } else { cur_token_real_len = buffer_pos - cur_token; cur_token_len = -3; } return; } else if (c == '"') { cur_token_quoted = 1; cur_token = buffer_pos ++; int backslashed = 0; while (buffer_pos < buffer_end && (*buffer_pos != '"' || backslashed)) { if (*buffer_pos == '\\') { backslashed ^= 1; } else { backslashed = 0; } buffer_pos ++; } if (*buffer_pos == '"') { buffer_pos ++; expand_backslashed (cur_token + 1, buffer_pos - cur_token - 2); if (exp_buffer_pos < 0) { cur_token_len = -2; } else { cur_token_len = exp_buffer_pos; cur_token = exp_buffer; } } else { cur_token_len = -2; } return; } else { if (c) { cur_token = buffer_pos ++; cur_token_len = 1; } else { cur_token_len = -3; cur_token_real_len = 0; } } } static struct paramed_type *paramed_type_dup (struct paramed_type *P) { if (ODDP (P)) { return P; } struct paramed_type *R = malloc (sizeof (*R)); assert (R); R->type = malloc (sizeof (*R->type)); assert (R->type); memcpy (R->type, P->type, sizeof (*P->type)); R->type->id = strdup (P->type->id); assert (R->type->id); if (P->type->params_num) { R->params = malloc (sizeof (void *) * P->type->params_num); assert (R->params); int i; for (i = 0; i < P->type->params_num; i++) { R->params[i] = paramed_type_dup (P->params[i]); } } return R; } #ifndef IN_AUTOCOMPLETE_H void tgl_paramed_type_free (struct paramed_type *P) { if (ODDP (P)) { return; } if (P->type->params_num) { int i; for (i = 0; i < P->type->params_num; i++) { tgl_paramed_type_free (P->params[i]); } free (P->params); } free (P->type->id); free (P->type); free (P); } #else void tgl_paramed_type_free (struct paramed_type *P); #endif #ifndef IN_AUTOCOMPLETE_H struct paramed_type *tglf_extf_store (struct tgl_state *TLS, const char *data, int data_len) { #ifdef DISABLE_EXTF assert (0); #else buffer_pos = (char *)data; buffer_end = (char *)(data + data_len); local_next_token (); return store_function_any (); #endif } int tglf_store_type (struct tgl_state *TLS, const char *data, int data_len, struct paramed_type *P) { buffer_pos = (char *)data; buffer_end = (char *)(data + data_len); local_next_token (); return store_type_any (P); } #endif ================================================ FILE: auto-static.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #include "mtproto-common.h" #include "config.h" #include #ifndef DISABLE_EXTF static int cur_token_len; static char *cur_token; static int cur_token_real_len; static int cur_token_quoted; #define expect_token(token,len) \ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \ local_next_token (); #define expect_token_ptr(token,len) \ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \ local_next_token (); #define expect_token_autocomplete(token,len) \ if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return -1; }\ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return -1; } \ local_next_token (); #define expect_token_ptr_autocomplete(token,len) \ if (cur_token_len == -3 && len >= cur_token_real_len && !memcmp (cur_token, token, cur_token_real_len)) { set_autocomplete_string (token); return 0; }\ if (len != cur_token_len || memcmp (cur_token, token, cur_token_len)) { return 0; } \ local_next_token (); static int autocomplete_mode; static char *autocomplete_string; static int (*autocomplete_fun)(const char *, int, int, char **); static void set_autocomplete_string (const char *s) { if (autocomplete_string) { free (autocomplete_string); } autocomplete_string = strdup (s); assert (autocomplete_string); autocomplete_mode = 1; } static void set_autocomplete_type (int (*f)(const char *, int, int, char **)) { autocomplete_fun = f; autocomplete_mode = 2; } static int is_int (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; if (strtoll (cur_token, &p, 10)) {} cur_token[cur_token_len] = c; return p == cur_token + cur_token_len; } static long long get_int (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; long long val = strtoll (cur_token, &p, 0); cur_token[cur_token_len] = c; return val; } static int is_double (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; if (strtod (cur_token, &p)) {} cur_token[cur_token_len] = c; return p == cur_token + cur_token_len; } static double get_double (void) { if (cur_token_len <= 0) { return 0; } char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *p = 0; double val = strtod (cur_token, &p); cur_token[cur_token_len] = c; return val; } static struct paramed_type *paramed_type_dup (struct paramed_type *P) { if (ODDP (P)) { return P; } struct paramed_type *R = malloc (sizeof (*R)); assert (R); R->type = malloc (sizeof (*R->type)); assert (R->type); memcpy (R->type, P->type, sizeof (*P->type)); R->type->id = strdup (P->type->id); assert (R->type->id); if (P->type->params_num) { R->params = malloc (sizeof (void *) * P->type->params_num); assert (R->params); int i; for (i = 0; i < P->type->params_num; i++) { R->params[i] = paramed_type_dup (P->params[i]); } } return R; } void tgl_paramed_type_free (struct paramed_type *P) { if (ODDP (P)) { return; } if (P->type->params_num) { int i; for (i = 0; i < P->type->params_num; i++) { tgl_paramed_type_free (P->params[i]); } free (P->params); } free (P->type->id); free (P->type); free (P); } static char *buffer_pos, *buffer_end; static int is_wspc (char c) { return c <= 32 && c > 0; } static void skip_wspc (void) { while (buffer_pos < buffer_end && is_wspc (*buffer_pos)) { buffer_pos ++; } } static int is_letter (char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-'; } static char exp_buffer[1 << 25];; static int exp_buffer_pos; static inline int is_hex (char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); } static inline int hex2dec (char c) { if (c >= '0' && c <= '9') { return c - '0'; } else { return c - 'a' + 10; } } static void expand_backslashed (char *s, int len) { int backslashed = 0; exp_buffer_pos = 0; int i = 0; while (i < len) { assert (i + 3 <= (1 << 25)); if (backslashed) { backslashed = 0; switch (s[i ++]) { case 'n': exp_buffer[exp_buffer_pos ++] = '\n'; break; case 'r': exp_buffer[exp_buffer_pos ++] = '\r'; break; case 't': exp_buffer[exp_buffer_pos ++] = '\t'; break; case 'b': exp_buffer[exp_buffer_pos ++] = '\b'; break; case 'a': exp_buffer[exp_buffer_pos ++] = '\a'; break; case '\\': exp_buffer[exp_buffer_pos ++] = '\\'; break; case 'x': if (i + 2 > len || !is_hex (s[i]) || !is_hex (s[i + 1])) { exp_buffer_pos = -1; return; } exp_buffer[exp_buffer_pos ++] = hex2dec (s[i]) * 16 + hex2dec (s[i + 1]); i += 2; break; default: break; } } else { if (s[i] == '\\') { backslashed = 1; i ++; } else { exp_buffer[exp_buffer_pos ++] = s[i ++]; } } } } static void local_next_token (void) { skip_wspc (); cur_token_quoted = 0; if (buffer_pos >= buffer_end) { cur_token_len = -3; cur_token_real_len = 0; return; } char c = *buffer_pos; if (is_letter (c)) { cur_token = buffer_pos; while (buffer_pos < buffer_end && is_letter (*buffer_pos)) { buffer_pos ++; } if (buffer_pos < buffer_end) { cur_token_len = buffer_pos - cur_token; } else { cur_token_real_len = buffer_pos - cur_token; cur_token_len = -3; } return; } else if (c == '"') { cur_token_quoted = 1; cur_token = buffer_pos ++; int backslashed = 0; while (buffer_pos < buffer_end && (*buffer_pos != '"' || backslashed)) { if (*buffer_pos == '\\') { backslashed ^= 1; } else { backslashed = 0; } buffer_pos ++; } if (*buffer_pos == '"') { buffer_pos ++; expand_backslashed (cur_token + 1, buffer_pos - cur_token - 2); if (exp_buffer_pos < 0) { cur_token_len = -2; } else { cur_token_len = exp_buffer_pos; cur_token = exp_buffer; } } else { cur_token_len = -2; } return; } else { if (c) { cur_token = buffer_pos ++; cur_token_len = 1; } else { cur_token_len = -3; cur_token_real_len = 0; } } } #define MAX_FVARS 100 static struct paramed_type *fvars[MAX_FVARS]; static int fvars_pos; static void add_var_to_be_freed (struct paramed_type *P) { assert (fvars_pos < MAX_FVARS); fvars[fvars_pos ++] = P; } static void free_vars_to_be_freed (void) { int i; for (i = 0; i < fvars_pos; i++) { tgl_paramed_type_free (fvars[i]); } fvars_pos = 0; } int tglf_extf_autocomplete (struct tgl_state *TLS, const char *text, int text_len, int index, char **R, char *data, int data_len) { if (index == -1) { buffer_pos = data; buffer_end = data + data_len; autocomplete_mode = 0; local_next_token (); struct paramed_type *P = autocomplete_function_any (); free_vars_to_be_freed (); if (P) { tgl_paramed_type_free (P); } } if (autocomplete_mode == 0) { return -1; } int len = strlen (text); if (autocomplete_mode == 1) { if (index >= 0) { return -1; } index = 0; if (!strncmp (text, autocomplete_string, len)) { *R = strdup (autocomplete_string); assert (*R); return index; } else { return -1; } } else { return autocomplete_fun (text, len, index, R); } } #endif ================================================ FILE: auto.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #ifndef __AUTO_H__ #define __AUTO_H__ #include "tools.h" struct tl_type_descr { unsigned name; char *id; int params_num; long long params_types; }; struct paramed_type { struct tl_type_descr *type; struct paramed_type **params; }; #define NAME_ARRAY 0x89932ad9 #define TYPE_TO_PARAM(NAME) (&(struct paramed_type) {.type = &tl_type_## NAME, .params=0}) #define TYPE_TO_PARAM_1(NAME,PARAM1) (&(struct paramed_type) {.type = &tl_type_## NAME, .params=(struct paramed_type *[1]){PARAM1}}) #define ODDP(x) (((long)(x)) & 1) #define EVENP(x) (!ODDP(x)) #define INT2PTR(x) (void *)(long)(((long)x) * 2 + 1) #define PTR2INT(x) ((((long)x) - 1) / 2) static inline void *memdup (const void *d, int len) { assert (d || !len); if (!d) { return NULL; } void *r = talloc (len); memcpy (r, d, len); return r; } #define DS_LVAL(x) ((x) ? *(x) : 0) #define DS_STR(x) ((x) ? (x)->data : NULL), ((x) ? (x)->len : 0) #define DS_RSTR(x) ((x) ? (x)->len : 0), ((x) ? (x)->data : NULL) #define DS_STR_DUP(x) memdup(((x) ? (x)->data : NULL), ((x) ? (x)->len + 1: 0)) #define DS_BVAL(x) ((x) && ((x)->magic == CODE_bool_true)) void tgl_paramed_type_free (struct paramed_type *P); #endif ================================================ FILE: binlog.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "crypto/bn.h" #include "tgl-binlog.h" #include "mtproto-common.h" //#include "net.h" #include "mtproto-client.h" #include "mtproto-utils.h" #include "tgl.h" #include "auto.h" #include "auto/auto-types.h" #include "auto/auto-skip.h" #include "auto/auto-store-ds.h" #include "auto/auto-fetch-ds.h" #include "auto/auto-free-ds.h" #include "tgl-structures.h" #include "tgl-methods-in.h" #include "crypto/sha.h" static int mystreq1 (const char *a, const char *b, int l) { if ((int)strlen (a) != l) { return 1; } return memcmp (a, b, l); } void bl_do_dc_option (struct tgl_state *TLS, int flags, int id, const char *name, int l1, const char *ip, int l2, int port) /* {{{ */ { struct tgl_dc *DC = TLS->DC_list[id]; if (DC) { struct tgl_dc_option *O = DC->options[flags & 3]; while (O) { if (!strncmp (O->ip, ip, l2)) { return; } O = O->next; } } vlogprintf (E_NOTICE, "DC%d '%.*s' update: %.*s:%d\n", id, l1, name, l2, ip, port ); tglmp_alloc_dc (TLS, flags, id, tstrndup (ip, l2), port ); } /* }}} */ void bl_do_set_working_dc (struct tgl_state *TLS, int num) /* {{{ */ { assert (num > 0 && num <= MAX_DC_ID); TLS->DC_working = TLS->DC_list[num]; TLS->dc_working_num = num; } /* }}} */ void bl_do_dc_signed (struct tgl_state *TLS, int num) /* {{{ */ { assert (num > 0 && num <= MAX_DC_ID); assert (TLS->DC_list[num]); TLS->DC_list[num]->flags |= TGLDCF_LOGGED_IN; } /* }}} */ void bl_do_set_auth_key (struct tgl_state *TLS, int num, unsigned char *buf) /* {{{ */ { assert (num > 0 && num <= MAX_DC_ID); assert (TLS->DC_list[num]); memcpy (TLS->DC_list[num]->auth_key, buf, 256); static unsigned char sha1_buffer[20]; TGLC_sha1 ((void *)TLS->DC_list[num]->auth_key, 256, sha1_buffer); TLS->DC_list[num]->auth_key_id = *(long long *)(sha1_buffer + 12); TLS->DC_list[num]->flags |= TGLDCF_AUTHORIZED; } /* }}} */ void bl_do_set_our_id (struct tgl_state *TLS, tgl_peer_id_t id) /* {{{ */ { /*if (TLS->our_id.peer_type) { assert (!tgl_cmp_peer_id (TLS->our_id, id)); return; }*/ TLS->our_id = id; if (TLS->callback.our_id) { TLS->callback.our_id (TLS, TLS->our_id); } } /* }}} */ void bl_do_set_dh_params (struct tgl_state *TLS, int root, unsigned char prime[], int version) /* {{{ */ { if (TLS->encr_prime) { tfree (TLS->encr_prime, 256); TGLC_bn_free (TLS->encr_prime_bn); } TLS->encr_root = root; TLS->encr_prime = talloc (256); memcpy (TLS->encr_prime, prime, 256); TLS->encr_prime_bn = TGLC_bn_new (); TGLC_bn_bin2bn ((void *)TLS->encr_prime, 256, TLS->encr_prime_bn); TLS->encr_param_version = version; assert (tglmp_check_DH_params (TLS, TLS->encr_prime_bn, TLS->encr_root) >= 0); } /* }}} */ void bl_do_set_pts (struct tgl_state *TLS, int pts) /* {{{ */ { if (TLS->locks & TGL_LOCK_DIFF) { return; } if (pts <= TLS->pts) { return; } TLS->pts = pts; } /* }}} */ void bl_do_set_channel_pts (struct tgl_state *TLS, int id, int pts) /* {{{ */ { tgl_peer_t *E = tgl_peer_get (TLS, TGL_MK_CHANNEL (id)); if (!E || !(E->flags & TGLPF_CREATED)) { return; } if (E->flags & TGLCHF_DIFF) { return ; } if (E->channel.pts <= pts) { return; } E->channel.pts = pts; } /* }}} */ void bl_do_set_qts (struct tgl_state *TLS, int qts) /* {{{ */ { if (TLS->locks & TGL_LOCK_DIFF) { return; } if (qts <= TLS->qts) { return; } TLS->qts = qts; } /* }}} */ void bl_do_set_date (struct tgl_state *TLS, int date) /* {{{ */ { if (TLS->locks & TGL_LOCK_DIFF) { return; } if (date <= TLS->date) { return; } TLS->date = date; } /* }}} */ void bl_do_set_seq (struct tgl_state *TLS, int seq) /* {{{ */ { if (TLS->locks & TGL_LOCK_DIFF) { return; } if (seq <= TLS->seq) { return; } TLS->seq = seq; } /* }}} */ void bl_do_set_msg_id (struct tgl_state *TLS, tgl_message_id_t *old_id, tgl_message_id_t *new_id) /* {{{ */ { if (!memcmp (old_id, new_id, sizeof (tgl_message_id_t))) { return; } struct tgl_message *M = tgl_message_get (TLS, old_id); assert (M); if (M->flags & TGLMF_PENDING) { tglm_message_remove_unsent (TLS, M); M->flags &= ~TGLMF_PENDING; } tglm_message_remove_tree (TLS, M); tglm_message_del_peer (TLS, M); M->permanent_id = *new_id; if (tgl_message_get (TLS, new_id)) { tglm_message_del_use (TLS, M); tglm_message_del_temp_id (TLS, M); tglm_message_del_random_id (TLS, M); tgls_free_message (TLS, M); } else { tglm_message_insert_tree (TLS, M); tglm_message_add_peer (TLS, M); } M->server_id = new_id->id; } /* }}} */ void bl_do_chat_add_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user, int inviter, int date) /* {{{ */ { tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P || !(P->flags & TGLPF_CREATED)) { return; } struct tgl_chat *C = &P->chat; if (C->user_list_version >= version || !C->user_list_version) { return; } int i; for (i = 0; i < C->user_list_size; i++) { if (C->user_list[i].user_id == user) { return; } } C->user_list_size ++; C->user_list = trealloc (C->user_list, 12 * C->user_list_size - 12, 12 * C->user_list_size); C->user_list[C->user_list_size - 1].user_id = user; C->user_list[C->user_list_size - 1].inviter_id = inviter; C->user_list[C->user_list_size - 1].date = date; C->user_list_version = version; if (TLS->callback.chat_update) { TLS->callback.chat_update (TLS, C, TGL_UPDATE_MEMBERS); } } /* }}} */ void bl_do_chat_del_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user) /* {{{ */ { tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P || !(P->flags & TGLPF_CREATED)) { return; } struct tgl_chat *C = &P->chat; if (C->user_list_version >= version || !C->user_list_version) { return; } int i; for (i = 0; i < C->user_list_size; i++) { if (C->user_list[i].user_id == user) { struct tgl_chat_user t; t = C->user_list[i]; C->user_list[i] = C->user_list[C->user_list_size - 1]; C->user_list[C->user_list_size - 1] = t; } } if (C->user_list[C->user_list_size - 1].user_id != user) { return; } assert (C->user_list[C->user_list_size - 1].user_id == user); C->user_list_size --; C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size); C->user_list_version = version; if (TLS->callback.chat_update) { TLS->callback.chat_update (TLS, C, TGL_UPDATE_MEMBERS); } } /* }}} */ void bl_do_edit_message (struct tgl_state *TLS, tgl_message_id_t *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, tgl_peer_id_t *fwd_from_id, int *fwd_date, int *date, const char *message, int message_len, struct tl_ds_message_media *media, struct tl_ds_message_action *action, int *reply_id, struct tl_ds_reply_markup *reply_markup, struct tl_ds_vector *entities, int flags) /* {{{ */ { assert (!(flags & 0xfffe0000)); struct tgl_message *M = tgl_message_get (TLS, id); assert (flags & TGLMF_CREATED); assert (!(flags & TGLMF_ENCRYPTED)); if (flags & (1 << 16)) { if (!M) { M = tglm_message_alloc (TLS, id); } M->server_id = id->id; assert (!(M->flags & TGLMF_CREATED)); } else { assert (M->flags & TGLMF_CREATED); } assert (M); assert (!(M->flags & TGLMF_ENCRYPTED)); if ((M->flags & TGLMF_PENDING) && !(flags & TGLMF_PENDING)){ tglm_message_remove_unsent (TLS, M); } if (!(M->flags & TGLMF_PENDING) && (flags & TGLMF_PENDING)){ tglm_message_insert_unsent (TLS, M); } if ((M->flags & TGLMF_UNREAD) && !(flags & TGLMF_UNREAD)) { M->flags = (flags & 0xffff) | TGLMF_UNREAD; } else { M->flags = (flags & 0xffff); } if (from_id) { M->from_id = *from_id; } else { if (!M->from_id.peer_type) { assert (to_id); M->from_id = *to_id; } } if (to_id) { assert (flags & 0x10000); M->to_id = *to_id; } if (date) { M->date = *date; } if (fwd_from_id) { assert (fwd_date); M->fwd_from_id = *fwd_from_id; M->fwd_date = *fwd_date;; } if (action) { tglf_fetch_message_action (TLS, &M->action, action); M->flags |= TGLMF_SERVICE; } if (message) { M->message_len = message_len; M->message = tstrndup (message, message_len); assert (!(M->flags & TGLMF_SERVICE)); } if (media) { tglf_fetch_message_media (TLS, &M->media, media); assert (!(M->flags & TGLMF_SERVICE)); } if (entities) { tglf_fetch_message_entities (TLS, M, entities); } if (reply_id) { M->reply_id = *reply_id; } if (flags & 0x10000) { tglm_message_insert (TLS, M); } if (!(flags & TGLMF_UNREAD) && (M->flags & TGLMF_UNREAD)) { tgls_messages_mark_read (TLS, M, M->flags & TGLMF_OUT, M->permanent_id.id); } if (reply_markup) { M->reply_markup = tglf_fetch_alloc_reply_markup (TLS, M->next, reply_markup); } if (M->flags & TGLMF_PENDING) { tgls_message_change_random_id (TLS, M, M->permanent_id.id); } if (!M->temp_id) { tgls_message_change_temp_id (TLS, M, ++TLS->last_temp_id); } } /* }}} */ void bl_do_edit_message_encr (struct tgl_state *TLS, tgl_message_id_t *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, int *date, const char *message, int message_len, struct tl_ds_decrypted_message_media *media, struct tl_ds_decrypted_message_action *action, struct tl_ds_encrypted_file *file, int flags) /* {{{ */ { clear_packet (); assert (!(flags & 0xfffe0000)); struct tgl_message *M = tgl_message_get (TLS, id); if (flags & (1 << 16)) { if (!M) { M = tglm_message_alloc (TLS, id); } else { assert (!(M->flags & TGLMF_CREATED)); } assert (!(M->flags & TGLMF_CREATED)); } else { assert (M->flags & TGLMF_CREATED); } assert (flags & TGLMF_CREATED); assert (flags & TGLMF_ENCRYPTED); if ((M->flags & TGLMF_PENDING) && !(flags & TGLMF_PENDING)){ tglm_message_remove_unsent (TLS, M); } if (!(M->flags & TGLMF_PENDING) && (flags & TGLMF_PENDING)){ tglm_message_insert_unsent (TLS, M); } M->flags = flags & 0xffff; if (from_id) { M->from_id = *from_id; } if (to_id) { assert (flags & 0x10000); M->to_id = *to_id; } if (date) { M->date = *date; } struct tgl_secret_chat *E = (void *)tgl_peer_get (TLS, M->to_id); assert (E); if (action) { tglf_fetch_message_action_encrypted (TLS, &M->action, action); M->flags |= TGLMF_SERVICE; } if (message) { M->message_len = message_len; M->message = tstrndup (message, message_len); assert (!(M->flags & TGLMF_SERVICE)); } if (media) { tglf_fetch_message_media_encrypted (TLS, &M->media, media); assert (!(M->flags & TGLMF_SERVICE)); } if (file) { tglf_fetch_encrypted_message_file (TLS, &M->media, file); assert (!(M->flags & TGLMF_SERVICE)); } if (action && !(M->flags & TGLMF_OUT) && M->action.type == tgl_message_action_notify_layer) { E->layer = M->action.layer; } if ((flags & TGLMF_CREATE) && (flags & TGLMF_OUT)) { E->out_seq_no ++; } if (flags & 0x10000) { tglm_message_insert (TLS, M); } } /* }}} */ void bl_do_message_delete (struct tgl_state *TLS, tgl_message_id_t *id) /* {{{ */ { struct tgl_message *M = tgl_message_get (TLS, id); if (!M) { return; } assert (M); if (M->flags & TGLMF_PENDING) { tglm_message_remove_unsent (TLS, M); M->flags &= ~TGLMF_PENDING; } tglm_message_remove_tree (TLS, M); tglm_message_del_peer (TLS, M); tglm_message_del_use (TLS, M); tglm_message_del_temp_id (TLS, M); tglm_message_del_random_id (TLS, M); tgls_free_message (TLS, M); } /* }}} */ void bl_do_msg_update (struct tgl_state *TLS, tgl_message_id_t *id) /* {{{ */ { struct tgl_message *M = tgl_message_get (TLS, id); if (!M) { return; } assert (M); if (!(M->flags & TGLMF_ENCRYPTED)) { if (TLS->max_msg_id < M->server_id) { TLS->max_msg_id = M->server_id; } } if (TLS->callback.msg_receive) { TLS->callback.msg_receive (TLS, M); } } /* }}} */ void bl_do_reset_authorization (struct tgl_state *TLS) /* {{{ */ { int i; for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) { struct tgl_dc *D = TLS->DC_list[i]; D->flags = 0; D->state = st_init; D->auth_key_id = D->temp_auth_key_id = 0; } TLS->seq = 0; TLS->qts = 0; } /* }}} */ void bl_do_encr_chat_exchange (struct tgl_state *TLS, tgl_peer_id_t id, long long *exchange_id, const void *key, int *state) /* {{{ */ { tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P) { return; } if (state) { P->encr_chat.exchange_state = *state; } if (exchange_id) { P->encr_chat.exchange_id = *exchange_id; } static unsigned char sha_buffer[20]; switch (P->encr_chat.exchange_state) { case tgl_sce_requested: memcpy (P->encr_chat.exchange_key, key, 256); break; case tgl_sce_accepted: memcpy (P->encr_chat.exchange_key, key, 256); TGLC_sha1 ((unsigned char *)P->encr_chat.exchange_key, 256, sha_buffer); P->encr_chat.exchange_key_fingerprint = *(long long *)(sha_buffer + 12); break; case tgl_sce_committed: memcpy (P->encr_chat.exchange_key, P->encr_chat.key, 256); P->encr_chat.exchange_key_fingerprint = P->encr_chat.key_fingerprint; memcpy (P->encr_chat.key, key, 256); TGLC_sha1 ((unsigned char *)P->encr_chat.key, 256, sha_buffer); P->encr_chat.key_fingerprint = *(long long *)(sha_buffer + 12); break; case tgl_sce_confirmed: P->encr_chat.exchange_state = tgl_sce_none; if (P->encr_chat.exchange_state != tgl_sce_committed) { memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256); P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint; } break; case tgl_sce_aborted: P->encr_chat.exchange_state = tgl_sce_none; if (P->encr_chat.exchange_state == tgl_sce_committed) { memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256); P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint; } break; default: assert (0); } } /* }}} */ void bl_do_user (struct tgl_state *TLS, int id, long long *access_hash, const char *first_name, int first_name_len, const char *last_name, int last_name_len, const char *phone, int phone_len, const char *username, int username_len, struct tl_ds_photo *photo, struct tl_ds_user_profile_photo *profile_photo, int *last_read_in, int *last_read_out, struct tl_ds_bot_info *bot_info, int flags) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_USER (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_USER (id); tglp_insert_user (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_user *U = (void *)_U; if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; } flags &= TGLUF_TYPE_MASK; if ((flags & TGLUF_TYPE_MASK) != (U->flags & TGLUF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } U->flags = (U->flags & ~TGLUF_TYPE_MASK) | flags; if (access_hash && *access_hash != U->access_hash) { U->access_hash = *access_hash; U->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (first_name || last_name) { if (!U->first_name || !U->last_name || mystreq1 (U->first_name, first_name, first_name_len) || mystreq1 (U->last_name, last_name, last_name_len)) { if (U->first_name) { tfree_str (U->first_name); } U->first_name = tstrndup (first_name, first_name_len); if (U->last_name) { tfree_str (U->last_name); } U->last_name = tstrndup (last_name, last_name_len); updates |= TGL_UPDATE_NAME; if (U->print_name) { tglp_peer_delete_name (TLS, (void *)U); tfree_str (U->print_name); } U->print_name = TLS->callback.create_print_name (TLS, U->id, U->first_name, U->last_name, 0, 0); tglp_peer_insert_name (TLS, (void *)U); } } if (phone && (!U->phone || mystreq1 (U->phone, phone, phone_len))) { if (U->phone) { tfree_str (U->phone); } U->phone = tstrndup (phone, phone_len); updates |= TGL_UPDATE_PHONE; } if (username && (!U->username || mystreq1 (U->username, username, username_len))) { if (U->username) { tfree_str (U->username); } U->username = tstrndup (username, username_len); updates |= TGL_UPDATE_USERNAME; } if (photo) { if (!U->photo || U->photo->id != DS_LVAL (photo->id)) { if (U->photo) { tgls_free_photo (TLS, U->photo); } U->photo = tglf_fetch_alloc_photo (TLS, photo); U->flags |= TGLUF_HAS_PHOTO; } } if (profile_photo) { if (U->photo_id != DS_LVAL (profile_photo->photo_id)) { U->photo_id = DS_LVAL (profile_photo->photo_id); tglf_fetch_file_location (TLS, &U->photo_big, profile_photo->photo_big); tglf_fetch_file_location (TLS, &U->photo_small, profile_photo->photo_small); updates |= TGL_UPDATE_PHOTO; } } if (last_read_in) { U->last_read_in = *last_read_in; tgls_messages_mark_read (TLS, U->last, 0, U->last_read_in); } if (last_read_out) { U->last_read_out = *last_read_out; tgls_messages_mark_read (TLS, U->last, TGLMF_OUT, U->last_read_out); } if (bot_info) { if (!U->bot_info || U->bot_info->version != DS_LVAL (bot_info->version)) { if (U->bot_info) { tgls_free_bot_info (TLS, U->bot_info); } U->bot_info = tglf_fetch_alloc_bot_info (TLS, bot_info); } } if (TLS->callback.user_update && updates) { TLS->callback.user_update (TLS, U, updates); } } /* }}} */ void bl_do_chat (struct tgl_state *TLS, int id, const char *title, int title_len, int *user_num, int *date, int *version, struct tl_ds_vector *participants, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *admin, int *last_read_in, int *last_read_out, int flags) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHAT (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_CHAT (id); tglp_insert_chat (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_chat *C = &_U->chat; if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; } flags &= TGLCF_TYPE_MASK; if ((flags & TGLCF_TYPE_MASK) != (C->flags & TGLCF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } C->flags = (C->flags & ~TGLCF_TYPE_MASK) | flags; if (title && (!C->title || mystreq1 (C->title, title, title_len))) { if (C->title) { tfree_str (C->title); } C->title = tstrndup (title, title_len); if (C->print_title) { tglp_peer_delete_name (TLS, (void *)C); tfree_str (C->print_title); } C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0); tglp_peer_insert_name (TLS, (void *)C); updates |= TGL_UPDATE_TITLE; } if (user_num) { C->users_num = *user_num; } if (date) { C->date = *date; } if (chat_photo && chat_photo->photo_big) { if (DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) { tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big); tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small); updates |= TGL_UPDATE_PHOTO; } } if (photo) { if (!C->photo || C->photo->id != DS_LVAL (photo->id)) { if (C->photo) { tgls_free_photo (TLS, C->photo); } C->photo = tglf_fetch_alloc_photo (TLS, photo); C->flags |= TGLPF_HAS_PHOTO; //updates |= TGL_UPDATE_PHOTO; } } if (admin && *admin != C->admin_id) { C->admin_id = *admin; updates |= TGL_UPDATE_ADMIN; } if (version) { assert (participants); if (*version > C->version) { C->version = *version; if (C->user_list) { tfree (C->user_list, 12 * C->user_list_size); } C->user_list_size = DS_LVAL (participants->f1); C->user_list = talloc (12 * C->user_list_size); int i; for (i = 0; i < C->user_list_size; i++) { struct tl_ds_chat_participant *DS_P = participants->f2[i]; C->user_list[i].user_id = DS_LVAL (DS_P->user_id); C->user_list[i].inviter_id = DS_LVAL (DS_P->inviter_id); C->user_list[i].date = DS_LVAL (DS_P->date); } updates |= TGL_UPDATE_MEMBERS; } } if (last_read_in) { C->last_read_in = *last_read_in; tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in); } if (last_read_out) { C->last_read_out = *last_read_out; tgls_messages_mark_read (TLS, C->last, TGLMF_OUT, C->last_read_out); } if (TLS->callback.chat_update && updates) { TLS->callback.chat_update (TLS, C, updates); } } /* }}} */ void bl_do_encr_chat (struct tgl_state *TLS, int id, long long *access_hash, int *date, int *admin, int *user_id, void *key, void *g_key, void *first_key_id, int *state, int *ttl, int *layer, int *in_seq_no, int *last_in_seq_no, int *out_seq_no, long long *key_fingerprint, int flags, const char *print_name, int print_name_len) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_ENCR_CHAT (id); tglp_insert_encrypted_chat (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_secret_chat *U = (void *)_U; if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; } flags &= TGLECF_TYPE_MASK; if ((flags & TGLECF_TYPE_MASK) != (U->flags & TGLECF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } U->flags = (U->flags & ~TGLECF_TYPE_MASK) | flags; if (access_hash && *access_hash != U->access_hash) { U->access_hash = *access_hash; U->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (date) { U->date = *date; } if (admin) { U->admin_id = *admin; } if (user_id) { U->user_id = *user_id; } if (key_fingerprint) { U->key_fingerprint = *key_fingerprint; } if (in_seq_no) { U->in_seq_no = *in_seq_no; } if (out_seq_no) { U->out_seq_no = *out_seq_no; } if (last_in_seq_no) { U->last_in_seq_no = *last_in_seq_no; } tgl_peer_t *Us = tgl_peer_get (TLS, TGL_MK_USER (U->user_id)); if (!U->print_name) { if (print_name) { U->print_name = tstrndup (print_name, print_name_len); } else { if (Us) { U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", Us->user.first_name, Us->user.last_name, 0); } else { static char buf[100]; tsnprintf (buf, 99, "user#%d", U->user_id); U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", buf, 0, 0); } tglp_peer_insert_name (TLS, (void *)U); } } if (g_key) { if (!U->g_key) { U->g_key = talloc (256); } memcpy (U->g_key, g_key, 256); } if (key) { memcpy (U->key, key, 256); } if (first_key_id) { memcpy (U->first_key_sha, first_key_id, 20); } if (state) { if (U->state == sc_waiting && *state == sc_ok) { tgl_do_create_keys_end (TLS, U); } if ((int)U->state != *state) { switch (*state) { case sc_request: updates |= TGL_UPDATE_REQUESTED; break; case sc_ok: updates |= TGL_UPDATE_WORKING; vlogprintf (E_WARNING, "Secret chat in ok state\n"); break; default: break; } } U->state = *state; } if (TLS->callback.secret_chat_update && updates) { TLS->callback.secret_chat_update (TLS, U, updates); } } /* }}} */ void bl_do_channel (struct tgl_state *TLS, int id, long long *access_hash, int *date, const char *title, int title_len, const char *username, int username_len, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *version, char *about, int about_len, int *participants_count, int *admins_count, int *kicked_count, int *last_read_in, int flags) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHANNEL (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_CHANNEL (id); tglp_insert_channel (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_channel *C = &_U->channel; if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; } flags &= TGLCHF_TYPE_MASK; if ((flags & TGLCHF_TYPE_MASK) != (C->flags & TGLCHF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } C->flags = (C->flags & ~TGLCHF_TYPE_MASK) | flags; if (access_hash && *access_hash != C->access_hash) { C->access_hash = *access_hash; C->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (date) { C->date = *date; } if (title && (!C->title || mystreq1 (C->title, title, title_len))) { if (C->title) { tfree_str (C->title); } C->title = tstrndup (title, title_len); if (C->print_title) { tglp_peer_delete_name (TLS, (void *)C); tfree_str (C->print_title); } C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0); tglp_peer_insert_name (TLS, (void *)C); updates |= TGL_UPDATE_TITLE; } if (chat_photo) { if (chat_photo->photo_big && DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) { tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big); tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small); updates |= TGL_UPDATE_PHOTO; } } if (photo) { if (!C->photo || C->photo->id != DS_LVAL (photo->id)) { if (C->photo) { tgls_free_photo (TLS, C->photo); } C->photo = tglf_fetch_alloc_photo (TLS, photo); C->flags |= TGLPF_HAS_PHOTO; } } if (username) { if (!C->username || mystreq1 (C->username, username, username_len)) { if (C->username) { tfree_str (C->username); } C->username = tstrndup (username, username_len); updates |= TGL_UPDATE_USERNAME; } } if (about) { if (!C->about || mystreq1 (C->about, about, about_len)) { tfree_str (C->about); } C->about = tstrndup (about, about_len); } if (admins_count) { C->admins_count = *admins_count; } if (participants_count) { C->participants_count = *participants_count; } if (kicked_count) { C->kicked_count = *kicked_count; } if (last_read_in) { C->last_read_in = *last_read_in; tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in); } if (TLS->callback.channel_update && updates) { TLS->callback.channel_update (TLS, C, updates); } } /* }}} */ void bl_do_peer_delete (struct tgl_state *TLS, tgl_peer_id_t id) /* {{{ */ { tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P || !(P->flags & TGLPF_CREATED)) { return; } if (P->flags & TGLPF_DELETED) { return; } P->flags |= TGLPF_DELETED; switch (id.peer_type) { case TGL_PEER_USER: if (TLS->callback.user_update) { TLS->callback.user_update (TLS, (void *)P, TGL_UPDATE_DELETED); } break; case TGL_PEER_CHAT: if (TLS->callback.chat_update) { TLS->callback.chat_update (TLS, (void *)P, TGL_UPDATE_DELETED); } break; case TGL_PEER_ENCR_CHAT: if (TLS->callback.secret_chat_update) { TLS->callback.secret_chat_update (TLS, (void *)P, TGL_UPDATE_DELETED); } break; case TGL_PEER_CHANNEL: if (TLS->callback.channel_update) { TLS->callback.channel_update (TLS, (void *)P, TGL_UPDATE_DELETED); } break; default: assert (0); } } /* }}} */ ================================================ FILE: binlog.tl ================================================ ---types--- binlog.encrKey key:64*[int] = binlog.EncrKey; binlog.peerUser = binlog.PeerType; binlog.peerChat = binlog.PeerType; binlog.peerChannel = binlog.PeerType; binlog.peer peer_type:binlog.PeerType peer_id:int = binlog.Peer; binlog.start = binlog.Update; binlog.authKey dc:int key:%binlog.EncrKey = binlog.Update; binlog.defaultDc dc:int = binlog.Update; binlog.dcSigned dc:int = binlog.Update; binlog.dcOption flags:int dc:int name:string ip:string port:int = binlog.Update; binlog.ourId id:int = binlog.Update; binlog.setDhParams root:int prime:%binlog.EncrKey version:int = binlog.Update; binlog.setPts pts:int = binlog.Update; binlog.setQts qts:int = binlog.Update; binlog.setDate date:int = binlog.Update; binlog.setSeq seq:int = binlog.Update; binlog.peerDelete peer:%binlog.Peer = binlog.Update; binlog.encrChat#84977251 flags:# id:int access_hash:flags.17?long date:flags.18?int admin:flags.19?int user_id:flags.20?int key:flags.21?%binlog.EncrKey g_key:flags.22?%binlog.EncrKey state:flags.23?int ttl:flags.24?int layer:flags.25?int in_seq_no:flags.26?int last_in_seq_no:flags.26?int out_seq_no:flags.26?int key_fingerprint:flags.27?long = binlog.Update; binlog.encrChatExchange#9d49488d flags:# id:int exchange_id:flags.17?long key:flags.18?%binlog.EncrKey state:flags.19?int = binlog.Update; binlog.user#127cf2f9 flags:# id:int access_hash:flags.17?long first_name:flags.18?string last_name:flags.18?string phone:flags.19?string username:flags.20?string photo:flags.21?Photo real_first_name:flags.22?string real_last_name:flags.22?string user_photo:flags.23?UserProfilePhoto last_read_in:flags.24?int last_read_out:flags.25?int bot_info:flags.26?BotInfo = binlog.Update; binlog.chat#0a10aa92 flags:# id:int title:flags.17?string user_num:flags.18?int date:flags.19?int version:flags.20?int participants:flags.20?(Vector ChatParticipant) chat_photo:flags.21?ChatPhoto photo:flags.22?Photo admin:flags.23?int last_read_in:flags.24?int last_read_out:flags.25?int = binlog.Update; binlog.channel flags:# id:int title:flags.17?string username:flags.18?string date:flags.19?int version:flags.20?int chat_photo:flags.21?ChatPhoto photo:flags.22?Photo about:flags.23?int last_read_in:flags.24?int admins_count:flags.25?int kicked_count:flags.26?int access_hash:flags.27?long = binlog.Update; binlog.chatAddParticipant id:int version:int user_id:int inviter_id:int date:int = binlog.Update; binlog.chatDelParticipant id:int version:int user_id:int = binlog.Update; binlog.setMsgId old_id:long new_id:int = binlog.Update; binlog.messageDelete lid:long = binlog.Update; binlog.messageNew#427cfcdb flags:# lid:long from:flags.17?%binlog.Peer to:flags.17?%binlog.Peer fwd_from_id:flags.18?%binlog.Peer fwd_date:flags.18?int date:flags.19?int message:flags.20?string media:flags.21?MessageMedia action:flags.22?MessageAction reply_id:flags.23?int reply_markup:flags.24?ReplyMarkup = binlog.Update; binlog.messageEncrNew#6cf7cabc flags:# lid:long from:flags.17?%binlog.Peer to:flags.17?%binlog.Peer //empty 18 bit date:flags.19?int message:flags.20?string encr_media:flags.21?DecryptedMessageMedia encr_action:flags.22?DecryptedMessageAction file:flags.23?EncryptedFile = binlog.Update; binlog.msgUpdate#6dd4d85f lid:long = binlog.Update; binlog.resetAuthorization = binlog.Update; ---functions--- ================================================ FILE: config.h.in ================================================ /* config.h.in. Generated from configure.ac by autoheader. */ /* disable extf queries */ #undef DISABLE_EXTF /* Use libevent v1 */ #undef EVENT_V1 /* Use libevent v2 */ #undef EVENT_V2 /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the `endpwent' function. */ #undef HAVE_ENDPWENT /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `event' library (-levent). */ #undef HAVE_LIBEVENT /* Define to 1 if you have the `gcrypt' library (-lgcrypt). */ #undef HAVE_LIBGCRYPT /* Define to 1 if you have `z' library (-lz) */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_MACH_MACH_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #undef HAVE_REALLOC /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the `__builtin_bswap32' built-in function */ #undef HAVE___BUILTIN_BSWAP32 /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* avoid OpenSSL entirely, use libgcrypt instead (this can't read *.pub files, though.) */ #undef TGL_AVOID_OPENSSL /* fixed for correct valgrind work */ #undef VALGRIND_FIXES /* Define to `int' if doesn't define. */ #undef gid_t /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if doesn't define. */ #undef uid_t ================================================ FILE: configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for telegram-cli 1.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='telegram-cli' PACKAGE_TARNAME='telegram-cli' PACKAGE_VERSION='1.0' PACKAGE_STRING='telegram-cli 1.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="config.h.in" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS EXTRA_OBJECTS EXTRA_LIBS LIBOBJS EGREP GREP CPP OPENSSL_LDFLAGS OPENSSL_LIBS OPENSSL_INCLUDES PKG_CONFIG OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_openssl with_openssl with_zlib enable_extf enable_libevent enable_valgrind ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures telegram-cli 1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/telegram-cli] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of telegram-cli 1.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-openssl disables OpenSSL, and don't link against it (this can't read *.pub files, though.) --enable-extf enables extended queries system --enable-libevent include libevent-based net and timers --enable-valgrind fixes for correct valgrind work Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-openssl=DIR root of the OpenSSL directory --with-zlib=DIR root directory path of zlib installation [defaults to /usr/local or /usr if not found in /usr/local] --without-zlib to disable zlib usage completely Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF telegram-cli configure 1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by telegram-cli $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) # # DESCRIPTION # # Look for OpenSSL in a number of default spots, or in a user-selected # spot (via --with-openssl). Sets # # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately # # This macro sets OPENSSL_INCLUDES such that source files should use the # openssl/ directory in include directives: # # #include # # LICENSE # # Copyright (c) 2009,2010 Zmanda Inc. # Copyright (c) 2009,2010 Dustin J. Mitchell # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 # This is what autoupdate's m4 run will expand. It fires # the warning (with _au_warn_XXX), outputs it into the # updated configure.ac (with AC_DIAGNOSE), and then outputs # the replacement expansion. # This is an auxiliary macro that is also run when # autoupdate runs m4. It simply calls m4_warning, but # we need a wrapper so that each warning is emitted only # once. We break the quoting in m4_warning's argument in # order to expand this macro's arguments, not AU_DEFUN's. # Finally, this is the expansion that is picked up by # autoconf. It tells the user to run autoupdate, and # then outputs the replacement expansion. We do not care # about autoupdate's warning because that contains # information on what to do *after* running autoupdate. # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_ZLIB([action-if-found], [action-if-not-found]) # # DESCRIPTION # # This macro searches for an installed zlib library. If nothing was # specified when calling configure, it searches first in /usr/local and # then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified, # it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If # --without-zlib is specified, the library is not searched at all. # # If either the header file (zlib.h) or the library (libz) is not found, # shell commands 'action-if-not-found' is run. If 'action-if-not-found' is # not specified, the configuration exits on error, asking for a valid zlib # installation directory or --without-zlib. # # If both header file and library are found, shell commands # 'action-if-found' is run. If 'action-if-found' is not specified, the # default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends # '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls # AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition # for this symbol in a config.h file. Sample usage in a C/C++ source is as # follows: # # #ifdef HAVE_LIBZ # #include # #endif /* HAVE_LIBZ */ # # LICENSE # # Copyright (c) 2008 Loic Dachary # Copyright (c) 2010 Bastien Chevreux # # 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, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 14 # This is what autoupdate's m4 run will expand. It fires # the warning (with _au_warn_XXX), outputs it into the # updated configure.ac (with AC_DIAGNOSE), and then outputs # the replacement expansion. # This is an auxiliary macro that is also run when # autoupdate runs m4. It simply calls m4_warning, but # we need a wrapper so that each warning is emitted only # once. We break the quoting in m4_warning's argument in # order to expand this macro's arguments, not AU_DEFUN's. # Finally, this is the expansion that is picked up by # autoconf. It tells the user to run autoupdate, and # then outputs the replacement expansion. We do not care # about autoupdate's warning because that contains # information on what to do *after* running autoupdate. # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # BSD locations for headers and libraries from packages, Linux locations for self-compiled stuff. CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" # Checks for libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 $as_echo_n "checking for library containing clock_gettime... " >&6; } if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF for ac_lib in '' rt; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_clock_gettime+:} false; then : break fi done if ${ac_cv_search_clock_gettime+:} false; then : else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 $as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi EVENT_VER="" EXTRA_OBJECTS="" # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # Check whether --enable-openssl was given. if test "${enable_openssl+set}" = set; then : enableval=$enable_openssl; if test "x$enableval" = "xno" ; then $as_echo "#define TGL_AVOID_OPENSSL 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_mpi_snatch in -lgcrypt" >&5 $as_echo_n "checking for gcry_mpi_snatch in -lgcrypt... " >&6; } if ${ac_cv_lib_gcrypt_gcry_mpi_snatch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgcrypt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gcry_mpi_snatch (); int main () { return gcry_mpi_snatch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gcrypt_gcry_mpi_snatch=yes else ac_cv_lib_gcrypt_gcry_mpi_snatch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcrypt_gcry_mpi_snatch" >&5 $as_echo "$ac_cv_lib_gcrypt_gcry_mpi_snatch" >&6; } if test "x$ac_cv_lib_gcrypt_gcry_mpi_snatch" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBGCRYPT 1 _ACEOF LIBS="-lgcrypt $LIBS" else as_fn_error $? "\"Need libgcrypt >= 1.60\"" "$LINENO" 5 fi else # Don't be annoying, so don't inform the user about --disable-openssl found=false # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; case "$withval" in "" | y | ye | yes | n | no) as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5 ;; *) ssldirs="$withval" ;; esac else # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi fi # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ssl.h in $ssldir" >&5 $as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; } if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } break else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5 $as_echo_n "checking whether compiling and linking against OpenSSL works... " >&6; } echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5 save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { SSL_new(NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "No openssl found." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi else found=false # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; case "$withval" in "" | y | ye | yes | n | no) as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5 ;; *) ssldirs="$withval" ;; esac else # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi fi # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ssl.h in $ssldir" >&5 $as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; } if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } break else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5 $as_echo_n "checking whether compiling and linking against OpenSSL works... " >&6; } echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5 save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { SSL_new(NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "No openssl found. With --disable-openssl, libtgl will use libgcrypt instead." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # # Handle user hints # { $as_echo "$as_me:${as_lineno-$LINENO}: checking if zlib is wanted" >&5 $as_echo_n "checking if zlib is wanted... " >&6; } zlib_places="/usr/local /usr /opt/local /sw" # Check whether --with-zlib was given. if test "${with_zlib+set}" = set; then : withval=$with_zlib; if test "$withval" != no ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test -d "$withval" then zlib_places="$withval $zlib_places" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Sorry, $withval does not exist, checking usual places" >&5 $as_echo "$as_me: WARNING: Sorry, $withval does not exist, checking usual places" >&2;} fi else zlib_places= { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # # Locate zlib, if wanted # if test -n "${zlib_places}" then # check the user supplied or any other more or less 'standard' place: # Most UNIX systems : /usr/local and /usr # MacPorts / Fink on OSX : /opt/local respectively /sw for ZLIB_HOME in ${zlib_places} ; do if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi ZLIB_HOME="" done ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$CPPFLAGS if test -n "${ZLIB_HOME}"; then LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inflateEnd (); int main () { return inflateEnd (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_inflateEnd=yes else ac_cv_lib_z_inflateEnd=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : zlib_cv_libz=yes else zlib_cv_libz=no fi ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : zlib_cv_zlib_h=yes else zlib_cv_zlib_h=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, action-if-found # CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" LIBS="-lz $LIBS" $as_echo "#define HAVE_LIBZ 1" >>confdefs.h else # # If either header or library was not found, action-if-not-found # as_fn_error $? "No zlib found" "$LINENO" 5 fi fi # Check whether --enable-extf was given. if test "${enable_extf+set}" = set; then : enableval=$enable_extf; if test "x$enableval" = "xno" ; then $as_echo "#define DISABLE_EXTF 1" >>confdefs.h fi fi # Check whether --enable-libevent was given. if test "${enable_libevent+set}" = set; then : enableval=$enable_libevent; if test "x$enableval" = "xyes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for event_base_new in -levent" >&5 $as_echo_n "checking for event_base_new in -levent... " >&6; } if ${ac_cv_lib_event_event_base_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-levent $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char event_base_new (); int main () { return event_base_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_event_event_base_new=yes else ac_cv_lib_event_event_base_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_event_event_base_new" >&5 $as_echo "$ac_cv_lib_event_event_base_new" >&6; } if test "x$ac_cv_lib_event_event_base_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBEVENT 1 _ACEOF LIBS="-levent $LIBS" else as_fn_error $? "no libevent found" "$LINENO" 5 fi ac_fn_c_check_header_mongrel "$LINENO" "event2/event.h" "ac_cv_header_event2_event_h" "$ac_includes_default" if test "x$ac_cv_header_event2_event_h" = xyes; then : $as_echo "#define EVENT_V2 1" >>confdefs.h else ac_fn_c_check_header_mongrel "$LINENO" "event.h" "ac_cv_header_event_h" "$ac_includes_default" if test "x$ac_cv_header_event_h" = xyes; then : $as_echo "#define EVENT_V1 1" >>confdefs.h else as_fn_error $? "no libevent found" "$LINENO" 5 fi fi EXTRA_OBJECTS="${EXTRA_OBJECTS} objs/tgl-net.o objs/tgl-timers.o" fi fi # Check whether --enable-valgrind was given. if test "${enable_valgrind+set}" = set; then : enableval=$enable_valgrind; if test "x$enableval" = "xyes" ; then ac_fn_c_check_header_mongrel "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default" if test "x$ac_cv_header_valgrind_memcheck_h" = xyes; then : $as_echo "#define VALGRIND_FIXES 1" >>confdefs.h fi fi fi # Checks for header files. for ac_header in fcntl.h malloc.h netdb.h stdlib.h string.h unistd.h arpa/inet.h mach/mach.h netinet/in.h sys/file.h sys/socket.h termios.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # FreeBSD needs -lexecinfo for ac_header in execinfo.h do : ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" if test "x$ac_cv_header_execinfo_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EXECINFO_H 1 _ACEOF tgl_found_execinfo_header=yes; break; fi done if test "x$tgl_found_execinfo_header" = "xyes"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace_symbols_fd" >&5 $as_echo_n "checking for library containing backtrace_symbols_fd... " >&6; } if ${ac_cv_search_backtrace_symbols_fd+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char backtrace_symbols_fd (); int main () { return backtrace_symbols_fd (); ; return 0; } _ACEOF for ac_lib in '' execinfo; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_backtrace_symbols_fd=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_backtrace_symbols_fd+:} false; then : break fi done if ${ac_cv_search_backtrace_symbols_fd+:} false; then : else ac_cv_search_backtrace_symbols_fd=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace_symbols_fd" >&5 $as_echo "$ac_cv_search_backtrace_symbols_fd" >&6; } ac_res=$ac_cv_search_backtrace_symbols_fd if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi # Checks for typedefs, structures, and compiler characteristics. ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # Checks for library functions. for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi for ac_func in alarm endpwent memset memmove mkdir select socket strdup strndup uname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by telegram-cli $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ telegram-cli config.status 1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: configure.ac ================================================ AC_PREREQ([2.68]) AC_INIT([telegram-cli], [1.0]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) m4_include([m4_ax_check_openssl.m4]) m4_include([m4_ax_check_zlib.m4]) # Checks for programs. AC_PROG_CC # BSD locations for headers and libraries from packages, Linux locations for self-compiled stuff. CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" # Checks for libraries. AC_SEARCH_LIBS([clock_gettime], [rt]) EVENT_VER="" EXTRA_OBJECTS="" # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required AC_ARG_ENABLE(openssl,[ --disable-openssl disables OpenSSL, and don't link against it (this can't read *.pub files, though.)], [ if test "x$enableval" = "xno" ; then AC_DEFINE([TGL_AVOID_OPENSSL],[1],[avoid OpenSSL entirely, use libgcrypt instead (this can't read *.pub files, though.)]) AC_CHECK_LIB([gcrypt], [gcry_mpi_snatch], [], [AC_MSG_ERROR(["Need libgcrypt >= 1.60"])]) else # Don't be annoying, so don't inform the user about --disable-openssl AX_CHECK_OPENSSL(,[AC_MSG_ERROR([No openssl found.])]) fi ],[ AX_CHECK_OPENSSL(,[AC_MSG_ERROR([No openssl found. With --disable-openssl, libtgl will use libgcrypt instead.])]) ]) AX_CHECK_ZLIB(, [AC_MSG_ERROR([No zlib found])]) AC_ARG_ENABLE(extf,[ --enable-extf enables extended queries system], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_EXTF],[1],[disable extf queries]) fi ],[ ]) AC_ARG_ENABLE(libevent,[ --enable-libevent include libevent-based net and timers], [ if test "x$enableval" = "xyes" ; then AC_CHECK_LIB([event], [event_base_new], [], [AC_MSG_ERROR([no libevent found])]) AC_CHECK_HEADER(event2/event.h, [AC_DEFINE([EVENT_V2], [1], [Use libevent v2])], [ AC_CHECK_HEADER(event.h, [AC_DEFINE([EVENT_V1], [1], [Use libevent v1])], [AC_MSG_ERROR([no libevent found])]) ]) EXTRA_OBJECTS="${EXTRA_OBJECTS} objs/tgl-net.o objs/tgl-timers.o" fi ],[ ]) AC_ARG_ENABLE(valgrind,[ --enable-valgrind fixes for correct valgrind work], [ if test "x$enableval" = "xyes" ; then AC_CHECK_HEADER(valgrind/memcheck.h, [AC_DEFINE([VALGRIND_FIXES], [1], [fixed for correct valgrind work])], [ ]) fi ],[ ]) # Checks for header files. AC_CHECK_HEADERS([fcntl.h malloc.h netdb.h stdlib.h string.h unistd.h arpa/inet.h mach/mach.h netinet/in.h sys/file.h sys/socket.h termios.h]) # FreeBSD needs -lexecinfo AC_CHECK_HEADERS([execinfo.h], [tgl_found_execinfo_header=yes; break;]) AS_IF([test "x$tgl_found_execinfo_header" = "xyes"], [AC_SEARCH_LIBS([backtrace_symbols_fd], [execinfo])]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T AC_TYPE_UID_T AC_C_INLINE # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([alarm endpwent memset memmove mkdir select socket strdup strndup uname]) AC_SUBST(EXTRA_LIBS) AC_SUBST(EXTRA_OBJECTS) AC_CONFIG_FILES([Makefile]) AC_OUTPUT ================================================ FILE: crypto/aes.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_AES_H__ #define __TGL_CRYPTO_AES_H__ #include /* size_t */ #include "../config.h" typedef struct TGLC_aes_key { char _dummy[ #ifdef TGL_AVOID_OPENSSL 32 #else 244 #endif ]; } TGLC_aes_key; void TGLC_aes_set_encrypt_key (const unsigned char *userKey, const int bits, TGLC_aes_key *key); void TGLC_aes_set_decrypt_key (const unsigned char *userKey, const int bits, TGLC_aes_key *key); void TGLC_aes_ige_encrypt (const unsigned char *in, unsigned char *out, size_t length, const TGLC_aes_key *key, unsigned char *ivec, const int enc); #endif ================================================ FILE: crypto/aes_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL /* Marginally speed up compilation */ #define GCRYPT_NO_MPI_MACROS /* Fail-fast when something becomes deprecated. */ #define GCRYPT_NO_DEPRECATED #include #include #include "aes.h" #include "meta.h" #include "rand.h" #define AES_BLOCK_BITS 128 #define AES_BLOCK_BYTES (AES_BLOCK_BITS/8) #define AES_KEY_BITS 256 #define AES_KEY_BYTES (AES_KEY_BITS/8) typedef char check_struct_sizes[(sizeof (TGLC_aes_key) == AES_KEY_BYTES) - 1]; void TGLC_aes_set_encrypt_key (const unsigned char *userKey, const int bits, TGLC_aes_key *key) { assert (bits == AES_KEY_BITS); memcpy (key->_dummy, userKey, AES_KEY_BYTES); } void TGLC_aes_set_decrypt_key (const unsigned char *userKey, const int bits, TGLC_aes_key *key) { TGLC_aes_set_encrypt_key (userKey, bits, key); } // TODO: Try to use gcrypt's internal buf_xor? static void do_xor_block (const unsigned char *in, const unsigned char *with, unsigned char *out) { /* TODO: Referencing them as "size_t" (or whatever biggest numerical type available) is probably faster, but also more error-prone. */ int i; for (i = 0; i < 16; ++i) { *out++ = *in++ ^ *with++; } } static gcry_error_t do_ige_encrypt (const unsigned char *in, unsigned char *out, unsigned long n_blocks, gcry_cipher_hd_t cipher, unsigned char *ivec) { /* The docs say, at the end of section 2: * "OpenSSL uses the convention that the first block of the IV is x_0 * and the second block is y_0." * Well, no. This is a subtle error: FIRST comes the previous ENcrypted block, * THEN the DEcrypted block. * Also, keep a copy of the old cleartext, in case in == out. */ unsigned char buf[2 * 16]; unsigned char *prev_x = buf; unsigned char *cur_x = buf + 16; memcpy (prev_x, ivec + 16, 16); const unsigned char *prev_y = ivec; /* gcrypt doesn't allow overlapping buffers. Kudos to "reubensammut" for * noticing this. Note that this also works if in == out. */ unsigned char tmp[16]; unsigned long i; for (i = 0; i < n_blocks; ++i) { memcpy (cur_x, in, 16); /* Might overwrite 'in'. */ do_xor_block (in, prev_y, out); gcry_error_t gcry_error = gcry_cipher_encrypt (cipher, tmp, 16, out, 16); if (gcry_error) { return gcry_error; } do_xor_block (tmp, prev_x, out); prev_y = out; // encrypted is in 'out' in += 16; out += 16; // swap (tmp_x, cur_x); unsigned char *tmp_x = cur_x; cur_x = prev_x; prev_x = tmp_x; } if (n_blocks > 0) { /* OpenSSL updates the IV, so we do that, too. * One could avoid memcpy here, as it's only 16 bytes. */ memcpy (ivec + 16, prev_x, 16); memcpy (ivec, prev_y, 16); } return 0; } static gcry_error_t do_ige_decrypt (const unsigned char *in, unsigned char *out, unsigned long n_blocks, gcry_cipher_hd_t cipher, unsigned char *ivec) { /* Also, keep a copy of the old ciphertext, in case in == out. */ unsigned char buf[2 * 16]; unsigned char *prev_y = buf; unsigned char *cur_y = buf + 16; memcpy (prev_y, ivec, 16); const unsigned char *prev_x = ivec + 16; /* gcrypt doesn't allow overlapping buffers. Kudos to "reubensammut" for * noticing this. Note that this also works if in == out. */ unsigned char tmp[16]; unsigned long i; for (i = 0; i < n_blocks; ++i) { memcpy (cur_y, in, 16); /* Might overwrite 'in'. */ do_xor_block (in, prev_x, out); gcry_error_t gcry_error = gcry_cipher_decrypt (cipher, tmp, 16, out, 16); if (gcry_error) { return gcry_error; } do_xor_block (tmp, prev_y, out); prev_x = out; // decrypted is in 'out' in += 16; out += 16; // swap (tmp_y, cur_y); unsigned char *tmp_y = cur_y; cur_y = prev_y; prev_y = tmp_y; } /* Do not change ivec */ return 0; } /* Needs to be given an IV of length 2*AES_BLOCK_BYTES. */ void TGLC_aes_ige_encrypt (const unsigned char *in, unsigned char *out, size_t length, const TGLC_aes_key *key, unsigned char *ivec, const int enc) { assert (!(length % AES_BLOCK_BYTES)); /* Set it up. */ gcry_cipher_hd_t cipher; gcry_error_t gcry_error = gcry_cipher_open (&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB, 0); assert (!gcry_error); gcry_cipher_setkey (cipher, key->_dummy, AES_KEY_BYTES); if (enc) { gcry_error = do_ige_encrypt(in, out, length / AES_BLOCK_BYTES, cipher, ivec); } else { gcry_error = do_ige_decrypt(in, out, length / AES_BLOCK_BYTES, cipher, ivec); } assert (!gcry_error); gcry_cipher_close(cipher); } #endif ================================================ FILE: crypto/aes_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL #include #include "aes.h" #include "meta.h" typedef char check_struct_sizes[(sizeof (AES_KEY) == sizeof (TGLC_aes_key)) - 1]; TGLC_WRAPPER_ASSOC(aes_key,AES_KEY) void TGLC_aes_set_encrypt_key (const unsigned char *userKey, const int bits, TGLC_aes_key *key) { int success = AES_set_encrypt_key(userKey, bits, unwrap_aes_key (key)); assert (0 == success); } void TGLC_aes_set_decrypt_key (const unsigned char *userKey, const int bits, TGLC_aes_key *key) { int success = AES_set_decrypt_key(userKey, bits, unwrap_aes_key (key)); assert (0 == success); } void TGLC_aes_ige_encrypt (const unsigned char *in, unsigned char *out, size_t length, const TGLC_aes_key *key, unsigned char *ivec, const int enc) { AES_ige_encrypt (in, out, length, unwrap_aes_key (key), ivec, enc); } #endif ================================================ FILE: crypto/bn.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_BN_H__ #define __TGL_CRYPTO_BN_H__ typedef struct TGLC_bn_ctx TGLC_bn_ctx; typedef struct TGLC_bn TGLC_bn; TGLC_bn_ctx *TGLC_bn_ctx_new (void); void TGLC_bn_ctx_free (TGLC_bn_ctx* ctx); TGLC_bn *TGLC_bn_new (void); void TGLC_bn_free (TGLC_bn *a); void TGLC_bn_clear_free (TGLC_bn *a); int TGLC_bn_cmp (const TGLC_bn *a, const TGLC_bn *b); int TGLC_bn_is_prime (const TGLC_bn *a, int checks, void (*callback) (int, int, void *), TGLC_bn_ctx *ctx, void *cb_arg); int TGLC_bn_bn2bin (const TGLC_bn *a, unsigned char *to); TGLC_bn * TGLC_bn_bin2bn(const unsigned char *s, int len, TGLC_bn *ret); int TGLC_bn_set_word (TGLC_bn *a, unsigned long w); unsigned long TGLC_bn_get_word (const TGLC_bn *a); int TGLC_bn_num_bits (const TGLC_bn *a); void TGLC_bn_sub (TGLC_bn *r, const TGLC_bn *a, const TGLC_bn *b); int TGLC_bn_div (TGLC_bn *dv, TGLC_bn *rem, const TGLC_bn *a, const TGLC_bn *d, TGLC_bn_ctx *ctx); int TGLC_bn_mod_exp (TGLC_bn *r, const TGLC_bn *a, const TGLC_bn *p, const TGLC_bn *m, TGLC_bn_ctx *ctx); #define TGLC_bn_num_bytes(a) ((TGLC_bn_num_bits(a)+7)/8) #define TGLC_bn_mod(rem,m,d,ctx) TGLC_bn_div(NULL,(rem),(m),(d),(ctx)) #endif ================================================ FILE: crypto/bn_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL /* Fail-fast when something becomes deprecated. */ #define GCRYPT_NO_DEPRECATED #include #include #include "bn.h" #include "meta.h" // There is no "_ctx" equivalent in gcrypt. TGLC_WRAPPER_ASSOC(bn_ctx,int) TGLC_WRAPPER_ASSOC(bn,struct gcry_mpi) TGLC_bn_ctx *TGLC_bn_ctx_new (void) { /* Must not be the null pointer, but must never be dereferenced. Assume that "1" is an invalid address. */ return ((void *)1); } void TGLC_bn_ctx_free (TGLC_bn_ctx* ctx) { (void) ctx; } TGLC_bn *TGLC_bn_new (void) { // TODO: Determine how many bits should be pre-allocated. TGLC_bn *ret = wrap_bn (gcry_mpi_new (2048)); assert (ret); return ret; } void TGLC_bn_free (TGLC_bn *a) { gcry_mpi_release (unwrap_bn (a)); } void TGLC_bn_clear_free (TGLC_bn *a) { /* This only protects against accidental use-after-free. I don't see the point of clearing, since we're not operating in protected memory AND the most crucial fields are never cleared anyway. */ gcry_mpi_set_ui (unwrap_bn (a), 0); gcry_mpi_release (unwrap_bn (a)); } int TGLC_bn_cmp (const TGLC_bn *a, const TGLC_bn *b) { return gcry_mpi_cmp (unwrap_bn (a), unwrap_bn (b)); } int TGLC_bn_is_prime (const TGLC_bn *a, int checks, void (*callback) (int, int, void *), TGLC_bn_ctx *ctx, void *cb_arg) { assert (0 == checks); assert (NULL == callback); (void) ctx; assert (NULL == cb_arg); /* Second argument is ignored. * No really, here's what libgcrypt's source does: * (void)flags; */ gcry_error_t err = gcry_prime_check (unwrap_bn (a), 0); /* This is nasty. In essence, gcry returns a bool whether it is NOT a prime. */ return !err; } int TGLC_bn_bn2bin (const TGLC_bn *a, unsigned char *to) { const unsigned long num_bytes = TGLC_bn_num_bytes (a); gcry_error_t gcry_error = gcry_mpi_print (GCRYMPI_FMT_USG, to, num_bytes, NULL, unwrap_bn (a)); assert (!gcry_error); return num_bytes; } TGLC_bn *TGLC_bn_bin2bn(const unsigned char *s, int len, TGLC_bn *ret) { gcry_mpi_t ret_ptr = NULL; gcry_error_t gcry_error = gcry_mpi_scan (&ret_ptr, GCRYMPI_FMT_USG, s, len, NULL); assert (!gcry_error); assert (ret_ptr); if (!ret) { return wrap_bn (ret_ptr); } gcry_mpi_snatch (unwrap_bn (ret), ret_ptr); return ret; } int TGLC_bn_set_word (TGLC_bn *a, unsigned long w) { assert (a); gcry_mpi_set_ui (unwrap_bn (a), w); return 1; } unsigned long TGLC_bn_get_word (const TGLC_bn *a) { const unsigned long num_bytes = TGLC_bn_num_bytes (a); assert (sizeof (unsigned long) >= num_bytes); unsigned char tmp[sizeof (unsigned long)]; memset (tmp, 0, sizeof (unsigned long)); TGLC_bn_bn2bin (a, tmp + sizeof (unsigned long) - num_bytes); /* Inefficient, but runs a total of three times per connection. */ /* TODO: Optimize? */ unsigned long ret = 0; unsigned int i; for (i = 0; i < sizeof (unsigned long); ++i) { ret <<= 8; ret |= tmp[i]; } return ret; } int TGLC_bn_num_bits (const TGLC_bn *a) { return gcry_mpi_get_nbits (unwrap_bn (a)); } void TGLC_bn_sub (TGLC_bn *r, const TGLC_bn *a, const TGLC_bn *b) { gcry_mpi_sub (unwrap_bn (r), unwrap_bn (a), unwrap_bn (b)); } int TGLC_bn_div (TGLC_bn *dv, TGLC_bn *rem, const TGLC_bn *a, const TGLC_bn *d, TGLC_bn_ctx *ctx) { (void) ctx; gcry_mpi_div (unwrap_bn (dv), unwrap_bn (rem), unwrap_bn (a), unwrap_bn (d), 0); return 1; } int TGLC_bn_mod_exp (TGLC_bn *r, const TGLC_bn *a, const TGLC_bn *p, const TGLC_bn *m, TGLC_bn_ctx *ctx) { (void) ctx; gcry_mpi_powm (unwrap_bn (r), unwrap_bn (a), unwrap_bn (p), unwrap_bn (m)); return 1; } #endif ================================================ FILE: crypto/bn_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL #include #include #include "bn.h" #include "meta.h" TGLC_WRAPPER_ASSOC(bn_ctx,BN_CTX) TGLC_WRAPPER_ASSOC(bn,BIGNUM) TGLC_bn_ctx *TGLC_bn_ctx_new (void) { return wrap_bn_ctx (BN_CTX_new ()); } void TGLC_bn_ctx_free (TGLC_bn_ctx* ctx) { BN_CTX_free (unwrap_bn_ctx (ctx)); } TGLC_bn *TGLC_bn_new (void) { return wrap_bn (BN_new ()); } void TGLC_bn_free (TGLC_bn *a) { BN_free (unwrap_bn (a)); } void TGLC_bn_clear_free (TGLC_bn *a) { BN_clear_free (unwrap_bn (a)); } int TGLC_bn_cmp (const TGLC_bn *a, const TGLC_bn *b) { return BN_cmp (unwrap_bn (a), unwrap_bn (b)); } int TGLC_bn_is_prime (const TGLC_bn *a, int checks, void (*callback) (int, int, void *), TGLC_bn_ctx *ctx, void *cb_arg) { return BN_is_prime (unwrap_bn (a), checks, callback, unwrap_bn_ctx (ctx), cb_arg); } int TGLC_bn_bn2bin (const TGLC_bn *a, unsigned char *to) { return BN_bn2bin (unwrap_bn (a), to); } TGLC_bn * TGLC_bn_bin2bn(const unsigned char *s, int len, TGLC_bn *ret) { return wrap_bn (BN_bin2bn (s, len, unwrap_bn (ret))); } int TGLC_bn_set_word (TGLC_bn *a, unsigned long w) { return BN_set_word (unwrap_bn (a), w); } unsigned long TGLC_bn_get_word (const TGLC_bn *a) { return BN_get_word (unwrap_bn (a)); } int TGLC_bn_num_bits (const TGLC_bn *a) { return BN_num_bits (unwrap_bn (a)); } void TGLC_bn_sub (TGLC_bn *r, const TGLC_bn *a, const TGLC_bn *b) { int res = BN_sub (unwrap_bn (r), unwrap_bn (a), unwrap_bn (b)); assert (res); } int TGLC_bn_div (TGLC_bn *dv, TGLC_bn *rem, const TGLC_bn *a, const TGLC_bn *d, TGLC_bn_ctx *ctx) { return BN_div (unwrap_bn (dv), unwrap_bn (rem), unwrap_bn (a), unwrap_bn (d), unwrap_bn_ctx (ctx)); } int TGLC_bn_mod_exp (TGLC_bn *r, const TGLC_bn *a, const TGLC_bn *p, const TGLC_bn *m, TGLC_bn_ctx *ctx) { return BN_mod_exp (unwrap_bn (r), unwrap_bn (a), unwrap_bn (p), unwrap_bn (m), unwrap_bn_ctx (ctx)); } #endif ================================================ FILE: crypto/err.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_ERR_H__ #define __TGL_CRYPTO_ERR_H__ #include void TGLC_err_print_errors_fp (FILE *fp); #endif ================================================ FILE: crypto/err_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL #include #include "err.h" void TGLC_err_print_errors_fp (FILE *fp) { // Can't print anything meaningful, so don't. (void) fp; } #endif ================================================ FILE: crypto/err_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL #include #include "err.h" void TGLC_err_print_errors_fp (FILE *fp) { ERR_print_errors_fp (fp); } #endif ================================================ FILE: crypto/md5.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_MD5_H__ #define __TGL_CRYPTO_MD5_H__ #include /* size_t */ void TGLC_md5 (const unsigned char *d, size_t n, unsigned char *md); #endif ================================================ FILE: crypto/md5_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL /* Marginally speed up compilation */ #define GCRYPT_NO_MPI_MACROS /* Fail-fast when something becomes deprecated. */ #define GCRYPT_NO_DEPRECATED #include #include "md5.h" void TGLC_md5 (const unsigned char *d, size_t n, unsigned char *md) { gcry_md_hash_buffer (GCRY_MD_MD5, md, d, n); } #endif ================================================ FILE: crypto/md5_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL #include #include "md5.h" void TGLC_md5(const unsigned char *d, size_t n, unsigned char *md) { MD5(d, n, md); } #endif ================================================ FILE: crypto/meta.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef CRYPTO_META_H_ #define CRYPTO_META_H_ #include /* All this wrapping/unwrapping solves a fundamental problem: * - The libtgl implementation wants access to the TGLC_* types. * - The libtgl implementation should not see any other definitions from any * external crypto library (to make sure no symbol slips "through" during the * OpenSSL-to-gcrypt transition). * - Most TGLC_* types (3 out of 4 types) are exclusively used as pointers * throughout the libtgl source, in a way to allow for incomplete types. * - The CORE type (e.g. BIGNUM from ) may be incomplete, * even for tglc. * This means the standard approaches don't work: * - TGLC_NAME can't be a typedef to CORE, since CORE shouldn't even be visible * from libtgl. * - TGLC_NAME can't be a pointer to CORE, same reason. Also, it would require * a significant amount of rewriting (error-prone work). * - TGLC_NAME can't be a void pointer. Retain type checking! * - So TGLC_NAME *must* be an incomplete custom struct. * However, this ensues the following ugliness. * * The standard doesn't explicitly allow it, but there's a pretty good argument * that casting ptr-to-some-struct to ptr-to-other-struct is *probably* okay for * most compilers: https://stackoverflow.com/a/8702750/3070326 */ #define TGLC_WRAPPER_ASSOC(NAME,CORE) \ static TGLC_ ## NAME *wrap_ ## NAME (const CORE *p) \ __attribute__ ((unused)); \ static CORE *unwrap_ ## NAME (const TGLC_ ## NAME *p) \ __attribute__ ((unused)); \ static CORE *unwrap_ ## NAME (const TGLC_ ## NAME *p) { \ return (CORE *)p; \ } \ static TGLC_ ## NAME *wrap_ ## NAME (const CORE *p) { \ return (TGLC_ ## NAME *)p; \ } #endif /* CRYPTO_META_H_ */ ================================================ FILE: crypto/rand.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_RAND_H__ #define __TGL_CRYPTO_RAND_H__ void TGLC_rand_add (const void *buf, int num, double entropy); int TGLC_rand_bytes (unsigned char *buf, int num); int TGLC_rand_pseudo_bytes (unsigned char *buf, int num); #endif ================================================ FILE: crypto/rand_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL /* Marginally speed up compilation */ #define GCRYPT_NO_MPI_MACROS /* Fail-fast when something becomes deprecated. */ #define GCRYPT_NO_DEPRECATED #include #include #include "rand.h" void TGLC_rand_add (const void *buf, int num, double entropy) { (void) entropy; // TODO: Translate half-broken "entropy" into gcry's "quality". gcry_random_add_bytes (buf, num, 50); } int TGLC_rand_bytes (unsigned char *buf, int num) { gcry_randomize (buf, num, GCRY_STRONG_RANDOM); return 1; // Don't ask why. } int TGLC_rand_pseudo_bytes (unsigned char *buf, int num) { gcry_create_nonce (buf, num); return 0; // Don't ask why. } #endif ================================================ FILE: crypto/rand_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL #include #include "rand.h" void TGLC_rand_add (const void *buf, int num, double entropy) { RAND_add (buf, num, entropy); } int TGLC_rand_bytes (unsigned char *buf, int num) { return RAND_bytes (buf, num); } int TGLC_rand_pseudo_bytes (unsigned char *buf, int num) { return RAND_pseudo_bytes (buf, num); } #endif ================================================ FILE: crypto/rsa_pem.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_RSA_H__ #define __TGL_CRYPTO_RSA_H__ #include /* FILE */ #include "bn.h" typedef struct TGLC_rsa TGLC_rsa; TGLC_rsa *TGLC_rsa_new (unsigned long e, int n_bytes, const unsigned char *n); TGLC_bn *TGLC_rsa_n (TGLC_rsa *); TGLC_bn *TGLC_rsa_e (TGLC_rsa *); void TGLC_rsa_free (TGLC_rsa *); TGLC_rsa *TGLC_pem_read_RSAPublicKey (FILE *fp); #endif ================================================ FILE: crypto/rsa_pem_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL #include #include "meta.h" #include "rsa_pem.h" #include "../tools.h" /* talloc */ struct TGLC_rsa { TGLC_bn *n; TGLC_bn *e; }; TGLC_rsa *TGLC_rsa_new (unsigned long e, int n_bytes, const unsigned char *n) { assert (n_bytes > 0 && n_bytes < 5000); TGLC_rsa *ret = talloc (sizeof (TGLC_rsa)); ret->e = TGLC_bn_new (); TGLC_bn_set_word (ret->e, e); ret->n = TGLC_bn_bin2bn (n, n_bytes, NULL); assert (n_bytes == TGLC_bn_num_bytes (ret->n)); return ret; } #define RSA_GETTER(M) \ TGLC_bn *TGLC_rsa_ ## M (TGLC_rsa *key) { \ return key->M; \ } \ RSA_GETTER(n); RSA_GETTER(e); void TGLC_rsa_free (TGLC_rsa *key) { if (key->e) { TGLC_bn_free (key->e); } if (key->n) { TGLC_bn_free (key->n); } tfree (key, sizeof (TGLC_rsa)); } TGLC_rsa *TGLC_pem_read_RSAPublicKey (FILE *fp) { /* * Reading PEM format involves ASN.1 and is hard. libgcrypt doesn't support it. * The dependency on oh-so-freaking-much code just to parse static data that * will never change is not justified. Let the caller figure out how to resolve * this (telegram-purple does so by using libpurple's built-in functions), and * ignore any PEM files. */ (void) fp; return NULL; } #endif ================================================ FILE: crypto/rsa_pem_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL //#include /* NULL */ #include #include #include "bn.h" #include "meta.h" #include "rsa_pem.h" TGLC_WRAPPER_ASSOC(rsa,RSA) // TODO: Refactor crucial struct-identity into its own header. TGLC_WRAPPER_ASSOC(bn,BIGNUM) TGLC_rsa *TGLC_rsa_new (unsigned long e, int n_bytes, const unsigned char *n) { RSA *ret = RSA_new (); ret->e = unwrap_bn (TGLC_bn_new ()); TGLC_bn_set_word (wrap_bn (ret->e), e); ret->n = unwrap_bn (TGLC_bn_bin2bn (n, n_bytes, NULL)); return wrap_rsa (ret); } #define RSA_GETTER(M) \ TGLC_bn *TGLC_rsa_ ## M (TGLC_rsa *key) { \ return wrap_bn (unwrap_rsa (key)->M); \ } \ RSA_GETTER(n); RSA_GETTER(e); void TGLC_rsa_free (TGLC_rsa *p) { RSA_free (unwrap_rsa (p)); } TGLC_rsa *TGLC_pem_read_RSAPublicKey (FILE *fp) { return wrap_rsa (PEM_read_RSAPublicKey (fp, NULL, NULL, NULL)); } #endif ================================================ FILE: crypto/sha.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #ifndef __TGL_CRYPTO_SHA_H__ #define __TGL_CRYPTO_SHA_H__ #include /* size_t */ void TGLC_sha1 (const unsigned char *d, size_t n, unsigned char *md); void TGLC_sha256 (const unsigned char *d, size_t n, unsigned char *md); #endif ================================================ FILE: crypto/sha_altern.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifdef TGL_AVOID_OPENSSL /* Marginally speed up compilation */ #define GCRYPT_NO_MPI_MACROS /* Fail-fast when something becomes deprecated. */ #define GCRYPT_NO_DEPRECATED #include #include "sha.h" void TGLC_sha1 (const unsigned char *d, size_t n, unsigned char *md) { gcry_md_hash_buffer (GCRY_MD_SHA1, md, d, n); } void TGLC_sha256 (const unsigned char *d, size_t n, unsigned char *md) { gcry_md_hash_buffer (GCRY_MD_SHA256, md, d, n); } #endif ================================================ FILE: crypto/sha_openssl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Ben Wiederhake 2015 */ #include "../config.h" #ifndef TGL_AVOID_OPENSSL #include #include "sha.h" void TGLC_sha1 (const unsigned char *d, size_t n, unsigned char *md) { SHA1 (d, n, md); } void TGLC_sha256 (const unsigned char *d, size_t n, unsigned char *md) { SHA256 (d, n, md); } #endif ================================================ FILE: encrypted_scheme.tl ================================================ ---types--- decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia; decryptedMessageMediaPhoto#32798a8c str_thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia; decryptedMessageMediaGeoPoint#35480a59 latitude:double longitude:double = DecryptedMessageMedia; decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia; decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction; decryptedMessageMediaDocument#b095434b str_thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia; decryptedMessageActionReadMessages#c4f40be random_ids:Vector = DecryptedMessageAction; decryptedMessageActionDeleteMessages#65614304 random_ids:Vector = DecryptedMessageAction; decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector = DecryptedMessageAction; decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction; decryptedMessage#204d3878 random_id:long ttl:int message:string media:DecryptedMessageMedia = DecryptedMessage; decryptedMessageService#73164160 random_id:long action:DecryptedMessageAction = DecryptedMessage; decryptedMessageMediaVideo#524a415d str_thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia; decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia; decryptedMessageLayer#1be31789 random_bytes:bytes layer:int in_seq_no:int out_seq_no:int message:DecryptedMessage = DecryptedMessageLayer; decryptedMessageActionResend#511110b0 start_seq_no:int end_seq_no:int = DecryptedMessageAction; decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction; decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction; decryptedMessageActionRequestKey#f3c9611b exchange_id:long g_a:bytes = DecryptedMessageAction; decryptedMessageActionAcceptKey#6fe1735b exchange_id:long g_b:bytes key_fingerprint:long = DecryptedMessageAction; decryptedMessageActionAbortKey#dd05ec6b exchange_id:long = DecryptedMessageAction; decryptedMessageActionCommitKey#ec2e0b9b exchange_id:long key_fingerprint:long = DecryptedMessageAction; decryptedMessageActionNoop#a82fdd63 = DecryptedMessageAction; decryptedMessageMediaExternalDocument#fa95b0dd id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector = DecryptedMessageMedia; ---functions--- ================================================ FILE: errors ================================================ type of errors that tgl can set: EPROTO: server returned error for query. Some kinds of error (such as FLOOD_WAIT) tgl can handle by itself, but others it can not. In most cases it means bug in tgl or invalid parameter supplied to method (such as message id). On BSD, EPROTO is not defined. Whenever EPROTO is not #define'd, tgl uses EIO instead. EINVAL: tgl detected invalid argument supplied before sending query to server. For example user instead of chat or bad msg id. ENOENT: tgl received empty response from server. For example when user tried to get message by id EBADF: tgl can not open file on disk or file is empty E2BIG: supplied file is too big ENOTCONN: no public keys available ================================================ FILE: event-old.h ================================================ #ifndef __EVENT_OLD_H__ #define __EVENT_OLD_H__ #include #include #define BEV_EVENT_READ EVBUFFER_READ #define BEV_EVENT_WRITE EVBUFFER_WRITE #define BEV_EVENT_EOF EVBUFFER_EOF #define BEV_EVENT_ERROR EVBUFFER_ERROR #define BEV_EVENT_TIMEOUT EVBUFFER_TIMEOUT typedef int evutil_socket_t; static inline struct event *event_new (struct event_base *base, int fd, int what, void(*callback)(int, short, void *), void *arg) __attribute__ ((unused)); static inline struct event *event_new (struct event_base *base, int fd, int what, void(*callback)(int, short, void *), void *arg) { struct event *ev = malloc (sizeof (*ev)); event_set (ev, fd, what, callback, arg); event_base_set (base, ev); return ev; } static inline struct event *evtimer_new (struct event_base *base, void(*callback)(int, short, void *), void *arg) __attribute__ ((unused)); static inline struct event *evtimer_new (struct event_base *base, void(*callback)(int, short, void *), void *arg) { struct event *ev = malloc (sizeof (*ev)); event_set (ev, -1, 0, callback, arg); event_base_set (base, ev); return ev; } static void event_free (struct event *ev) __attribute__ ((unused)); static void event_free (struct event *ev) { event_del (ev); free (ev); } static struct bufferevent *bufferevent_socket_new (struct event_base *base, int fd, int flags) __attribute__ ((unused)); static struct bufferevent *bufferevent_socket_new (struct event_base *base, int fd, int flags) { assert (!flags); struct bufferevent *bev = bufferevent_new(fd, 0, 0, 0, 0); bufferevent_base_set (base, bev); return bev; } static inline void *event_get_callback_arg(const struct event *ev) { return ev->ev_arg; } #endif ================================================ FILE: gen_constants_h.awk ================================================ BEGIN { print "/*"; print " This file is part of telegram-client."; print ""; print " Telegram-client is free software: you can redistribute it and/or modify"; print " it under the terms of the GNU General Public License as published by"; print " the Free Software Foundation, either version 2 of the License, or"; print " (at your option) any later version."; print ""; print " Telegram-client is distributed in the hope that it will be useful,"; print " but WITHOUT ANY WARRANTY; without even the implied warranty of"; print " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"; print " GNU General Public License for more details."; print ""; print " You should have received a copy of the GNU General Public License"; print " along with this telegram-client. If not, see ."; print ""; print " Copyright Vitaly Valtman 2013"; print "*/"; print "#ifndef CONSTANTS_H"; print "#define CONSTANTS_H"; } // { if (split ($1, a, "#") == 2) { gsub (/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/, "_&", a[1]); gsub (/[.]/, "_", a[1]); if (a[2] in h) { print "ERROR: Duplicate magic " a[2] " for define " a[1] " and " h[a[2]] > "/dev/stderr" exit 1; } h[a[2]] = a[1]; print "#define", "CODE_" tolower(a[1]), "0x" a[2]; } } END { print "#endif"; } ================================================ FILE: generate.c ================================================ /* This file is part of tgl-libary/generate Tgl-library/generate 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. Tgl-library/generate 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 tgl-library/generate. If not, see . Copyright Vitaly Valtman 2014-2015 It is derivative work of VK/KittenPHP-DB-Engine (https://github.com/vk-com/kphp-kdb/) Copyright 2012-2013 Vkontakte Ltd 2012-2013 Vitaliy Valtman */ #define _GNU_SOURCE #include "config.h" #include #include #ifdef HAVE_EXECINFO_H #include #endif #include #include #include #include #include #include #include #include #if defined(_MSC_VER) || defined(__MINGW32__) /* Find the length of STRING, but scan at most MAXLEN characters. If no '\0' terminator is found in that many characters, return MAXLEN. */ size_t strnlen (const char *string, size_t maxlen) { const char *end = memchr (string, '\0', maxlen); return end ? (size_t)(end - string) : maxlen; } char *strndup (const char *s, size_t n) { size_t len = strnlen (s, n); char *new = malloc (len + 1); if (new == NULL) return NULL; new[len] = '\0'; return memcpy (new, s, len); } #define INT64_PRINTF_MODIFIER "I64" #else #define INT64_PRINTF_MODIFIER "ll" #endif #include "tl-parser/tl-tl.h" #include "generate.h" #include "tree.h" int header; #define tl_type_name_cmp(a,b) (a->name > b->name ? 1 : a->name < b->name ? -1 : 0) DEFINE_TREE (tl_type, struct tl_type *, tl_type_name_cmp, 0) DEFINE_TREE (tl_combinator, struct tl_combinator *, tl_type_name_cmp, 0) struct tree_tl_type *type_tree; struct tree_tl_combinator *function_tree; void tl_function_insert_by_name (struct tl_combinator *c) { function_tree = tree_insert_tl_combinator (function_tree, c, rand ()); } struct tl_type *tl_type_get_by_name (int name) { static struct tl_type t; t.name = name; return tree_lookup_tl_type (type_tree, &t); } void tl_type_insert_by_name (struct tl_type *t) { type_tree = tree_insert_tl_type (type_tree, t, rand ()); } int is_empty (struct tl_type *t) { if (t->name == NAME_INT || t->name == NAME_LONG || t->name == NAME_DOUBLE || t->name == NAME_STRING) { return 1; } if (t->constructors_num != 1) { return 0; } int count = 0; int i; struct tl_combinator *c = t->constructors[0]; for (i = 0; i < c->args_num; i++) { if (!(c->args[i]->flags & FLAG_OPT_VAR)) { count ++; } } return count == 1; } static char buf[1 << 20]; int buf_size; int *buf_ptr = (int *)buf; int *buf_end; #ifndef DISABLE_EXTF int skip_only = 0; #else int skip_only = 1; #endif int verbosity; int get_int (void) { assert (buf_ptr < buf_end); return *(buf_ptr ++); } long long get_long (void) { assert (buf_ptr + 1 < buf_end); long long r = *(long long *)buf_ptr; buf_ptr += 2; return r; } static void *malloc0 (int size) { void *r = malloc (size); assert (r); memset (r, 0, size); return r; } char *get_string (void) { int l = *(unsigned char *)buf_ptr; assert (l != 0xff); char *res; int tlen = 0; if (l == 0xfe) { l = ((unsigned)get_int ()) >> 8; res = (char *)buf_ptr; tlen = l; } else { res = ((char *)buf_ptr) + 1; tlen = 1 + l; } int len = l; tlen += ((-tlen) & 3); assert (!(tlen & 3)); buf_ptr += tlen / 4; assert (buf_ptr <= buf_end); char *r = strndup (res, len); assert (r); return r; } int tn, fn, cn; struct tl_type **tps; struct tl_combinator **fns; struct tl_tree *read_tree (int *var_num); struct tl_tree *read_nat_expr (int *var_num); struct tl_tree *read_type_expr (int *var_num); int read_args_list (struct arg **args, int args_num, int *var_num); #define use_var_nat_full_form(x) 0 void *int_to_var_nat_const_init (long long x) { if (use_var_nat_full_form (x)) { struct tl_tree_nat_const *T = malloc (sizeof (*T)); assert (T); T->self.flags = 0; T->self.methods = &tl_pnat_const_full_methods; T->value = x; return T; } else { return (void *)(long)(x * 2 - 0x80000001l); } } long long var_nat_const_to_int (void *x) { if (((long)x) & 1) { return (((long)x) + 0x80000001l) / 2; } else { return ((struct tl_tree_nat_const *)x)->value; } } int tl_tree_type_type (struct tl_tree *x) { return NODE_TYPE_TYPE; } int tl_tree_type_array (struct tl_tree *x) { return NODE_TYPE_ARRAY; } int tl_tree_type_nat_const (struct tl_tree *x) { return NODE_TYPE_NAT_CONST; } int tl_tree_type_var_num (struct tl_tree *x) { return NODE_TYPE_VAR_NUM; } int tl_tree_type_var_type (struct tl_tree *x) { return NODE_TYPE_VAR_TYPE; } struct tl_tree_methods tl_var_num_methods = { .type = tl_tree_type_var_num }; struct tl_tree_methods tl_var_type_methods = { .type = tl_tree_type_var_type }; struct tl_tree_methods tl_type_methods = { .type = tl_tree_type_type }; struct tl_tree_methods tl_nat_const_methods = { .type = tl_tree_type_nat_const }; struct tl_tree_methods tl_array_methods = { .type = tl_tree_type_array }; struct tl_tree_methods tl_ptype_methods = { .type = tl_tree_type_type }; struct tl_tree_methods tl_parray_methods = { .type = tl_tree_type_array }; struct tl_tree_methods tl_pvar_num_methods = { .type = tl_tree_type_var_num }; struct tl_tree_methods tl_pvar_type_methods = { .type = tl_tree_type_var_type }; struct tl_tree_methods tl_nat_const_full_methods = { .type = tl_tree_type_nat_const }; struct tl_tree_methods tl_pnat_const_full_methods = { .type = tl_tree_type_nat_const }; struct tl_tree *read_num_const (int *var_num) { return (void *)int_to_var_nat_const_init (get_int ()); } void print_c_type_name (struct tl_tree *t, char *offset, int in) { int x = TL_TREE_METHODS(t)->type (t); if (x == NODE_TYPE_VAR_TYPE) { printf ("void *"); return; } if (x == NODE_TYPE_ARRAY) { struct tl_tree_array *a = (void *)t; assert (a->args_num == 1); print_c_type_name (a->args[0]->type, offset, in); printf ("*"); return; } struct tl_type *T = ((struct tl_tree_type *)t)->type; if (!strcmp (T->id, "Vector") && in) { printf ("struct {\n"); printf ("%s int *cnt;\n", offset); printf ("%s ", offset); print_c_type_name (((struct tl_tree_type *)t)->children[0], offset, in); printf ("*data;\n"); printf ("%s} *", offset); return; } if (!strcmp (T->id, "Long")) { printf ("long long *"); return; } if (!strcmp (T->id, "#") || !strcmp (T->id, "Int")) { printf ("int *"); return; } if (!strcmp (T->id, "Double")) { printf ("double *"); return; } if (!strcmp (T->id, "String") || !strcmp (T->id, "Bytes")) { /*printf ("struct {\n"); printf ("%s int len;\n", offset); printf ("%s char *data;\n", offset); printf ("%s} *", offset); return;*/ printf ("struct tl_ds_string *"); return; } printf ("struct tl_ds_%s *", T->print_id); } int gen_uni_skip (struct tl_tree *t, char *cur_name, int *vars, int first, int fun) { assert (t); int x = TL_TREE_METHODS (t)->type (t); int l = 0; int i; int j; struct tl_tree_type *t1; struct tl_tree_array *t2; int y; int L = strlen (cur_name); char *fail = fun == 1 ? "return 0;" : fun == -1 ? "return;" : "return -1;"; switch (x) { case NODE_TYPE_TYPE: t1 = (void *)t; if (!first) { printf (" if (ODDP(%s) || %s->type->name != 0x%08x) { %s }\n", cur_name, cur_name, t1->type->name, fail); } else { printf (" if (ODDP(%s) || (%s->type->name != 0x%08x && %s->type->name != 0x%08x)) { %s }\n", cur_name, cur_name, t1->type->name, cur_name, ~t1->type->name, fail); } for (i = 0; i < t1->children_num; i++) { sprintf (cur_name + L, "->params[%d]", i); gen_uni_skip (t1->children[i], cur_name, vars, 0, fun); cur_name[L] = 0; } return 0; case NODE_TYPE_NAT_CONST: printf (" if (EVENP(%s) || ((long)%s) != %" INT64_PRINTF_MODIFIER "d) { %s }\n", cur_name, cur_name, var_nat_const_to_int (t) * 2 + 1, fail); return 0; case NODE_TYPE_ARRAY: printf (" if (ODDP(%s) || %s->type->name != TL_TYPE_ARRAY) { %s }\n", cur_name, cur_name, fail); t2 = (void *)t; sprintf (cur_name + L, "->params[0]"); y = gen_uni_skip (t2->multiplicity, cur_name, vars, 0, fun); cur_name[L] = 0; sprintf (cur_name + L, "->params[1]"); y += gen_uni_skip (t2->args[0]->type, cur_name, vars, 0, fun); cur_name[L] = 0; return 0; case NODE_TYPE_VAR_TYPE: printf (" if (ODDP(%s)) { %s }\n", cur_name, fail); i = ((struct tl_tree_var_type *)t)->var_num; if (!vars[i]) { printf (" struct paramed_type *var%d = %s; assert (var%d);\n", i, cur_name, i); vars[i] = 1; } else if (vars[i] == 1) { printf (" if (compare_types (var%d, %s) < 0) { %s }\n", i, cur_name, fail); } else { assert (0); return -1; } return l; case NODE_TYPE_VAR_NUM: printf (" if (EVENP(%s)) { %s }\n", cur_name, fail); i = ((struct tl_tree_var_num *)t)->var_num; j = ((struct tl_tree_var_num *)t)->dif; if (!vars[i]) { printf (" struct paramed_type *var%d = ((void *)%s) + %d; assert (var%d);\n", i, cur_name, 2 * j, i); vars[i] = 2; } else if (vars[i] == 2) { printf (" if (var%d != ((void *)%s) + %d) { %s }\n", i, cur_name, 2 * j, fail); } else { assert (0); return -1; } return 0; default: assert (0); return -1; } } void print_offset (int len) { int i; for (i = 0; i < len; i++) { printf (" "); } } int gen_create (struct tl_tree *t, int *vars, int offset) { int x = TL_TREE_METHODS (t)->type (t); int i; struct tl_tree_type *t1; struct tl_tree_array *t2; switch (x) { case NODE_TYPE_TYPE: print_offset (offset); printf ("&(struct paramed_type){\n"); print_offset (offset + 2); t1 = (void *)t; if (t1->self.flags & FLAG_BARE) { printf (".type = &(struct tl_type_descr) {.name = 0x%08x, .id = \"Bare_%s\", .params_num = %d, .params_types = %" INT64_PRINTF_MODIFIER "d},\n", ~t1->type->name, t1->type->id, t1->type->arity, t1->type->params_types); } else { printf (".type = &(struct tl_type_descr) {.name = 0x%08x, .id = \"%s\", .params_num = %d, .params_types = %" INT64_PRINTF_MODIFIER "d},\n", t1->type->name, t1->type->id, t1->type->arity, t1->type->params_types); } if (t1->children_num) { print_offset (offset + 2); printf (".params = (struct paramed_type *[]){\n"); for (i = 0; i < t1->children_num; i++) { assert (gen_create (t1->children[i], vars, offset + 4) >= 0); printf (",\n"); } print_offset (offset + 2); printf ("}\n"); } else { print_offset (offset + 2); printf (".params = 0,\n"); } print_offset (offset); printf ("}"); return 0; case NODE_TYPE_NAT_CONST: print_offset (offset); printf ("INT2PTR (%d)", (int)var_nat_const_to_int (t)); return 0; case NODE_TYPE_ARRAY: print_offset (offset); printf ("&(struct paramed_type){\n"); print_offset (offset + 2); t2 = (void *)t; printf (".type = &(struct tl_type_descr) {.name = NAME_ARRAY, .id = \"array\", .params_num = 2, .params_types = 1},\n"); print_offset (offset + 2); printf (".params = (struct paramed_type **){\n"); gen_create (t2->multiplicity, vars, offset + 4); printf (",\n"); gen_create (t2->args[0]->type, vars, offset + 4); printf (",\n"); print_offset (offset + 2); printf ("}\n"); print_offset (offset); printf ("}"); return 0; case NODE_TYPE_VAR_TYPE: print_offset (offset); printf ("var%d", ((struct tl_tree_var_type *)t)->var_num); return 0; case NODE_TYPE_VAR_NUM: print_offset (offset); printf ("((void *)var%d) + %d", ((struct tl_tree_var_type *)t)->var_num, 2 * ((struct tl_tree_var_num *)t)->dif); return 0; default: assert (0); return -1; } } int gen_field_skip (struct arg *arg, int *vars, int num) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } if (arg->var_num >= 0) { assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); if (vars[arg->var_num] == 0) { printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); printf ("%sif (vars%d != INT2PTR (fetch_int ())) { return -1; }\n", offset, arg->var_num); } else { assert (0); return -1; } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } if (!bare) { printf ("%sif (skip_type_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); } else { printf ("%sif (skip_type_bare_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); } } else { assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); printf ("%s if (skip_type_%s (field%d) < 0) { return -1;}\n", offset, "any", num); printf ("%s}\n", offset); } } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_fetch (struct arg *arg, int *vars, int num, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } if (!empty) { printf("%sif (multiline_output >= 2) { print_offset (); }\n", offset); } if (arg->id && strlen (arg->id) && !empty) { printf ("%sif (!disable_field_names) { eprintf (\" %s :\"); }\n", offset, arg->id); } if (arg->var_num >= 0) { assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); if (vars[arg->var_num] == 0) { printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); printf ("%seprintf (\" %%d\", prefetch_int ());\n", offset); printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sif (in_remaining () < 4) { return -1;}\n", offset); printf ("%seprintf (\" %%d\", prefetch_int ());\n", offset); printf ("%sif (vars%d != INT2PTR (fetch_int ())) { return -1; }\n", offset, arg->var_num); } else { assert (0); return -1; } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } if (!bare) { printf ("%sif (fetch_type_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); } else { printf ("%sif (fetch_type_bare_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); } } else { assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%seprintf (\" [\");\n", offset); printf ("%sif (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset); printf ("%sif (multiline_output >= 1) { multiline_offset += multiline_offset_size;}\n", offset); printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); printf ("%s if (multiline_output >= 1) { print_offset (); }\n", offset); printf ("%s if (fetch_type_%s (field%d) < 0) { return -1;}\n", offset, "any", num); printf ("%s if (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset); printf ("%s}\n", offset); printf ("%sif (multiline_output >= 1) { multiline_offset -= multiline_offset_size; print_offset ();}\n", offset); printf ("%seprintf (\" ]\");\n", offset); } } if (!empty) { printf("%sif (multiline_output >= 2) { eprintf (\"\\n\"); }\n", offset); } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_store (struct arg *arg, int *vars, int num, int from_func, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } char *fail = from_func ? "0" : "-1"; char *expect = from_func ? "expect_token_ptr" : "expect_token"; if (arg->id && strlen (arg->id) > 0 && !empty) { printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); printf ("%s local_next_token ();\n", offset); printf ("%s %s (\":\", 1);\n", offset, expect); printf ("%s}\n", offset); } if (arg->var_num >= 0) { printf ("%sif (cur_token_len < 0) { return %s; }\n", offset, fail); assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); if (vars[arg->var_num] == 0) { printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); printf ("%sstruct paramed_type *var%d = INT2PTR (get_int ());\n", offset, arg->var_num); printf ("%sout_int (get_int ());\n", offset); printf ("%sassert (var%d);\n", offset, arg->var_num); printf ("%slocal_next_token ();\n", offset); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); printf ("%sif (vars%d != INT2PTR (get_int ())) { return %s; }\n", offset, arg->var_num, fail); printf ("%sout_int (get_int ());\n", offset); printf ("%slocal_next_token ();\n", offset); } else { assert (0); return -1; } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } if (!bare) { printf ("%sif (store_type_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); } else { printf ("%sif (store_type_bare_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); } } else { printf ("%s%s (\"[\", 1);\n", offset, expect); assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); printf ("%s if (store_type_%s (field%d) < 0) { return %s;}\n", offset, "any", num, fail); printf ("%s}\n", offset); printf ("%s%s (\"]\", 1);\n", offset, expect); } } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_autocomplete (struct arg *arg, int *vars, int num, int from_func, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } char *fail = from_func ? "0" : "-1"; char *expect = from_func ? "expect_token_ptr_autocomplete" : "expect_token_autocomplete"; if (arg->id && strlen (arg->id) > 0 && !empty) { printf ("%sif (cur_token_len == -3 && cur_token_real_len <= %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_real_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); printf ("%s set_autocomplete_string (\"%s\");\n", offset, arg->id); printf ("%s return %s;\n", offset, fail); printf ("%s}\n", offset); printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); printf ("%s local_next_token ();\n", offset); printf ("%s %s (\":\", 1);\n", offset, expect); printf ("%s}\n", offset); } if (arg->var_num >= 0) { printf ("%sif (cur_token_len < 0) { return %s; }\n", offset, fail); assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); if (vars[arg->var_num] == 0) { printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); printf ("%sstruct paramed_type *var%d = INT2PTR (get_int ());\n", offset, arg->var_num); printf ("%sassert (var%d);\n", offset, arg->var_num); printf ("%slocal_next_token ();\n", offset); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sif (!is_int ()) { return %s;}\n", offset, fail); printf ("%sif (vars%d != INT2PTR (get_int ())) { return %s; }\n", offset, arg->var_num, fail); printf ("%slocal_next_token ();\n", offset); } else { assert (0); return -1; } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } if (!bare) { printf ("%sif (autocomplete_type_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); } else { printf ("%sif (autocomplete_type_bare_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail); } } else { printf ("%s%s (\"[\", 1);\n", offset, expect); assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num); printf ("%s if (autocomplete_type_%s (field%d) < 0) { return %s;}\n", offset, "any", num, fail); printf ("%s}\n", offset); printf ("%s%s (\"]\", 1);\n", offset, expect); } } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_fetch_ds (struct arg *arg, int *vars, int num, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } if (arg->var_num >= 0) { assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); printf ("%sassert (in_remaining () >= 4);\n", offset); if (arg->id && strlen (arg->id)) { printf ("%sresult->%s = talloc (4);", offset, arg->id); printf ("%s*result->%s = prefetch_int ();", offset, arg->id); } else { printf ("%sresult->f%d = talloc (4);", offset, num - 1); printf ("%s*result->f%d = prefetch_int ();", offset, num - 1); } if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == INT2PTR (fetch_int ()));\n", offset, arg->var_num); } else { assert (0); return -1; } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } if (arg->id && strlen (arg->id)) { printf ("%sresult->%s = ", offset, arg->id); } else { printf ("%sresult->f%d = ", offset, num - 1); } if (t == NODE_TYPE_TYPE && !strcmp (((struct tl_tree_type *)arg->type)->type->id, "Vector")) { printf ("(void *)"); } if (!bare) { printf ("fetch_ds_type_%s (field%d);\n", t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); } else { printf ("fetch_ds_type_bare_%s (field%d);\n", t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num); } } else { assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); if (arg->id && strlen (arg->id)) { printf ("%sresult->%s = ", offset, arg->id); } else { printf ("%sresult->f%d = ", offset, num - 1); } printf ("talloc0 (multiplicity%d * sizeof (void *));\n", num); printf ("%s{\n", offset); printf ("%s int i = 0;\n", offset); printf ("%s while (i < multiplicity%d) {\n", offset, num); if (arg->id && strlen (arg->id)) { printf ("%s result->%s[i ++] =", offset, arg->id); } else { printf ("%s result->f%d[i ++] = ", offset, num - 1); } printf ("fetch_ds_type_%s (field%d);\n", "any", num); printf ("%s }\n", offset); printf ("%s}\n", offset); } } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_free_ds (struct arg *arg, int *vars, int num, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } if (arg->var_num >= 0) { assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); if (arg->id && strlen (arg->id)) { if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (*D->%s);\n", offset, arg->var_num, arg->id); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == INT2PTR (*D->%s));\n", offset, arg->var_num, arg->id); } printf ("%stfree (D->%s, sizeof (*D->%s));\n", offset, arg->id, arg->id); } else { if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (*D->f%d);\n", offset, arg->var_num, num - 1); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == *D->f%d);\n", offset, arg->var_num, num - 1); } printf ("%stfree (D->f%d, sizeof (*D->f%d));\n", offset, num - 1, num - 1); } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int any = (t == NODE_TYPE_VAR_TYPE) || ((struct tl_tree_type *)arg->type)->type->name == NAME_VECTOR; if (arg->id && strlen (arg->id)) { printf ("%sfree_ds_type_%s (D->%s, field%d);\n", offset, any ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, arg->id, num); } else { printf ("%sfree_ds_type_%s (D->f%d, field%d);\n", offset, any ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num - 1, num); } } else { assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%s{\n", offset); printf ("%s int i = 0;\n", offset); printf ("%s while (i < multiplicity%d) {\n", offset, num); if (arg->id && strlen (arg->id)) { printf ("%s free_ds_type_%s (D->%s[i ++], field%d);\n", offset, "any", arg->id, num); } else { printf ("%s free_ds_type_%s (D->f%d[i ++], field%d);\n", offset, "any", num - 1, num); } printf ("%s }\n", offset); printf ("%s}\n", offset); if (arg->id && strlen (arg->id)) { printf ("%stfree (D->%s, sizeof (void *) * multiplicity%d);\n", offset, arg->id, num); } else { printf ("%stfree (D->f%d, sizeof (void *) * multiplicity%d);\n", offset, num - 1, num); } } } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_store_ds (struct arg *arg, int *vars, int num, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } if (arg->var_num >= 0) { assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { assert (t == NAME_VAR_NUM); if (arg->id && strlen (arg->id)) { if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (*D->%s);\n", offset, arg->var_num, arg->id); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == INT2PTR (*D->%s));\n", offset, arg->var_num, arg->id); } printf ("%sout_int (PTR2INT (var%d));\n", offset, arg->var_num); } else { if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (*D->f%d);\n", offset, arg->var_num, num - 1); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == *D->f%d);\n", offset, arg->var_num, num - 1); } printf ("%sout_int (PTR2INT (var%d));\n", offset, arg->var_num); } } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int any = (t == NODE_TYPE_VAR_TYPE); int vec = ((struct tl_tree_type *)arg->type)->type->name == NAME_VECTOR; if (arg->id && strlen (arg->id)) { printf ("%sstore_ds_type_%s%s (%sD->%s, field%d);\n", offset, bare ? "bare_" : "", any ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, vec ? "(void *)" : "", arg->id, num); } else { printf ("%sstore_ds_type_%s%s (%sD->f%d, field%d);\n", offset, bare ? "bare_" : "", any ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, vec ? "(void *)" : "", num - 1, num); } } else { assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%s{\n", offset); printf ("%s int i = 0;\n", offset); printf ("%s while (i < multiplicity%d) {\n", offset, num); if (arg->id && strlen (arg->id)) { printf ("%s store_ds_type_%s (D->%s[i ++], field%d);\n", offset, "any", arg->id, num); } else { printf ("%s store_ds_type_%s (D->f%d[i ++], field%d);\n", offset, "any", num - 1, num); } printf ("%s }\n", offset); printf ("%s}\n", offset); } } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_print_ds (struct arg *arg, int *vars, int num, int empty) { assert (arg); char *offset = " "; int o = 0; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; o = 2; } if (!empty) { printf("%sif (multiline_output >= 2) { print_offset (); }\n", offset); } if (arg->id && strlen (arg->id) && !empty) { printf ("%sif (!disable_field_names) { eprintf (\" %s :\"); }\n", offset, arg->id); } if (arg->var_num >= 0) { assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE); int t = ((struct tl_tree_type *)arg->type)->type->name; if (t == NAME_VAR_TYPE) { fprintf (stderr, "Not supported yet\n"); assert (0); } else { if (arg->id && strlen (arg->id)) { if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (*DS->%s);\n", offset, arg->var_num, arg->id); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == INT2PTR (*DS->%s));\n", offset, arg->var_num, arg->id); } } else { if (vars[arg->var_num] == 0) { printf ("%sstruct paramed_type *var%d = INT2PTR (*DS->f%d);\n", offset, arg->var_num, num - 1); vars[arg->var_num] = 2; } else if (vars[arg->var_num] == 2) { printf ("%sassert (vars%d == *DS->f%d);\n", offset, arg->var_num, num - 1); } } printf ("%seprintf (\" %%d\", (int)PTR2INT (var%d));\n", offset, arg->var_num); } } else { int t = TL_TREE_METHODS (arg->type)->type (arg->type); if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) { printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (arg->type, vars, 2 + o) >= 0); printf (";\n"); int bare = arg->flags & FLAG_BARE; if (!bare && t == NODE_TYPE_TYPE) { bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE; } int any = (t == NODE_TYPE_VAR_TYPE); int vec = ((struct tl_tree_type *)arg->type)->type->name == NAME_VECTOR; if (arg->id && strlen (arg->id)) { printf ("%sprint_ds_type_%s%s (%sDS->%s, field%d);\n", offset, bare ? "bare_" : "", any ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, vec ? "(void *)" : "", arg->id, num); } else { printf ("%sprint_ds_type_%s%s (%sDS->f%d, field%d);\n", offset, bare ? "bare_" : "", any ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, vec ? "(void *)" : "", num - 1, num); } } else { assert (t == NODE_TYPE_ARRAY); printf ("%sint multiplicity%d = PTR2INT (\n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0); printf ("%s);\n", offset); printf ("%sstruct paramed_type *field%d = \n", offset, num); assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0); printf (";\n"); printf ("%seprintf (\" [\");\n", offset); printf ("%sif (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset); printf ("%sif (multiline_output >= 1) { multiline_offset += multiline_offset_size;}\n", offset); printf ("%s{\n", offset); printf ("%s int i = 0;\n", offset); printf ("%s while (i < multiplicity%d) {\n", offset, num); printf ("%s if (multiline_output >= 1) { print_offset (); }\n", offset); if (arg->id && strlen (arg->id)) { printf ("%s print_ds_type_%s (DS->%s[i ++], field%d);\n", offset, "any", arg->id, num); } else { printf ("%s print_ds_type_%s (DS->f%d[i ++], field%d);\n", offset, "any", num - 1, num); } printf ("%s if (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset); printf ("%s }\n", offset); printf ("%s}\n", offset); printf ("%sif (multiline_output >= 1) { multiline_offset -= multiline_offset_size; print_offset ();}\n", offset); printf ("%seprintf (\" ]\");\n", offset); } } if (!empty) { printf("%sif (multiline_output >= 2) { eprintf (\"\\n\"); }\n", offset); } if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_autocomplete_excl (struct arg *arg, int *vars, int num, int from_func) { assert (arg); assert (arg->var_num < 0); char *offset = " "; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; } char *fail = from_func ? "0" : "-1"; char *expect = from_func ? "expect_token_ptr_autocomplete" : "expect_token_autocomplete"; if (arg->id && strlen (arg->id) > 0) { printf ("%sif (cur_token_len == -3 && cur_token_real_len <= %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_real_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); printf ("%s set_autocomplete_string (\"%s\");\n", offset, arg->id); printf ("%s return %s;\n", offset, fail); printf ("%s}\n", offset); printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); printf ("%s local_next_token ();\n", offset); printf ("%s %s (\":\", 1);\n", offset, expect); printf ("%s}\n", offset); } int t = TL_TREE_METHODS (arg->type)->type (arg->type); assert (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE); printf ("%sstruct paramed_type *field%d = autocomplete_function_any ();\n", offset, num); printf ("%sif (!field%d) { return 0; }\n", offset, num); printf ("%sadd_var_to_be_freed (field%d);\n", offset, num); static char s[20]; sprintf (s, "field%d", num); gen_uni_skip (arg->type, s, vars, 1, 1); if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } int gen_field_store_excl (struct arg *arg, int *vars, int num, int from_func) { assert (arg); assert (arg->var_num < 0); char *offset = " "; if (arg->exist_var_num >= 0) { printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit); offset = " "; } char *expect = from_func ? "expect_token_ptr" : "expect_token"; if (arg->id && strlen (arg->id) > 0) { printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id); printf ("%s local_next_token ();\n", offset); printf ("%s %s (\":\", 1);\n", offset, expect); printf ("%s}\n", offset); } int t = TL_TREE_METHODS (arg->type)->type (arg->type); assert (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE); printf ("%sstruct paramed_type *field%d = store_function_any ();\n", offset, num); printf ("%sif (!field%d) { return 0; }\n", offset, num); static char s[20]; sprintf (s, "field%d", num); gen_uni_skip (arg->type, s, vars, 1, 1); if (arg->exist_var_num >= 0) { printf (" }\n"); } return 0; } void gen_constructor_skip (struct tl_combinator *c) { printf ("int skip_constructor_%s (struct paramed_type *T) {\n", c->print_id); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" return -1;\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (in_remaining () < 4) { return -1;}\n"); printf (" fetch_int ();\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" if (in_remaining () < 8) { return -1;}\n"); printf (" fetch_long ();\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING) { printf (" int l = prefetch_strlen ();\n"); printf (" if (l < 0) { return -1;}\n"); printf (" fetch_str (l);\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" if (in_remaining () < 8) { return -1;}\n"); printf (" fetch_double ();\n"); printf (" return 0;\n"); printf ("}\n"); return; } for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_skip (c->args[i], vars, i + 1) >= 0); } free (vars); printf (" return 0;\n"); printf ("}\n"); } void gen_constructor_fetch (struct tl_combinator *c) { printf ("int fetch_constructor_%s (struct paramed_type *T) {\n", c->print_id); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" return -1;\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (in_remaining () < 4) { return -1;}\n"); printf (" eprintf (\" %%d\", fetch_int ());\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" if (in_remaining () < 8) { return -1;}\n"); printf (" eprintf (\" %%" INT64_PRINTF_MODIFIER "d\", fetch_long ());\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING) { printf (" static char buf[1 << 22];\n"); printf (" int l = prefetch_strlen ();\n"); printf (" if (l < 0 || (l >= (1 << 22) - 2)) { return -1; }\n"); printf (" memcpy (buf, fetch_str (l), l);\n"); printf (" buf[l] = 0;\n"); printf (" print_escaped_string (buf, l);\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" if (in_remaining () < 8) { return -1;}\n"); printf (" eprintf (\" %%lf\", fetch_double ());\n"); printf (" return 0;\n"); printf ("}\n"); return; } assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE); int empty = is_empty (((struct tl_tree_type *)c->result)->type); if (!empty) { printf (" eprintf (\" %s\");\n", c->id); printf (" if (multiline_output >= 2) { eprintf (\"\\n\"); }\n"); } for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_fetch (c->args[i], vars, i + 1, empty) >= 0); } free (vars); printf (" return 0;\n"); printf ("}\n"); } void gen_constructor_store (struct tl_combinator *c) { printf ("int store_constructor_%s (struct paramed_type *T) {\n", c->print_id); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" return -1;\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; assert (c->var_num <= 10); gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (is_int ()) {\n"); printf (" out_int (get_int ());\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" if (is_int ()) {\n"); printf (" out_long (get_int ());\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING) { printf (" if (cur_token_len >= 0) {\n"); printf (" out_cstring (cur_token, cur_token_len);\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" if (is_double ()) {\n"); printf (" out_double (get_double());\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } int empty = is_empty (((struct tl_tree_type *)c->result)->type); for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_store (c->args[i], vars, i + 1, 0, empty) >= 0); } free (vars); printf (" return 0;\n"); printf ("}\n"); } void gen_constructor_autocomplete (struct tl_combinator *c) { printf ("int autocomplete_constructor_%s (struct paramed_type *T) {\n", c->print_id); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" return -1;\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; assert (c->var_num <= 10); gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" if (is_int ()) {\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" if (is_int ()) {\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING) { printf (" if (cur_token_len >= 0) {\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" if (is_double ()) {\n"); printf (" local_next_token ();\n"); printf (" return 0;\n"); printf (" } else {\n"); printf (" return -1;\n"); printf (" }\n"); printf ("}\n"); return; } int empty = is_empty (((struct tl_tree_type *)c->result)->type); for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_autocomplete (c->args[i], vars, i + 1, 0, empty) >= 0); } free (vars); printf (" return 0;\n"); printf ("}\n"); } void gen_constructor_fetch_ds (struct tl_combinator *c) { print_c_type_name (c->result, "", 0); printf ("fetch_ds_constructor_%s (struct paramed_type *T) {\n", c->print_id); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" assert (0);\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; gen_uni_skip (c->result, s, vars, 1, 1); printf (" "); print_c_type_name (c->result, " ", 0); printf (" result = talloc0 (sizeof (*result));\n"); struct tl_type *T = ((struct tl_tree_type *)c->result)->type; if (T->constructors_num > 1) { printf (" result->magic = 0x%08x;\n", c->name); } if (c->name == NAME_INT) { printf (" assert (in_remaining () >= 4);\n"); printf (" *result = fetch_int ();\n"); printf (" return result;\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" assert (in_remaining () >= 8);\n"); printf (" *result = fetch_long ();\n"); printf (" return result;\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING || c->name == NAME_BYTES) { printf (" assert (in_remaining () >= 4);\n"); printf (" int l = prefetch_strlen ();\n"); printf (" assert (l >= 0);\n"); printf (" result->len = l;\n"); printf (" result->data = talloc (l + 1);\n"); printf (" result->data[l] = 0;\n"); printf (" memcpy (result->data, fetch_str (l), l);\n"); printf (" return result;\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" assert (in_remaining () >= 8);\n"); printf (" *result = fetch_double ();\n"); printf (" return result;\n"); printf ("}\n"); return; } assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE); int empty = is_empty (((struct tl_tree_type *)c->result)->type); for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_fetch_ds (c->args[i], vars, i + 1, empty) >= 0); } free (vars); printf (" return result;\n"); printf ("}\n"); } void gen_constructor_free_ds (struct tl_combinator *c) { printf ("void free_ds_constructor_%s (", c->print_id); print_c_type_name (c->result, "", 0); printf ("D, struct paramed_type *T) {\n"); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" assert (0);\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; gen_uni_skip (c->result, s, vars, 1, -1); //printf (" "); //print_c_type_name (c->result, " ", 0); //printf (" result = talloc0 (sizeof (*result));\n"); //struct tl_type *T = ((struct tl_tree_type *)c->result)->type; if (c->name == NAME_INT) { printf (" tfree (D, sizeof (*D));\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" tfree (D, sizeof (*D));\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING || c->name == NAME_BYTES) { printf (" tfree (D->data, D->len + 1);\n"); printf (" tfree (D, sizeof (*D));\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" tfree (D, sizeof (*D));\n"); printf ("}\n"); return; } assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE); int empty = is_empty (((struct tl_tree_type *)c->result)->type); for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_free_ds (c->args[i], vars, i + 1, empty) >= 0); } printf (" tfree (D, sizeof (*D));\n"); free (vars); printf ("}\n"); } void gen_constructor_store_ds (struct tl_combinator *c) { printf ("void store_ds_constructor_%s (", c->print_id); print_c_type_name (c->result, "", 0); printf ("D, struct paramed_type *T) {\n"); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" assert (0);\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; gen_uni_skip (c->result, s, vars, 1, -1); //printf (" "); //print_c_type_name (c->result, " ", 0); //printf (" result = talloc0 (sizeof (*result));\n"); //struct tl_type *T = ((struct tl_tree_type *)c->result)->type; if (c->name == NAME_INT) { printf (" out_int (*D);\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" out_long (*D);\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING || c->name == NAME_BYTES) { printf (" out_cstring (D->data, D->len);\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" out_double (*D);\n"); printf ("}\n"); return; } assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE); int empty = is_empty (((struct tl_tree_type *)c->result)->type); for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_store_ds (c->args[i], vars, i + 1, empty) >= 0); } free (vars); printf ("}\n"); } void gen_constructor_print_ds (struct tl_combinator *c) { printf ("int print_ds_constructor_%s (", c->print_id); print_c_type_name (c->result, "", 0); printf ("DS, struct paramed_type *T) {\n"); int i; for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) { printf (" return -1;\n"); printf ("}\n"); return; } static char s[10000]; sprintf (s, "T"); int *vars = malloc0 (c->var_num * 4);; gen_uni_skip (c->result, s, vars, 1, 0); if (c->name == NAME_INT) { printf (" eprintf (\" %%d\", *DS);\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_LONG) { printf (" eprintf (\" %%" INT64_PRINTF_MODIFIER "d\", *DS);\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_STRING || c->name == NAME_BYTES) { printf (" print_escaped_string (DS->data, DS->len);\n"); printf (" return 0;\n"); printf ("}\n"); return; } else if (c->name == NAME_DOUBLE) { printf (" eprintf (\" %%lf\", *DS);\n"); printf (" return 0;\n"); printf ("}\n"); return; } assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE); int empty = is_empty (((struct tl_tree_type *)c->result)->type); if (!empty) { printf (" eprintf (\" %s\");\n", c->id); printf (" if (multiline_output >= 2) { eprintf (\"\\n\"); }\n"); } for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) { assert (gen_field_print_ds (c->args[i], vars, i + 1, empty) >= 0); } free (vars); printf (" return 0;\n"); printf ("}\n"); } void gen_type_skip (struct tl_type *t) { printf ("int skip_type_%s (struct paramed_type *T) {\n", t->print_id); printf (" if (in_remaining () < 4) { return -1;}\n"); printf (" int magic = fetch_int ();\n"); printf (" switch (magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" case 0x%08x: return skip_constructor_%s (T);\n", t->constructors[i]->name, t->constructors[i]->print_id); } printf (" default: return -1;\n"); printf (" }\n"); printf ("}\n"); printf ("int skip_type_bare_%s (struct paramed_type *T) {\n", t->print_id); if (t->constructors_num > 1) { printf (" int *save_in_ptr = in_ptr;\n"); for (i = 0; i < t->constructors_num; i++) { printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id); printf (" in_ptr = save_in_ptr;\n"); } } else { for (i = 0; i < t->constructors_num; i++) { printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id); } } printf (" return -1;\n"); printf ("}\n"); } void gen_type_fetch (struct tl_type *t) { int empty = is_empty (t);; printf ("int fetch_type_%s (struct paramed_type *T) {\n", t->print_id); printf (" if (in_remaining () < 4) { return -1;}\n"); if (!empty) { printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); printf (" eprintf (\" (\");\n"); } printf (" int magic = fetch_int ();\n"); printf (" int res = -1;\n"); printf (" switch (magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" case 0x%08x: res = fetch_constructor_%s (T); break;\n", t->constructors[i]->name, t->constructors[i]->print_id); } printf (" default: return -1;\n"); printf (" }\n"); if (!empty) { printf (" if (res >= 0) {\n"); printf (" if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); }\n"); printf (" eprintf (\" )\");\n"); //printf (" if (multiline_output >= 2) { printf (\"\\n\"); }\n"); printf (" }\n"); } printf (" return res;\n"); printf ("}\n"); printf ("int fetch_type_bare_%s (struct paramed_type *T) {\n", t->print_id); if (t->constructors_num > 1) { printf (" int *save_in_ptr = in_ptr;\n"); if (!empty) { printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); } for (i = 0; i < t->constructors_num; i++) { printf (" if (skip_constructor_%s (T) >= 0) { in_ptr = save_in_ptr; %sassert (!fetch_constructor_%s (T)); %sreturn 0; }\n", t->constructors[i]->print_id, empty ? "" : "eprintf (\" (\"); ", t->constructors[i]->print_id , empty ? "" : "if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); } eprintf (\" )\");"); printf (" in_ptr = save_in_ptr;\n"); } } else { for (i = 0; i < t->constructors_num; i++) { if (!empty) { printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); printf (" eprintf (\" (\");\n"); } printf (" if (fetch_constructor_%s (T) >= 0) { %sreturn 0; }\n", t->constructors[i]->print_id, empty ? "" : "if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); } eprintf (\" )\");" ); } } printf (" return -1;\n"); printf ("}\n"); } void gen_type_store (struct tl_type *t) { int empty = is_empty (t);; int k = 0; for (k = 0; k < 2; k++) { printf ("int store_type_%s%s (struct paramed_type *T) {\n", k == 0 ? "" : "bare_", t->print_id); if (empty) { if (!k) { printf (" out_int (0x%08x);\n", t->constructors[0]->name); } printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); printf (" return 0;\n"); printf ("}\n"); } else { printf (" expect_token (\"(\", 1);\n"); printf (" if (cur_token_len < 0) { return -1; }\n"); printf (" if (cur_token_len < 0) { return -1; }\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (t->constructors[i]->id), t->constructors[i]->id); if (!k) { printf (" out_int (0x%08x);\n", t->constructors[i]->name); } printf (" local_next_token ();\n"); printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[i]->print_id); printf (" expect_token (\")\", 1);\n"); printf (" return 0;\n"); printf (" }\n"); } /*if (t->constructors_num == 1) { printf (" if (!force) {\n"); if (!k) { printf (" out_int (0x%08x);\n", t->constructors[0]->name); } printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); printf (" expect_token (\")\", 1);\n"); printf (" return 0;\n"); printf (" }\n"); }*/ printf (" return -1;\n"); printf ("}\n"); } } } void gen_type_autocomplete (struct tl_type *t) { int empty = is_empty (t);; int k = 0; for (k = 0; k < 2; k++) { printf ("int autocomplete_type_%s%s (struct paramed_type *T) {\n", k == 0 ? "" : "bare_", t->print_id); if (empty) { printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); printf (" return 0;\n"); printf ("}\n"); } else { printf (" expect_token_autocomplete (\"(\", 1);\n"); printf (" if (cur_token_len == -3) { set_autocomplete_type (do_autocomplete_type_%s); return -1; }\n", t->print_id); printf (" if (cur_token_len < 0) { return -1; }\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (t->constructors[i]->id), t->constructors[i]->id); printf (" local_next_token ();\n"); printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[i]->print_id); printf (" expect_token_autocomplete (\")\", 1);\n"); printf (" return 0;\n"); printf (" }\n"); } /*if (t->constructors_num == 1) { printf (" if (!force) {\n"); printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id); printf (" expect_token_autocomplete (\")\", 1);\n"); printf (" return 0;\n"); printf (" }\n"); }*/ printf (" return -1;\n"); printf ("}\n"); } } } void gen_type_fetch_ds (struct tl_type *t) { //int empty = is_empty (t);; print_c_type_name (t->constructors[0]->result, "", 0); printf ("fetch_ds_type_%s (struct paramed_type *T) {\n", t->print_id); printf (" assert (in_remaining () >= 4);\n"); printf (" int magic = fetch_int ();\n"); printf (" switch (magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" case 0x%08x: return fetch_ds_constructor_%s (T); break;\n", t->constructors[i]->name, t->constructors[i]->print_id); } printf (" default: assert (0); return NULL;\n"); printf (" }\n"); printf ("}\n"); print_c_type_name (t->constructors[0]->result, "", 0); printf ("fetch_ds_type_bare_%s (struct paramed_type *T) {\n", t->print_id); if (t->constructors_num > 1) { printf (" int *save_in_ptr = in_ptr;\n"); for (i = 0; i < t->constructors_num; i++) { printf (" if (skip_constructor_%s (T) >= 0) { in_ptr = save_in_ptr; return fetch_ds_constructor_%s (T); }\n", t->constructors[i]->print_id, t->constructors[i]->print_id); } } else { printf (" return fetch_ds_constructor_%s (T);\n", t->constructors[0]->print_id); } printf (" assert (0);\n"); printf (" return NULL;\n"); printf ("}\n"); } void gen_type_free_ds (struct tl_type *t) { printf ("void free_ds_type_%s (", t->print_id); print_c_type_name (t->constructors[0]->result, "", 0); printf ("D, struct paramed_type *T) {\n"); if (t->constructors_num > 1) { printf (" switch (D->magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" case 0x%08x: free_ds_constructor_%s (D, T); return; \n", t->constructors[i]->name, t->constructors[i]->print_id); } printf (" default: assert (0);\n"); printf (" }\n"); } else { printf (" free_ds_constructor_%s (D, T); return; \n", t->constructors[0]->print_id); } printf ("}\n"); } void gen_type_store_ds (struct tl_type *t) { int k; for (k = 0; k < 2; k++) { if (k == 0) { printf ("void store_ds_type_%s (", t->print_id); } else { printf ("void store_ds_type_bare_%s (", t->print_id); } print_c_type_name (t->constructors[0]->result, "", 0); printf ("D, struct paramed_type *T) {\n"); if (t->constructors_num > 1) { if (k == 0) { printf (" out_int (D->magic);\n"); } printf (" switch (D->magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" case 0x%08x: store_ds_constructor_%s (D, T); return; \n", t->constructors[i]->name, t->constructors[i]->print_id); } printf (" default: assert (0);\n"); printf (" }\n"); } else { if (k == 0) { printf (" out_int (0x%08x);\n", t->constructors[0]->name); } printf (" store_ds_constructor_%s (D, T); return; \n", t->constructors[0]->print_id); } printf ("}\n"); } } void gen_type_print_ds (struct tl_type *t) { int empty = is_empty (t);; int k; for (k = 0; k < 2; k++) { printf ("int print_ds_type_%s%s (", k ? "bare_" : "", t->print_id); print_c_type_name (t->constructors[0]->result, "", 0); printf ("DS, struct paramed_type *T) {\n"); printf (" int res;\n"); if (!empty) { printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n"); printf (" eprintf (\" (\");\n"); } if (t->constructors_num > 1) { printf (" switch (DS->magic) {\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" case 0x%08x: res = print_ds_constructor_%s (DS, T); break;\n", t->constructors[i]->name, t->constructors[i]->print_id); } printf (" default: return -1;\n"); printf (" }\n"); } else { printf (" res = print_ds_constructor_%s (DS, T);\n", t->constructors[0]->print_id); } if (!empty) { printf (" if (res >= 0) {\n"); printf (" if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); }\n"); printf (" eprintf (\" )\");\n"); //printf (" if (multiline_output >= 2) { printf (\"\\n\"); }\n"); printf (" }\n"); } printf (" return res;\n"); printf ("}\n"); } } void gen_function_store (struct tl_combinator *f) { printf ("struct paramed_type *store_function_%s (void) {\n", f->print_id); int i; int *vars = malloc0 (f->var_num * 4);; assert (f->var_num <= 10); for (i = 0; i < f->args_num; i++) if (!(f->args[i]->flags & FLAG_OPT_VAR)) { if (f->args[i]->flags & FLAG_EXCL) { assert (gen_field_store_excl (f->args[i], vars, i + 1, 1) >= 0); } else { assert (gen_field_store (f->args[i], vars, i + 1, 1, 0) >= 0); } } printf (" struct paramed_type *R = \n"); assert (gen_create (f->result, vars, 2) >= 0); printf (";\n"); free (vars); printf (" return paramed_type_dup (R);\n"); printf ("}\n"); } void gen_function_autocomplete (struct tl_combinator *f) { printf ("struct paramed_type *autocomplete_function_%s (void) {\n", f->print_id); int i; int *vars = malloc0 (f->var_num * 4);; assert (f->var_num <= 10); for (i = 0; i < f->args_num; i++) if (!(f->args[i]->flags & FLAG_OPT_VAR)) { if (f->args[i]->flags & FLAG_EXCL) { assert (gen_field_autocomplete_excl (f->args[i], vars, i + 1, 1) >= 0); } else { assert (gen_field_autocomplete (f->args[i], vars, i + 1, 1, 0) >= 0); } } printf (" struct paramed_type *R = \n"); assert (gen_create (f->result, vars, 2) >= 0); printf (";\n"); free (vars); printf (" return paramed_type_dup (R);\n"); printf ("}\n"); } void gen_type_do_autocomplete (struct tl_type *t) { printf ("int do_autocomplete_type_%s (const char *text, int text_len, int index, char **R) {\n", t->print_id); printf (" index ++;\n"); int i; for (i = 0; i < t->constructors_num; i++) { printf (" if (index == %d) { if (!strncmp (text, \"%s\", text_len)) { *R = tstrdup (\"%s\"); return index; } else { index ++; }}\n", i, t->constructors[i]->id, t->constructors[i]->id); } printf (" *R = 0;\n"); printf (" return 0;\n"); printf ("}\n"); } struct tl_tree *read_num_var (int *var_num) { struct tl_tree_var_num *T = malloc0 (sizeof (*T)); T->self.flags = 0; T->self.methods = &tl_pvar_num_methods;; T->dif = get_int (); T->var_num = get_int (); if (T->var_num >= *var_num) { *var_num = T->var_num + 1; } assert (!(T->self.flags & FLAG_NOVAR)); return (void *)T; } struct tl_tree *read_type_var (int *var_num) { struct tl_tree_var_type *T = malloc0 (sizeof (*T)); T->self.methods = &tl_pvar_type_methods; T->var_num = get_int (); T->self.flags = get_int (); if (T->var_num >= *var_num) { *var_num = T->var_num + 1; } assert (!(T->self.flags & (FLAG_NOVAR | FLAG_BARE))); return (void *)T; } struct tl_tree *read_array (int *var_num) { struct tl_tree_array *T = malloc0 (sizeof (*T)); T->self.methods = &tl_parray_methods; T->self.flags = 0; T->multiplicity = read_nat_expr (var_num); assert (T->multiplicity); T->args_num = get_int (); assert (T->args_num >= 0 && T->args_num <= 1000); T->args = malloc0 (sizeof (void *) * T->args_num); assert (read_args_list (T->args, T->args_num, var_num) >= 0); T->self.flags |= FLAG_NOVAR; int i; for (i = 0; i < T->args_num; i++) { if (!(T->args[i]->flags & FLAG_NOVAR)) { T->self.flags &= ~FLAG_NOVAR; } } return (void *)T; } struct tl_tree *read_type (int *var_num) { struct tl_tree_type *T = malloc0 (sizeof (*T)); T->self.methods = &tl_ptype_methods; T->type = tl_type_get_by_name (get_int ()); assert (T->type); T->self.flags = get_int (); T->children_num = get_int (); assert (T->type->arity == T->children_num); T->children = malloc0 (sizeof (void *) * T->children_num); int i; T->self.flags |= FLAG_NOVAR; for (i = 0; i < T->children_num; i++) { int t = get_int (); if (t == (int)TLS_EXPR_NAT) { assert ((T->type->params_types & (1 << i))); T->children[i] = read_nat_expr (var_num); } else if (t == (int)TLS_EXPR_TYPE) { assert (!(T->type->params_types & (1 << i))); T->children[i] = read_type_expr (var_num); } else { assert (0); } if (!TL_IS_NAT_VAR (T->children[i]) && !(T->children[i]->flags & FLAG_NOVAR)) { T->self.flags &= ~FLAG_NOVAR; } } return (void *)T; } struct tl_tree *read_tree (int *var_num) { int x = get_int (); if (verbosity >= 2) { fprintf (stderr, "read_tree: constructor = 0x%08x\n", x); } switch (x) { case TLS_TREE_NAT_CONST: return read_num_const (var_num); case TLS_TREE_NAT_VAR: return read_num_var (var_num); case TLS_TREE_TYPE_VAR: return read_type_var (var_num); case TLS_TREE_TYPE: return read_type (var_num); case TLS_TREE_ARRAY: return read_array (var_num); default: if (verbosity) { fprintf (stderr, "x = %d\n", x); } assert (0); return 0; } } struct tl_tree *read_type_expr (int *var_num) { int x = get_int (); if (verbosity >= 2) { fprintf (stderr, "read_type_expr: constructor = 0x%08x\n", x); } switch (x) { case TLS_TYPE_VAR: return read_type_var (var_num); case TLS_TYPE_EXPR: return read_type (var_num); case TLS_ARRAY: return read_array (var_num); default: if (verbosity) { fprintf (stderr, "x = %d\n", x); } assert (0); return 0; } } struct tl_tree *read_nat_expr (int *var_num) { int x = get_int (); if (verbosity >= 2) { fprintf (stderr, "read_nat_expr: constructor = 0x%08x\n", x); } switch (x) { case TLS_NAT_CONST: return read_num_const (var_num); case TLS_NAT_VAR: return read_num_var (var_num); default: if (verbosity) { fprintf (stderr, "x = %d\n", x); } assert (0); return 0; } } struct tl_tree *read_expr (int *var_num) { int x = get_int (); if (verbosity >= 2) { fprintf (stderr, "read_nat_expr: constructor = 0x%08x\n", x); } switch (x) { case TLS_EXPR_NAT: return read_nat_expr (var_num); case TLS_EXPR_TYPE: return read_type_expr (var_num); default: if (verbosity) { fprintf (stderr, "x = %d\n", x); } assert (0); return 0; } } int read_args_list (struct arg **args, int args_num, int *var_num) { int i; for (i = 0; i < args_num; i++) { args[i] = malloc0 (sizeof (struct arg)); args[i]->exist_var_num = -1; args[i]->exist_var_bit = 0; assert (get_int () == TLS_ARG_V2); args[i]->id = get_string (); args[i]->flags = get_int (); if (args[i]->flags & 2) { args[i]->flags &= ~2; args[i]->flags |= (1 << 20); } if (args[i]->flags & 4) { args[i]->flags &= ~4; args[i]->var_num = get_int (); } else { args[i]->var_num = -1; } int x = args[i]->flags & 6; args[i]->flags &= ~6; if (x & 2) { args[i]->flags |= 4; } if (x & 4) { args[i]->flags |= 2; } if (args[i]->var_num >= *var_num) { *var_num = args[i]->var_num + 1; } if (args[i]->flags & FLAG_OPT_FIELD) { args[i]->exist_var_num = get_int (); args[i]->exist_var_bit = get_int (); } args[i]->type = read_type_expr (var_num); assert (args[i]->type); if (args[i]->var_num < 0 && args[i]->exist_var_num < 0 && (TL_IS_NAT_VAR(args[i]->type) || (args[i]->type->flags & FLAG_NOVAR))) { args[i]->flags |= FLAG_NOVAR; } } return 1; } int read_combinator_args_list (struct tl_combinator *c) { c->args_num = get_int (); if (verbosity >= 2) { fprintf (stderr, "c->id = %s, c->args_num = %d\n", c->id, c->args_num); } assert (c->args_num >= 0 && c->args_num <= 1000); c->args = malloc0 (sizeof (void *) * c->args_num); c->var_num = 0; return read_args_list (c->args, c->args_num, &c->var_num); } int read_combinator_right (struct tl_combinator *c) { assert (get_int () == TLS_COMBINATOR_RIGHT_V2); c->result = read_type_expr (&c->var_num); assert (c->result); return 1; } int read_combinator_left (struct tl_combinator *c) { int x = get_int (); if (x == (int)TLS_COMBINATOR_LEFT_BUILTIN) { c->args_num = 0; c->var_num = 0; c->args = 0; return 1; } else if (x == TLS_COMBINATOR_LEFT) { return read_combinator_args_list (c); } else { assert (0); return -1; } } char *gen_print_id (const char *id) { static char s[1000]; char *ptr = s; int first = 1; while (*id) { if (*id == '.') { *(ptr ++) = '_'; } else if (*id >= 'A' && *id <= 'Z') { if (!first && *(ptr - 1) != '_') { *(ptr ++) = '_'; } *(ptr ++) = *id - 'A' + 'a'; } else { *(ptr ++) = *id; } id ++; first = 0; } *ptr = 0; return s; } struct tl_combinator *read_combinators (int v) { struct tl_combinator *c = malloc0 (sizeof (*c)); c->name = get_int (); c->id = get_string (); c->print_id = strdup (gen_print_id (c->id)); assert (c->print_id); //char *s = c->id; //while (*s) { if (*s == '.') { *s = '_'; } ; s ++;} int x = get_int (); struct tl_type *t = tl_type_get_by_name (x); assert (t || (!x && v == 3)); if (v == 2) { assert (t->extra < t->constructors_num); t->constructors[t->extra ++] = c; c->is_fun = 0; } else { assert (v == 3); tl_function_insert_by_name (c); c->is_fun = 1; } assert (read_combinator_left (c) >= 0); assert (read_combinator_right (c) >= 0); return c; } struct tl_type *read_types (void) { struct tl_type *t = malloc0 (sizeof (*t)); t->name = get_int (); t->id = get_string (); t->print_id = strdup (gen_print_id (t->id)); assert (t->print_id); t->constructors_num = get_int (); assert (t->constructors_num >= 0 && t->constructors_num <= 1000); t->constructors = malloc0 (sizeof (void *) * t->constructors_num); t->flags = get_int (); t->arity = get_int (); t->params_types = get_long (); // params_types t->extra = 0; tl_type_insert_by_name (t); return t; } char *gen_what[1000]; int gen_what_cnt; void gen_skip_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("int skip_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("int skip_type_%s (struct paramed_type *T);\n", tps[i]->print_id); printf ("int skip_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); } printf ("int skip_type_any (struct paramed_type *T);\n"); } void gen_skip_source (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"auto/auto-skip.h\"\n"); printf ("#include \"auto-static-skip.c\"\n"); printf ("#include \"mtproto-common.h\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_skip (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_skip (tps[i]); } printf ("int skip_type_any (struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return skip_type_%s (T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return skip_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return -1; }\n"); printf ("}\n"); } void gen_fetch_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \n"); printf ("struct tgl_state;\n"); printf ("char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("int fetch_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("int fetch_type_%s (struct paramed_type *T);\n", tps[i]->print_id); printf ("int fetch_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); } printf ("int fetch_type_any (struct paramed_type *T);\n"); } void gen_fetch_source (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"auto/auto-fetch.h\"\n"); printf ("#include \"auto/auto-skip.h\"\n"); printf ("#include \"auto-static-fetch.c\"\n"); printf ("#include \"mtproto-common.h\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_fetch (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_fetch (tps[i]); } printf ("int fetch_type_any (struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return fetch_type_%s (T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return fetch_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return -1; }\n"); printf ("}\n"); } void gen_store_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("struct paramed_type *tglf_extf_store (struct tgl_state *TLS, const char *data, int data_len);\n"); printf ("int tglf_store_type (struct tgl_state *TLS, const char *work, int work_len, struct paramed_type *P);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("int store_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("int store_type_%s (struct paramed_type *T);\n", tps[i]->print_id); printf ("int store_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); } for (i = 0; i < fn; i++) { printf ("struct paramed_type *store_function_%s (void);\n", fns[i]->print_id); } printf ("int store_type_any (struct paramed_type *T);\n"); printf ("struct paramed_type *store_function_any (void);\n"); } void gen_store_source (void ) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"mtproto-common.h\"\n"); printf ("#include \"auto/auto-store.h\"\n"); printf ("#include \"auto-static-store.c\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_store (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_store (tps[i]); } for (i = 0; i < fn; i++) { gen_function_store (fns[i]); } printf ("int store_type_any (struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return store_type_%s (T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return store_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return -1; }\n"); printf ("}\n"); printf ("struct paramed_type *store_function_any (void) {\n"); printf (" if (cur_token_len != 1 || *cur_token != '(') { return 0; }\n"); printf (" local_next_token ();\n"); printf (" if (cur_token_len == 1 || *cur_token == '.') { \n"); printf (" local_next_token ();\n"); printf (" if (cur_token_len != 1 || *cur_token != '=') { return 0; }\n"); printf (" local_next_token ();\n"); printf (" };\n"); printf (" if (cur_token_len < 0) { return 0; }\n"); for (i = 0; i < fn; i++) { printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (fns[i]->id), fns[i]->id); printf (" out_int (0x%08x);\n", fns[i]->name); printf (" local_next_token ();\n"); printf (" struct paramed_type *P = store_function_%s ();\n", fns[i]->print_id); printf (" if (!P) { return 0; }\n"); printf (" if (cur_token_len != 1 || *cur_token != ')') { return 0; }\n"); printf (" local_next_token ();\n"); printf (" return P;\n"); printf (" }\n"); } printf (" return 0;\n"); printf ("}\n"); } void gen_autocomplete_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("int tglf_extf_autocomplete (struct tgl_state *TLS, const char *text, int text_len, int index, char **R, char *data, int data_len);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("int autocomplete_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("int autocomplete_type_%s (struct paramed_type *T);\n", tps[i]->print_id); printf ("int do_autocomplete_type_%s (const char *text, int len, int index, char **R);\n", tps[i]->print_id); printf ("int autocomplete_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); } printf ("int autocomplete_type_any (struct paramed_type *T);\n"); printf ("struct paramed_type *autocomplete_function_any (void);\n"); } void gen_autocomplete_source (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"mtproto-common.h\"\n"); printf ("#include \"auto/auto-autocomplete.h\"\n"); printf ("#include \"auto-static-autocomplete.c\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_autocomplete (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_autocomplete (tps[i]); gen_type_do_autocomplete (tps[i]); } for (i = 0; i < fn; i++) { gen_function_autocomplete (fns[i]); } printf ("int autocomplete_type_any (struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return autocomplete_type_%s (T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return autocomplete_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return -1; }\n"); printf ("}\n"); printf ("int do_autocomplete_function (const char *text, int text_len, int index, char **R) {\n"); printf (" index ++;\n"); for (i = 0; i < fn; i++) { printf (" if (index == %d) { if (!strncmp (text, \"%s\", text_len)) { *R = tstrdup (\"%s\"); return index; } else { index ++; }}\n", i, fns[i]->id, fns[i]->id); } printf (" *R = 0;\n"); printf (" return 0;\n"); printf ("}\n"); printf ("struct paramed_type *autocomplete_function_any (void) {\n"); printf (" expect_token_ptr_autocomplete (\"(\", 1);\n"); printf (" if (cur_token_len == -3) { set_autocomplete_type (do_autocomplete_function); }\n"); printf (" if (cur_token_len < 0) { return 0; }\n"); for (i = 0; i < fn; i++) { printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (fns[i]->id), fns[i]->id); printf (" local_next_token ();\n"); printf (" struct paramed_type *P = autocomplete_function_%s ();\n", fns[i]->print_id); printf (" if (!P) { return 0; }\n"); printf (" expect_token_ptr_autocomplete (\")\", 1);\n"); printf (" return P;\n"); printf (" }\n"); } printf (" return 0;\n"); printf ("}\n"); } void gen_types_header (void) { printf ("#ifndef __AUTO_TYPES_H__\n"); printf ("#define __AUTO_TYPES_H__\n"); printf ("#include \"auto.h\"\n"); int i; for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("extern struct tl_type_descr tl_type_%s;\n", tps[i]->print_id); printf ("extern struct tl_type_descr tl_type_bare_%s;\n", tps[i]->print_id); } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("struct tl_ds_%s {\n", tps[i]->print_id); if (!strcmp (tps[i]->id, "String") || !strcmp (tps[i]->id, "Bytes")) { printf (" int len;\n"); printf (" char *data;\n"); printf ("};\n"); continue; } int j; if (tps[i]->constructors_num > 1) { printf (" unsigned magic;\n"); } for (j = 0; j < tps[i]->constructors_num; j++) { struct tl_combinator *c = tps[i]->constructors[j]; int k; for (k = 0; k < c->args_num; k++) { if ((c->args[k]->flags & FLAG_OPT_VAR)) { continue; } if (c->args[k]->id && strlen (c->args[k]->id) && j > 0) { int l; int ok = 1; for (l = 0; l < j && ok; l++) { int m; struct tl_combinator *d = tps[i]->constructors[l]; for (m = 0; m < d->args_num && ok; m++) { if (d->args[m]->id && !strcmp (d->args[m]->id, c->args[k]->id)) { ok = 0; } } } if (!ok) { continue; } } printf (" "); print_c_type_name (c->args[k]->type, " ", 1); if (!c->args[k]->id || !strlen (c->args[k]->id)) { assert (!j); printf ("f%d;\n", k); } else { printf ("%s;\n", c->args[k]->id); } } } printf ("};\n"); } printf ("#endif\n"); } void gen_types_source (void) { printf ("#include \"auto.h\"\n"); int i; for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("struct tl_type_descr tl_type_%s = {\n", tps[i]->print_id); printf (" .name = 0x%08x,\n", tps[i]->name); printf (" .id = \"%s\"\n,", tps[i]->id); printf (" .params_num = %d,\n", tps[i]->arity); printf (" .params_types = %" INT64_PRINTF_MODIFIER "d\n", tps[i]->params_types); printf ("};\n"); printf ("struct tl_type_descr tl_type_bare_%s = {\n", tps[i]->print_id); printf (" .name = 0x%08x,\n", ~tps[i]->name); printf (" .id = \"Bare_%s\",\n", tps[i]->id); printf (" .params_num = %d,\n", tps[i]->arity); printf (" .params_types = %" INT64_PRINTF_MODIFIER "d\n", tps[i]->params_types); printf ("};\n"); } } void gen_fetch_ds_source (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"auto/auto-fetch-ds.h\"\n"); printf ("#include \"auto/auto-skip.h\"\n"); printf ("#include \"auto/auto-types.h\"\n"); printf ("#include \"mtproto-common.h\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_fetch_ds (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_fetch_ds (tps[i]); } printf ("void *fetch_ds_type_any (struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return fetch_ds_type_%s (T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return fetch_ds_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return NULL; }\n"); printf ("}\n"); } void gen_fetch_ds_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \n"); printf ("struct tgl_state;\n"); //printf ("char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { print_c_type_name (tps[i]->constructors[j]->result, "", 0); printf ("fetch_ds_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("fetch_ds_type_%s (struct paramed_type *T);\n", tps[i]->print_id); print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("fetch_ds_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id); } printf ("void *fetch_ds_type_any (struct paramed_type *T);\n"); } void gen_free_ds_source (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"auto/auto-free-ds.h\"\n"); printf ("#include \"auto/auto-skip.h\"\n"); printf ("#include \"auto/auto-types.h\"\n"); printf ("#include \"mtproto-common.h\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_free_ds (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_free_ds (tps[i]); } printf ("void free_ds_type_any (void *D, struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: free_ds_type_%s (D, T); return;\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: free_ds_type_%s (D, T); return;\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return; }\n"); printf ("}\n"); } void gen_free_ds_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \"auto/auto-types.h\"\n"); printf ("#include \n"); printf ("#include \n"); printf ("struct tgl_state;\n"); //printf ("char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("void free_ds_constructor_%s (", tps[i]->constructors[j]->print_id); print_c_type_name (tps[i]->constructors[j]->result, "", 0); printf ("D, struct paramed_type *T);\n"); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("void free_ds_type_%s (", tps[i]->print_id); print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("D, struct paramed_type *T);\n"); } printf ("void free_ds_type_any (void *D, struct paramed_type *T);\n"); } void gen_store_ds_source (void) { printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("#include \"auto/auto-store-ds.h\"\n"); printf ("#include \"auto/auto-skip.h\"\n"); printf ("#include \"auto/auto-types.h\"\n"); printf ("#include \"mtproto-common.h\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_store_ds (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_store_ds (tps[i]); } printf ("void store_ds_type_any (void *D, struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: store_ds_type_%s (D, T); return;\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: store_ds_type_bare_%s (D, T); return;\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return; }\n"); printf ("}\n"); } void gen_store_ds_header (void) { printf ("#include \"auto.h\"\n"); printf ("#include \"auto/auto-types.h\"\n"); printf ("#include \n"); printf ("#include \n"); printf ("struct tgl_state;\n"); //printf ("char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("void store_ds_constructor_%s (", tps[i]->constructors[j]->print_id); print_c_type_name (tps[i]->constructors[j]->result, "", 0); printf ("D, struct paramed_type *T);\n"); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("void store_ds_type_%s (", tps[i]->print_id); print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("D, struct paramed_type *T);\n"); printf ("void store_ds_type_bare_%s (", tps[i]->print_id); print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("D, struct paramed_type *T);\n"); } printf ("void store_ds_type_any (void *D, struct paramed_type *T);\n"); } void gen_print_ds_header (void) { printf ("#include \"config.h\"\n"); printf ("#ifndef DISABLE_EXTF\n"); printf ("\n"); printf ("#include \"auto.h\"\n"); printf ("#include \"auto-types.h\"\n"); printf ("#include \n"); printf ("#include \n"); printf ("struct tgl_state;\n"); printf ("char *tglf_extf_print_ds (struct tgl_state *TLS, void *DS, struct paramed_type *T);\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { printf ("int print_ds_constructor_%s (", tps[i]->constructors[j]->print_id); print_c_type_name (tps[i]->constructors[j]->result, "", 0); printf ("DS, struct paramed_type *T);\n"); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { printf ("int print_ds_type_%s (", tps[i]->print_id); print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("DS, struct paramed_type *T);\n"); printf ("int print_ds_type_bare_%s (", tps[i]->print_id); print_c_type_name (tps[i]->constructors[0]->result, "", 0); printf ("DS, struct paramed_type *T);\n"); } printf ("int print_ds_type_any (void *DS, struct paramed_type *T);\n"); printf ("#endif\n"); } void gen_print_ds_source (void) { printf ("#include \"config.h\"\n"); printf ("#ifndef DISABLE_EXTF\n"); printf ("\n"); printf ("#include \"auto.h\"\n"); printf ("#include \n"); printf ("\n"); printf ("#include \"auto/auto-print-ds.h\"\n"); printf ("#include \"auto/auto-skip.h\"\n"); printf ("#include \"auto-static-print-ds.c\"\n"); printf ("#include \"mtproto-common.h\"\n"); int i, j; for (i = 0; i < tn; i++) { for (j = 0; j < tps[i]->constructors_num; j ++) { gen_constructor_print_ds (tps[i]->constructors[j]); } } for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { gen_type_print_ds (tps[i]); } printf ("int print_ds_type_any (void *DS, struct paramed_type *T) {\n"); printf (" switch (T->type->name) {\n"); for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) { printf (" case 0x%08x: return print_ds_type_%s (DS, T);\n", tps[i]->name, tps[i]->print_id); printf (" case 0x%08x: return print_ds_type_bare_%s (DS, T);\n", ~tps[i]->name, tps[i]->print_id); } printf (" default: return -1; }\n"); printf ("}\n"); printf ("#endif\n"); } int parse_tlo_file (void) { buf_end = buf_ptr + (buf_size / 4); assert (get_int () == TLS_SCHEMA_V2); get_int (); // version get_int (); // date tn = 0; fn = 0; cn = 0; int i; tn = get_int (); assert (tn >= 0 && tn < 10000); tps = malloc0 (sizeof (void *) * tn); if (verbosity >= 2) { fprintf (stderr, "Found %d types\n", tn); } for (i = 0; i < tn; i++) { assert (get_int () == TLS_TYPE); tps[i] = read_types (); assert (tps[i]); } cn = get_int (); assert (cn >= 0); if (verbosity >= 2) { fprintf (stderr, "Found %d constructors\n", cn); } for (i = 0; i < cn; i++) { assert (get_int () == TLS_COMBINATOR); assert (read_combinators (2)); } fn = get_int (); assert (fn >= 0 && fn < 10000); fns = malloc0 (sizeof (void *) * fn); if (verbosity >= 2) { fprintf (stderr, "Found %d functions\n", fn); } for (i = 0; i < fn; i++) { assert (get_int () == TLS_COMBINATOR); fns[i] = read_combinators (3); assert (fns[i]); } assert (buf_ptr == buf_end); int j; for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) { tps[i]->name = 0; for (j = 0; j < tps[i]->constructors_num; j ++) { tps[i]->name ^= tps[i]->constructors[j]->name; } } for (i = 0; i < gen_what_cnt; i++) { if (!strcmp (gen_what[i], "fetch")) { gen_fetch_source (); } else if (!strcmp (gen_what[i], "fetch-header")) { gen_fetch_header (); } else if (!strcmp (gen_what[i], "skip")) { gen_skip_source (); } else if (!strcmp (gen_what[i], "skip-header")) { gen_skip_header (); } else if (!strcmp (gen_what[i], "store")) { gen_store_source (); } else if (!strcmp (gen_what[i], "store-header")) { gen_store_header (); } else if (!strcmp (gen_what[i], "autocomplete")) { gen_autocomplete_source (); } else if (!strcmp (gen_what[i], "autocomplete-header")) { gen_autocomplete_header (); } else if (!strcmp (gen_what[i], "types")) { gen_types_source (); } else if (!strcmp (gen_what[i], "types-header")) { gen_types_header (); } else if (!strcmp (gen_what[i], "fetch-ds")) { gen_fetch_ds_source (); } else if (!strcmp (gen_what[i], "fetch-ds-header")) { gen_fetch_ds_header (); } else if (!strcmp (gen_what[i], "free-ds")) { gen_free_ds_source (); } else if (!strcmp (gen_what[i], "free-ds-header")) { gen_free_ds_header (); } else if (!strcmp (gen_what[i], "store-ds")) { gen_store_ds_source (); } else if (!strcmp (gen_what[i], "store-ds-header")) { gen_store_ds_header (); } else if (!strcmp (gen_what[i], "print-ds")) { gen_print_ds_source (); } else if (!strcmp (gen_what[i], "print-ds-header")) { gen_print_ds_header (); } else { assert (0); } } return 0; } void usage (void) { printf ("usage: generate [-v] [-h] \n" ); exit (2); } void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); void logprintf (const char *format __attribute__ ((unused)), ...) { } /* void hexdump (int *in_ptr, int *in_end) { int *ptr = in_ptr; while (ptr < in_end) { printf (" %08x", *(ptr ++)); } printf ("\n"); }*/ #ifdef HAVE_EXECINFO_H void print_backtrace (void) { void *buffer[255]; const int calls = backtrace (buffer, sizeof (buffer) / sizeof (void *)); backtrace_symbols_fd (buffer, calls, 1); } #else void print_backtrace (void) { if (write (1, "No libexec. Backtrace disabled\n", 32) < 0) { // Sad thing } } #endif void sig_segv_handler (int signum __attribute__ ((unused))) { if (write (1, "SIGSEGV received\n", 18) < 0) { // Sad thing } print_backtrace (); exit (EXIT_FAILURE); } void sig_abrt_handler (int signum __attribute__ ((unused))) { if (write (1, "SIGABRT received\n", 18) < 0) { // Sad thing } print_backtrace (); exit (EXIT_FAILURE); } static int read_all (int fd, void *buf, size_t len) { unsigned int rs = 0; while(rs < len) { int rval = read (fd, buf + rs, len - rs); if (rval == 0) { break; } if (rval < 0) { return rval; } rs += rval; } return rs; } #ifndef O_BINARY #define O_BINARY 0 #endif int main (int argc, char **argv) { signal (SIGSEGV, sig_segv_handler); signal (SIGABRT, sig_abrt_handler); int i; while ((i = getopt (argc, argv, "vhHg:")) != -1) { switch (i) { case 'h': usage (); return 2; case 'v': verbosity++; break; case 'H': header ++; break; case 'g': assert (gen_what_cnt < 1000); gen_what[gen_what_cnt ++] = optarg; break; } } if (argc != optind + 1) { usage (); } int fd = open (argv[optind], O_RDONLY | O_BINARY); if (fd < 0) { fprintf (stderr, "Can not open file '%s'. Error %s\n", argv[optind], strerror(errno)); exit (1); } buf_size = read_all (fd, buf, (1 << 20)); if (fd == (1 << 20)) { fprintf (stderr, "Too big tlo file\n"); exit (2); } return parse_tlo_file (); } ================================================ FILE: generate.h ================================================ /* This file is part of tgl-libary/generate Tgl-library/generate 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. Tgl-library/generate 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 tgl-library/generate. If not, see . Copyright Vitaly Valtman 2014-2015 It is derivative work of VK/KittenPHP-DB-Engine (https://github.com/vk-com/kphp-kdb/) Copyright 2012-2013 Vkontakte Ltd 2012-2013 Vitaliy Valtman */ #ifndef __GENERATE_H__ #define __GENERATE_H__ struct tl_combinator; struct tl_type { // struct tl_type_methods *methods; char *id; char *print_id; unsigned name; int arity; int flags; int constructors_num; struct tl_combinator **constructors; long long params_types; int extra; }; #define NODE_TYPE_TYPE 1 #define NODE_TYPE_NAT_CONST 2 #define NODE_TYPE_VAR_TYPE 3 #define NODE_TYPE_VAR_NUM 4 #define NODE_TYPE_ARRAY 5 #define MAX_COMBINATOR_VARS 64 #define NAME_VAR_NUM 0x70659eff #define NAME_VAR_TYPE 0x2cecf817 #define NAME_INT 0xa8509bda #define NAME_LONG 0x22076cba #define NAME_DOUBLE 0x2210c154 #define NAME_STRING 0xb5286e24 #define NAME_VECTOR 0x1cb5c415 #define NAME_MAYBE_TRUE 0x3f9c8ef8 #define NAME_MAYBE_FALSE 0x27930a7b #define NAME_BOOL_FALSE 0xbc799737 #define NAME_BOOL_TRUE 0x997275b5 #define NAME_BYTES 0x0ee1379f #define FLAG_OPT_VAR (1 << 17) #define FLAG_EXCL (1 << 18) #define FLAG_OPT_FIELD (1 << 20) #define FLAG_NOVAR (1 << 21) #define FLAG_BARE 1 #define FLAGS_MASK ((1 << 16) - 1) #define FLAG_DEFAULT_CONSTRUCTOR (1 << 25) #define FLAG_NOCONS (1 << 1) extern struct tl_tree_methods tl_nat_const_methods; extern struct tl_tree_methods tl_nat_const_full_methods; extern struct tl_tree_methods tl_pnat_const_full_methods; extern struct tl_tree_methods tl_array_methods; extern struct tl_tree_methods tl_type_methods; extern struct tl_tree_methods tl_parray_methods; extern struct tl_tree_methods tl_ptype_methods; extern struct tl_tree_methods tl_var_num_methods; extern struct tl_tree_methods tl_var_type_methods; extern struct tl_tree_methods tl_pvar_num_methods; extern struct tl_tree_methods tl_pvar_type_methods; #define TL_IS_NAT_VAR(x) (((long)x) & 1) #define TL_TREE_METHODS(x) (TL_IS_NAT_VAR (x) ? &tl_nat_const_methods : ((struct tl_tree *)(x))->methods) #define DEC_REF(x) (TL_TREE_METHODS(x)->dec_ref ((void *)x)) #define INC_REF(x) (TL_TREE_METHODS(x)->inc_ref ((void *)x)) #define TYPE(x) (TL_TREE_METHODS(x)->type ((void *)x)) typedef unsigned long long tl_tree_hash_t; struct tl_tree; struct tl_tree_methods { int (*type)(struct tl_tree *T); int (*eq)(struct tl_tree *T, struct tl_tree *U); void (*inc_ref)(struct tl_tree *T); void (*dec_ref)(struct tl_tree *T); }; struct tl_tree { int ref_cnt; int flags; //tl_tree_hash_t hash; struct tl_tree_methods *methods; }; /* struct tl_tree_nat_const { struct tl_tree self; int value; };*/ struct tl_tree_type { struct tl_tree self; struct tl_type *type; int children_num; struct tl_tree **children; }; struct tl_tree_array { struct tl_tree self; struct tl_tree *multiplicity; int args_num; struct arg **args; }; struct tl_tree_var_type { struct tl_tree self; int var_num; }; struct tl_tree_var_num { struct tl_tree self; int var_num; int dif; }; struct tl_tree_nat_const { struct tl_tree self; long long value; }; struct arg { char *id; int var_num; int flags; int exist_var_num; int exist_var_bit; struct tl_tree *type; }; struct tl_combinator { //struct tl_combinator_methods *methods; char *id; char *print_id; unsigned name; int is_fun; int var_num; int args_num; struct arg **args; struct tl_tree *result; void **IP; void **fIP; int IP_len; int fIP_len; }; #endif ================================================ FILE: m4_ax_check_openssl.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) # # DESCRIPTION # # Look for OpenSSL in a number of default spots, or in a user-selected # spot (via --with-openssl). Sets # # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately # # This macro sets OPENSSL_INCLUDES such that source files should use the # openssl/ directory in include directives: # # #include # # LICENSE # # Copyright (c) 2009,2010 Zmanda Inc. # Copyright (c) 2009,2010 Dustin J. Mitchell # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) AC_DEFUN([AX_CHECK_OPENSSL], [ found=false AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl=DIR], [root of the OpenSSL directory])], [ case "$withval" in "" | y | ye | yes | n | no) AC_MSG_ERROR([Invalid --with-openssl value]) ;; *) ssldirs="$withval" ;; esac ], [ # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs AC_PATH_PROG([PKG_CONFIG], [pkg-config]) if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi ] ) # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true AC_MSG_RESULT([yes]) break else AC_MSG_RESULT([no]) fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], [ AC_MSG_RESULT([yes]) $1 ], [ AC_MSG_RESULT([no]) $2 ]) CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" AC_SUBST([OPENSSL_INCLUDES]) AC_SUBST([OPENSSL_LIBS]) AC_SUBST([OPENSSL_LDFLAGS]) ]) ================================================ FILE: m4_ax_check_zlib.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_ZLIB([action-if-found], [action-if-not-found]) # # DESCRIPTION # # This macro searches for an installed zlib library. If nothing was # specified when calling configure, it searches first in /usr/local and # then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified, # it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If # --without-zlib is specified, the library is not searched at all. # # If either the header file (zlib.h) or the library (libz) is not found, # shell commands 'action-if-not-found' is run. If 'action-if-not-found' is # not specified, the configuration exits on error, asking for a valid zlib # installation directory or --without-zlib. # # If both header file and library are found, shell commands # 'action-if-found' is run. If 'action-if-found' is not specified, the # default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends # '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls # AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition # for this symbol in a config.h file. Sample usage in a C/C++ source is as # follows: # # #ifdef HAVE_LIBZ # #include # #endif /* HAVE_LIBZ */ # # LICENSE # # Copyright (c) 2008 Loic Dachary # Copyright (c) 2010 Bastien Chevreux # # 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, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 14 AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB]) AC_DEFUN([AX_CHECK_ZLIB], # # Handle user hints # [AC_MSG_CHECKING(if zlib is wanted) zlib_places="/usr/local /usr /opt/local /sw" AC_ARG_WITH([zlib], [ --with-zlib=DIR root directory path of zlib installation @<:@defaults to /usr/local or /usr if not found in /usr/local@:>@ --without-zlib to disable zlib usage completely], [if test "$withval" != no ; then AC_MSG_RESULT(yes) if test -d "$withval" then zlib_places="$withval $zlib_places" else AC_MSG_WARN([Sorry, $withval does not exist, checking usual places]) fi else zlib_places= AC_MSG_RESULT(no) fi], [AC_MSG_RESULT(yes)]) # # Locate zlib, if wanted # if test -n "${zlib_places}" then # check the user supplied or any other more or less 'standard' place: # Most UNIX systems : /usr/local and /usr # MacPorts / Fink on OSX : /opt/local respectively /sw for ZLIB_HOME in ${zlib_places} ; do if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi ZLIB_HOME="" done ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$CPPFLAGS if test -n "${ZLIB_HOME}"; then LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" fi AC_LANG_SAVE AC_LANG_C AC_CHECK_LIB([z], [inflateEnd], [zlib_cv_libz=yes], [zlib_cv_libz=no]) AC_CHECK_HEADER([zlib.h], [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no]) AC_LANG_RESTORE if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, action-if-found # m4_ifblank([$1],[ CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" LIBS="-lz $LIBS" AC_DEFINE([HAVE_LIBZ], [1], [Define to 1 if you have `z' library (-lz)]) ],[ # Restore variables LDFLAGS="$ZLIB_OLD_LDFLAGS" CPPFLAGS="$ZLIB_OLD_CPPFLAGS" $1 ]) else # # If either header or library was not found, action-if-not-found # m4_default([$2],[ AC_MSG_ERROR([either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib]) ]) fi fi ]) ================================================ FILE: mime-types.c ================================================ unsigned char mime_types[] = { 0x23, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x73, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x29, 0x2e, 0x0a, 0x23, 0x20, 0x41, 0x6c, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x74, 0x74, 0x70, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x29, 0x20, 0x75, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x0a, 0x23, 0x20, 0x41, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x75, 0x69, 0x64, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x65, 0x61, 0x73, 0x69, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x0a, 0x23, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x20, 0x22, 0x6e, 0x65, 0x77, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x20, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x63, 0x61, 0x72, 0x65, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x52, 0x46, 0x43, 0x20, 0x34, 0x32, 0x38, 0x38, 0x2e, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x61, 0x74, 0x20, 0x3c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x61, 0x6e, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x2e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x28, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x64, 0x29, 0x09, 0x09, 0x09, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x23, 0x20, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x09, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x31, 0x64, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x64, 0x2d, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x33, 0x67, 0x70, 0x70, 0x2d, 0x69, 0x6d, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x65, 0x77, 0x2d, 0x69, 0x6e, 0x73, 0x65, 0x74, 0x09, 0x09, 0x09, 0x65, 0x7a, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x78, 0x77, 0x61, 0x72, 0x65, 0x09, 0x09, 0x09, 0x09, 0x61, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x6f, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x61, 0x74, 0x6f, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x6f, 0x6d, 0x63, 0x61, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x61, 0x74, 0x6f, 0x6d, 0x63, 0x61, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x6d, 0x61, 0x69, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x6f, 0x6d, 0x73, 0x76, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x61, 0x74, 0x6f, 0x6d, 0x73, 0x76, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x2d, 0x73, 0x6d, 0x74, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x62, 0x65, 0x65, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x61, 0x6c, 0x73, 0x2d, 0x31, 0x38, 0x34, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x63, 0x6d, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x63, 0x78, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x63, 0x63, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x64, 0x6d, 0x69, 0x2d, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x09, 0x09, 0x09, 0x63, 0x64, 0x6d, 0x69, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x64, 0x6d, 0x69, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x09, 0x09, 0x09, 0x63, 0x64, 0x6d, 0x69, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x64, 0x6d, 0x69, 0x2d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x63, 0x64, 0x6d, 0x69, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x64, 0x6d, 0x69, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x09, 0x09, 0x09, 0x09, 0x63, 0x64, 0x6d, 0x69, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x64, 0x6d, 0x69, 0x2d, 0x71, 0x75, 0x65, 0x75, 0x65, 0x09, 0x09, 0x09, 0x09, 0x63, 0x64, 0x6d, 0x69, 0x71, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x65, 0x61, 0x2d, 0x32, 0x30, 0x31, 0x38, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x65, 0x6c, 0x6c, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x66, 0x77, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6e, 0x72, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x70, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x73, 0x74, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x73, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x75, 0x2d, 0x73, 0x65, 0x65, 0x6d, 0x65, 0x09, 0x09, 0x09, 0x09, 0x63, 0x75, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x79, 0x62, 0x65, 0x72, 0x63, 0x61, 0x73, 0x68, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x61, 0x76, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x64, 0x61, 0x76, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x63, 0x61, 0x2d, 0x72, 0x66, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x65, 0x63, 0x2d, 0x64, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x69, 0x63, 0x6f, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x6e, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x6f, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x64, 0x62, 0x6b, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x73, 0x6b, 0x70, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x73, 0x73, 0x63, 0x2b, 0x64, 0x65, 0x72, 0x09, 0x09, 0x09, 0x09, 0x64, 0x73, 0x73, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x73, 0x73, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x64, 0x73, 0x73, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x76, 0x63, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x63, 0x6d, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x09, 0x09, 0x09, 0x09, 0x65, 0x63, 0x6d, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x64, 0x69, 0x2d, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x64, 0x69, 0x2d, 0x78, 0x31, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x64, 0x69, 0x66, 0x61, 0x63, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x6d, 0x6d, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6d, 0x6d, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x70, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x70, 0x75, 0x62, 0x2b, 0x7a, 0x69, 0x70, 0x09, 0x09, 0x09, 0x09, 0x65, 0x70, 0x75, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x73, 0x68, 0x6f, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x78, 0x69, 0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x78, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x65, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x61, 0x73, 0x74, 0x73, 0x6f, 0x61, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x62, 0x32, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x62, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x69, 0x74, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x74, 0x64, 0x70, 0x66, 0x72, 0x09, 0x09, 0x09, 0x09, 0x70, 0x66, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x67, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x70, 0x78, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x67, 0x70, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x78, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x67, 0x78, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x32, 0x32, 0x34, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x6c, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x79, 0x70, 0x65, 0x72, 0x73, 0x74, 0x75, 0x64, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x73, 0x74, 0x6b, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x62, 0x65, 0x2d, 0x6b, 0x65, 0x79, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x62, 0x65, 0x2d, 0x70, 0x6b, 0x67, 0x2d, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x62, 0x65, 0x2d, 0x70, 0x70, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x67, 0x65, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6d, 0x2d, 0x69, 0x73, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x6d, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x6f, 0x62, 0x6a, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x76, 0x6e, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x6b, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x69, 0x6e, 0x6b, 0x20, 0x69, 0x6e, 0x6b, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x6f, 0x74, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x70, 0x66, 0x69, 0x78, 0x09, 0x09, 0x09, 0x09, 0x69, 0x70, 0x66, 0x69, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x70, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x73, 0x75, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x2d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x09, 0x09, 0x09, 0x6a, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x2d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x09, 0x09, 0x73, 0x65, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x2d, 0x76, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x6d, 0x6c, 0x2b, 0x6a, 0x73, 0x6f, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6b, 0x70, 0x6d, 0x6c, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6b, 0x70, 0x6d, 0x6c, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6c, 0x6f, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x73, 0x74, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x63, 0x2d, 0x62, 0x69, 0x6e, 0x68, 0x65, 0x78, 0x34, 0x30, 0x09, 0x09, 0x09, 0x68, 0x71, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x63, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x70, 0x72, 0x6f, 0x09, 0x09, 0x09, 0x63, 0x70, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x63, 0x77, 0x72, 0x69, 0x74, 0x65, 0x69, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x64, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x61, 0x64, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x72, 0x63, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x72, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x72, 0x63, 0x78, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x72, 0x63, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x61, 0x20, 0x6e, 0x62, 0x20, 0x6d, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x6d, 0x6c, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x6d, 0x6c, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x61, 0x74, 0x68, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x64, 0x75, 0x72, 0x65, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x64, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x6d, 0x73, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x6d, 0x73, 0x6b, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x72, 0x65, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6d, 0x73, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x62, 0x6f, 0x78, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x62, 0x6f, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x6d, 0x73, 0x63, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x34, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x6d, 0x65, 0x74, 0x61, 0x34, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x65, 0x74, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x65, 0x74, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x69, 0x6b, 0x65, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x64, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6f, 0x64, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x73, 0x73, 0x2d, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x73, 0x73, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x70, 0x32, 0x31, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x32, 0x31, 0x20, 0x6d, 0x70, 0x32, 0x31, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x70, 0x34, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x34, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x34, 0x2d, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x34, 0x2d, 0x69, 0x6f, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x34, 0x2d, 0x69, 0x6f, 0x64, 0x2d, 0x78, 0x6d, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x73, 0x63, 0x2d, 0x69, 0x76, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x73, 0x63, 0x2d, 0x6d, 0x69, 0x78, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x09, 0x09, 0x09, 0x09, 0x64, 0x6f, 0x63, 0x20, 0x64, 0x6f, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6d, 0x78, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x78, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6e, 0x61, 0x73, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, 0x66, 0x6f, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6e, 0x73, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x09, 0x62, 0x69, 0x6e, 0x20, 0x64, 0x6d, 0x73, 0x20, 0x6c, 0x72, 0x66, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x73, 0x6f, 0x20, 0x64, 0x69, 0x73, 0x74, 0x20, 0x64, 0x69, 0x73, 0x74, 0x7a, 0x20, 0x70, 0x6b, 0x67, 0x20, 0x62, 0x70, 0x6b, 0x20, 0x64, 0x75, 0x6d, 0x70, 0x20, 0x65, 0x6c, 0x63, 0x20, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x64, 0x61, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x64, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x65, 0x62, 0x70, 0x73, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x6f, 0x70, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x67, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x67, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x6d, 0x64, 0x6f, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x6d, 0x64, 0x6f, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x6e, 0x65, 0x6e, 0x6f, 0x74, 0x65, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x6e, 0x65, 0x74, 0x6f, 0x63, 0x20, 0x6f, 0x6e, 0x65, 0x74, 0x6f, 0x63, 0x32, 0x20, 0x6f, 0x6e, 0x65, 0x74, 0x6d, 0x70, 0x20, 0x6f, 0x6e, 0x65, 0x70, 0x6b, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x78, 0x70, 0x73, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x78, 0x70, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2d, 0x6f, 0x70, 0x73, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x65, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x64, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x67, 0x70, 0x2d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x09, 0x09, 0x09, 0x70, 0x67, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x67, 0x70, 0x2d, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x67, 0x70, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x09, 0x09, 0x09, 0x61, 0x73, 0x63, 0x20, 0x73, 0x69, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x69, 0x63, 0x73, 0x2d, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x09, 0x09, 0x09, 0x09, 0x70, 0x72, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x69, 0x64, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x69, 0x64, 0x66, 0x2d, 0x64, 0x69, 0x66, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x63, 0x73, 0x31, 0x30, 0x09, 0x09, 0x09, 0x09, 0x70, 0x31, 0x30, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x63, 0x73, 0x37, 0x2d, 0x6d, 0x69, 0x6d, 0x65, 0x09, 0x09, 0x09, 0x09, 0x70, 0x37, 0x6d, 0x20, 0x70, 0x37, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x63, 0x73, 0x37, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x09, 0x09, 0x09, 0x70, 0x37, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x63, 0x73, 0x38, 0x09, 0x09, 0x09, 0x09, 0x70, 0x38, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x69, 0x78, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x09, 0x09, 0x09, 0x61, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x69, 0x78, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x09, 0x09, 0x09, 0x09, 0x63, 0x65, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x69, 0x78, 0x2d, 0x63, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x63, 0x72, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x69, 0x78, 0x2d, 0x70, 0x6b, 0x69, 0x70, 0x61, 0x74, 0x68, 0x09, 0x09, 0x09, 0x70, 0x6b, 0x69, 0x70, 0x61, 0x74, 0x68, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x69, 0x78, 0x63, 0x6d, 0x70, 0x09, 0x09, 0x09, 0x09, 0x70, 0x6b, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6c, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x70, 0x6c, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x63, 0x2d, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x09, 0x09, 0x09, 0x09, 0x61, 0x69, 0x20, 0x65, 0x70, 0x73, 0x20, 0x70, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x61, 0x6c, 0x76, 0x65, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x2e, 0x74, 0x69, 0x74, 0x72, 0x61, 0x78, 0x2d, 0x73, 0x68, 0x65, 0x65, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x63, 0x77, 0x77, 0x09, 0x09, 0x09, 0x09, 0x63, 0x77, 0x77, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x6e, 0x70, 0x72, 0x65, 0x6e, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x63, 0x6b, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x72, 0x64, 0x66, 0x2d, 0x78, 0x6d, 0x6c, 0x2d, 0x63, 0x72, 0x79, 0x70, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x78, 0x73, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x73, 0x6b, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x70, 0x73, 0x6b, 0x63, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x71, 0x73, 0x69, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x64, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x72, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x72, 0x69, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x78, 0x2d, 0x6e, 0x67, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x09, 0x09, 0x72, 0x6e, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x72, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x2d, 0x64, 0x69, 0x66, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x72, 0x6c, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x69, 0x73, 0x63, 0x6f, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x6c, 0x6d, 0x69, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x72, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x70, 0x6b, 0x69, 0x2d, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x62, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x09, 0x09, 0x09, 0x67, 0x62, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x70, 0x6b, 0x69, 0x2d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x09, 0x09, 0x09, 0x6d, 0x66, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x70, 0x6b, 0x69, 0x2d, 0x72, 0x6f, 0x61, 0x09, 0x09, 0x09, 0x09, 0x72, 0x6f, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x70, 0x6b, 0x69, 0x2d, 0x75, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x73, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x72, 0x73, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x73, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x72, 0x73, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x74, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x74, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x72, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x61, 0x6d, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x61, 0x6d, 0x6c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x62, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x62, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x63, 0x76, 0x70, 0x2d, 0x63, 0x76, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x09, 0x09, 0x09, 0x73, 0x63, 0x71, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x63, 0x76, 0x70, 0x2d, 0x63, 0x76, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x09, 0x09, 0x09, 0x73, 0x63, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x63, 0x76, 0x70, 0x2d, 0x76, 0x70, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x09, 0x09, 0x09, 0x73, 0x70, 0x71, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x63, 0x76, 0x70, 0x2d, 0x76, 0x70, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x09, 0x09, 0x09, 0x73, 0x70, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x64, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x64, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x73, 0x65, 0x74, 0x70, 0x61, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x74, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x74, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x73, 0x65, 0x74, 0x72, 0x65, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x67, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x67, 0x6d, 0x6c, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x68, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x68, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x69, 0x65, 0x76, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x6d, 0x69, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x6d, 0x69, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x6d, 0x69, 0x20, 0x73, 0x6d, 0x69, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x6f, 0x61, 0x70, 0x2b, 0x66, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x65, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x6f, 0x61, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x70, 0x61, 0x72, 0x71, 0x6c, 0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x09, 0x09, 0x09, 0x72, 0x71, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x70, 0x61, 0x72, 0x71, 0x6c, 0x2d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x73, 0x72, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x73, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x72, 0x67, 0x73, 0x09, 0x09, 0x09, 0x09, 0x67, 0x72, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x72, 0x67, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x67, 0x72, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x72, 0x75, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x72, 0x75, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x73, 0x64, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x73, 0x64, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x73, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x73, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x61, 0x70, 0x65, 0x78, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x61, 0x70, 0x65, 0x78, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x69, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x74, 0x65, 0x69, 0x20, 0x74, 0x65, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x68, 0x72, 0x61, 0x75, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x74, 0x66, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2d, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x65, 0x64, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x09, 0x09, 0x09, 0x74, 0x73, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x76, 0x65, 0x2d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x75, 0x6c, 0x70, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x63, 0x61, 0x72, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x65, 0x6d, 0x6d, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x69, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x2e, 0x62, 0x73, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x2e, 0x70, 0x69, 0x63, 0x2d, 0x62, 0x77, 0x2d, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x09, 0x09, 0x70, 0x6c, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x2e, 0x70, 0x69, 0x63, 0x2d, 0x62, 0x77, 0x2d, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x09, 0x09, 0x70, 0x73, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x2e, 0x70, 0x69, 0x63, 0x2d, 0x62, 0x77, 0x2d, 0x76, 0x61, 0x72, 0x09, 0x09, 0x09, 0x70, 0x76, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x2e, 0x73, 0x6d, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x32, 0x2e, 0x62, 0x63, 0x6d, 0x63, 0x73, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x32, 0x2e, 0x73, 0x6d, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x32, 0x2e, 0x74, 0x63, 0x61, 0x70, 0x09, 0x09, 0x09, 0x74, 0x63, 0x61, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x6d, 0x2e, 0x70, 0x6f, 0x73, 0x74, 0x2d, 0x69, 0x74, 0x2d, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x09, 0x09, 0x70, 0x77, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x63, 0x63, 0x70, 0x61, 0x63, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x2e, 0x61, 0x73, 0x6f, 0x09, 0x09, 0x61, 0x73, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x63, 0x63, 0x70, 0x61, 0x63, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x2e, 0x69, 0x6d, 0x70, 0x09, 0x09, 0x69, 0x6d, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x63, 0x75, 0x63, 0x6f, 0x62, 0x6f, 0x6c, 0x09, 0x09, 0x09, 0x61, 0x63, 0x75, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x63, 0x75, 0x63, 0x6f, 0x72, 0x70, 0x09, 0x09, 0x09, 0x09, 0x61, 0x74, 0x63, 0x20, 0x61, 0x63, 0x75, 0x74, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2b, 0x7a, 0x69, 0x70, 0x09, 0x61, 0x69, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x2e, 0x66, 0x63, 0x64, 0x74, 0x09, 0x09, 0x66, 0x63, 0x64, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x66, 0x78, 0x70, 0x09, 0x09, 0x09, 0x66, 0x78, 0x70, 0x20, 0x66, 0x78, 0x70, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x64, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x64, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x66, 0x64, 0x66, 0x09, 0x09, 0x09, 0x78, 0x66, 0x64, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x69, 0x6d, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x68, 0x2d, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x68, 0x65, 0x61, 0x64, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x09, 0x09, 0x09, 0x61, 0x68, 0x65, 0x61, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x69, 0x72, 0x7a, 0x69, 0x70, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x61, 0x7a, 0x66, 0x09, 0x09, 0x61, 0x7a, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x69, 0x72, 0x7a, 0x69, 0x70, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x61, 0x7a, 0x73, 0x09, 0x09, 0x61, 0x7a, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x2e, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x09, 0x09, 0x09, 0x61, 0x7a, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x73, 0x2e, 0x61, 0x63, 0x63, 0x09, 0x09, 0x61, 0x63, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6d, 0x69, 0x67, 0x61, 0x2e, 0x61, 0x6d, 0x69, 0x09, 0x09, 0x09, 0x61, 0x6d, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6d, 0x75, 0x6e, 0x64, 0x73, 0x65, 0x6e, 0x2e, 0x6d, 0x61, 0x7a, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x09, 0x09, 0x61, 0x70, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6e, 0x73, 0x65, 0x72, 0x2d, 0x77, 0x65, 0x62, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2d, 0x69, 0x73, 0x73, 0x75, 0x65, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x63, 0x69, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6e, 0x73, 0x65, 0x72, 0x2d, 0x77, 0x65, 0x62, 0x2d, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x66, 0x74, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x6e, 0x74, 0x69, 0x78, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x09, 0x09, 0x61, 0x74, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x6d, 0x70, 0x6b, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x6d, 0x33, 0x75, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x72, 0x61, 0x73, 0x74, 0x72, 0x61, 0x2e, 0x73, 0x77, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x72, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x73, 0x77, 0x69, 0x09, 0x09, 0x73, 0x77, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x61, 0x65, 0x61, 0x2d, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x69, 0x6f, 0x74, 0x61, 0x09, 0x09, 0x69, 0x6f, 0x74, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x09, 0x09, 0x09, 0x61, 0x65, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x76, 0x69, 0x73, 0x74, 0x61, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x62, 0x6c, 0x75, 0x65, 0x69, 0x63, 0x65, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x73, 0x73, 0x09, 0x09, 0x6d, 0x70, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x62, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, 0x2e, 0x65, 0x70, 0x2e, 0x6f, 0x6f, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x62, 0x6d, 0x69, 0x09, 0x09, 0x09, 0x09, 0x62, 0x6d, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x09, 0x09, 0x09, 0x72, 0x65, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x61, 0x62, 0x2d, 0x6a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x70, 0x64, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x2d, 0x6c, 0x69, 0x70, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6f, 0x2e, 0x74, 0x68, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x63, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6e, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x68, 0x65, 0x6d, 0x64, 0x72, 0x61, 0x77, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x63, 0x64, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x68, 0x69, 0x70, 0x6e, 0x75, 0x74, 0x73, 0x2e, 0x6b, 0x61, 0x72, 0x61, 0x6f, 0x6b, 0x65, 0x2d, 0x6d, 0x6d, 0x64, 0x09, 0x09, 0x6d, 0x6d, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x09, 0x09, 0x09, 0x63, 0x64, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x69, 0x72, 0x70, 0x61, 0x63, 0x6b, 0x2e, 0x69, 0x73, 0x64, 0x6e, 0x2d, 0x65, 0x78, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6c, 0x61, 0x79, 0x6d, 0x6f, 0x72, 0x65, 0x09, 0x09, 0x09, 0x63, 0x6c, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6c, 0x6f, 0x61, 0x6e, 0x74, 0x6f, 0x2e, 0x72, 0x70, 0x39, 0x09, 0x09, 0x09, 0x72, 0x70, 0x39, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6c, 0x6f, 0x6e, 0x6b, 0x2e, 0x63, 0x34, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x09, 0x09, 0x09, 0x63, 0x34, 0x67, 0x20, 0x63, 0x34, 0x64, 0x20, 0x63, 0x34, 0x66, 0x20, 0x63, 0x34, 0x70, 0x20, 0x63, 0x34, 0x75, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6c, 0x75, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x61, 0x72, 0x74, 0x6f, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x09, 0x09, 0x63, 0x31, 0x31, 0x61, 0x6d, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6c, 0x75, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x61, 0x72, 0x74, 0x6f, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6b, 0x67, 0x09, 0x63, 0x31, 0x31, 0x61, 0x6d, 0x7a, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x6a, 0x73, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x2d, 0x62, 0x61, 0x74, 0x74, 0x65, 0x6c, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x09, 0x09, 0x09, 0x63, 0x73, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x2e, 0x63, 0x6d, 0x73, 0x67, 0x09, 0x09, 0x09, 0x63, 0x64, 0x62, 0x63, 0x6d, 0x73, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x09, 0x09, 0x09, 0x63, 0x6d, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x63, 0x6b, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x09, 0x09, 0x09, 0x63, 0x6c, 0x6b, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x63, 0x6b, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x09, 0x09, 0x63, 0x6c, 0x6b, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x63, 0x6b, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x09, 0x09, 0x63, 0x6c, 0x6b, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x63, 0x6b, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x09, 0x63, 0x6c, 0x6b, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x63, 0x6b, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x62, 0x61, 0x6e, 0x6b, 0x09, 0x09, 0x63, 0x6c, 0x6b, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2e, 0x77, 0x62, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x77, 0x62, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x74, 0x63, 0x2d, 0x70, 0x6f, 0x73, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x70, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x74, 0x63, 0x74, 0x2e, 0x77, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x70, 0x73, 0x2d, 0x70, 0x64, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x70, 0x73, 0x2d, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x70, 0x73, 0x2d, 0x70, 0x70, 0x64, 0x09, 0x09, 0x09, 0x70, 0x70, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x70, 0x73, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x70, 0x73, 0x2d, 0x72, 0x61, 0x77, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x2e, 0x63, 0x61, 0x72, 0x09, 0x09, 0x09, 0x63, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x2e, 0x70, 0x63, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x70, 0x63, 0x75, 0x72, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x79, 0x62, 0x61, 0x6e, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x61, 0x72, 0x74, 0x09, 0x09, 0x09, 0x09, 0x64, 0x61, 0x72, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x72, 0x64, 0x7a, 0x09, 0x09, 0x09, 0x72, 0x64, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x09, 0x09, 0x09, 0x75, 0x76, 0x66, 0x20, 0x75, 0x76, 0x76, 0x66, 0x20, 0x75, 0x76, 0x64, 0x20, 0x75, 0x76, 0x76, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x74, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x75, 0x76, 0x74, 0x20, 0x75, 0x76, 0x76, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x75, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x09, 0x09, 0x75, 0x76, 0x78, 0x20, 0x75, 0x76, 0x76, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x7a, 0x69, 0x70, 0x09, 0x09, 0x09, 0x75, 0x76, 0x7a, 0x20, 0x75, 0x76, 0x76, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x76, 0x6f, 0x2e, 0x66, 0x63, 0x73, 0x65, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x09, 0x09, 0x66, 0x65, 0x5f, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x69, 0x72, 0x2d, 0x62, 0x69, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2d, 0x64, 0x6c, 0x2d, 0x6e, 0x6f, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6e, 0x61, 0x09, 0x09, 0x09, 0x09, 0x64, 0x6e, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x6d, 0x6c, 0x70, 0x09, 0x09, 0x09, 0x6d, 0x6c, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2e, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2e, 0x32, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x70, 0x67, 0x72, 0x61, 0x70, 0x68, 0x09, 0x09, 0x09, 0x09, 0x64, 0x70, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x09, 0x09, 0x09, 0x64, 0x66, 0x61, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x73, 0x2d, 0x6b, 0x65, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x09, 0x09, 0x09, 0x6b, 0x70, 0x78, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x61, 0x69, 0x74, 0x09, 0x09, 0x09, 0x09, 0x61, 0x69, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x64, 0x76, 0x62, 0x6a, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x65, 0x73, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x64, 0x63, 0x64, 0x66, 0x74, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x64, 0x63, 0x65, 0x73, 0x67, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x64, 0x63, 0x65, 0x73, 0x67, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x64, 0x63, 0x65, 0x73, 0x67, 0x70, 0x64, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x64, 0x63, 0x72, 0x6f, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x2e, 0x61, 0x6c, 0x66, 0x65, 0x63, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x2e, 0x61, 0x6c, 0x66, 0x65, 0x63, 0x2d, 0x65, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x69, 0x61, 0x2d, 0x6d, 0x73, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x69, 0x61, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x69, 0x61, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x70, 0x66, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x09, 0x09, 0x09, 0x73, 0x76, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x78, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x79, 0x6e, 0x61, 0x67, 0x65, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x67, 0x65, 0x6f, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x61, 0x73, 0x79, 0x6b, 0x61, 0x72, 0x61, 0x6f, 0x6b, 0x65, 0x2e, 0x63, 0x64, 0x67, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x64, 0x69, 0x73, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x74, 0x09, 0x09, 0x09, 0x6d, 0x61, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x6d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x6e, 0x6c, 0x69, 0x76, 0x65, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x70, 0x73, 0x6f, 0x6e, 0x2e, 0x65, 0x73, 0x66, 0x09, 0x09, 0x09, 0x65, 0x73, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x70, 0x73, 0x6f, 0x6e, 0x2e, 0x6d, 0x73, 0x66, 0x09, 0x09, 0x09, 0x6d, 0x73, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x70, 0x73, 0x6f, 0x6e, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x61, 0x6e, 0x69, 0x6d, 0x65, 0x09, 0x09, 0x71, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x70, 0x73, 0x6f, 0x6e, 0x2e, 0x73, 0x61, 0x6c, 0x74, 0x09, 0x09, 0x09, 0x73, 0x6c, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x70, 0x73, 0x6f, 0x6e, 0x2e, 0x73, 0x73, 0x66, 0x09, 0x09, 0x09, 0x73, 0x73, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x72, 0x69, 0x63, 0x73, 0x73, 0x6f, 0x6e, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x63, 0x61, 0x6c, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x73, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x33, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x65, 0x73, 0x33, 0x20, 0x65, 0x74, 0x33, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x61, 0x6f, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x63, 0x75, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x73, 0x61, 0x64, 0x2d, 0x62, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x73, 0x61, 0x64, 0x2d, 0x63, 0x6f, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x73, 0x61, 0x64, 0x2d, 0x6e, 0x70, 0x76, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x75, 0x65, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x6d, 0x63, 0x69, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x6f, 0x61, 0x64, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x73, 0x63, 0x69, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x73, 0x69, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x74, 0x73, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x74, 0x73, 0x69, 0x2e, 0x74, 0x73, 0x6c, 0x2e, 0x64, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x7a, 0x70, 0x69, 0x78, 0x2d, 0x61, 0x6c, 0x62, 0x75, 0x6d, 0x09, 0x09, 0x09, 0x65, 0x7a, 0x32, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x7a, 0x70, 0x69, 0x78, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x09, 0x09, 0x09, 0x65, 0x7a, 0x33, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x2d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x64, 0x66, 0x09, 0x09, 0x09, 0x09, 0x66, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x64, 0x73, 0x6e, 0x2e, 0x6d, 0x73, 0x65, 0x65, 0x64, 0x09, 0x09, 0x09, 0x6d, 0x73, 0x65, 0x65, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x64, 0x73, 0x6e, 0x2e, 0x73, 0x65, 0x65, 0x64, 0x09, 0x09, 0x09, 0x73, 0x65, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x6c, 0x65, 0x73, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x66, 0x73, 0x6e, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x74, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x6c, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x74, 0x09, 0x09, 0x09, 0x67, 0x70, 0x68, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x6c, 0x75, 0x78, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x63, 0x6c, 0x69, 0x70, 0x09, 0x09, 0x09, 0x66, 0x74, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x2d, 0x73, 0x66, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x6d, 0x61, 0x6b, 0x65, 0x72, 0x09, 0x09, 0x09, 0x66, 0x6d, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x72, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x72, 0x6f, 0x67, 0x61, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x63, 0x09, 0x09, 0x09, 0x66, 0x6e, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x72, 0x6f, 0x67, 0x61, 0x6e, 0x73, 0x2e, 0x6c, 0x74, 0x66, 0x09, 0x09, 0x09, 0x6c, 0x74, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x73, 0x63, 0x2e, 0x77, 0x65, 0x62, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x09, 0x09, 0x09, 0x66, 0x73, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x74, 0x73, 0x75, 0x2e, 0x6f, 0x61, 0x73, 0x79, 0x73, 0x09, 0x09, 0x09, 0x6f, 0x61, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x74, 0x73, 0x75, 0x2e, 0x6f, 0x61, 0x73, 0x79, 0x73, 0x32, 0x09, 0x09, 0x09, 0x6f, 0x61, 0x32, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x74, 0x73, 0x75, 0x2e, 0x6f, 0x61, 0x73, 0x79, 0x73, 0x33, 0x09, 0x09, 0x09, 0x6f, 0x61, 0x33, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x74, 0x73, 0x75, 0x2e, 0x6f, 0x61, 0x73, 0x79, 0x73, 0x67, 0x70, 0x09, 0x09, 0x09, 0x66, 0x67, 0x35, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x74, 0x73, 0x75, 0x2e, 0x6f, 0x61, 0x73, 0x79, 0x73, 0x70, 0x72, 0x73, 0x09, 0x09, 0x62, 0x68, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x61, 0x72, 0x74, 0x2d, 0x65, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x61, 0x72, 0x74, 0x34, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x68, 0x62, 0x70, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x64, 0x64, 0x64, 0x09, 0x09, 0x09, 0x64, 0x64, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x09, 0x09, 0x78, 0x64, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x09, 0x78, 0x62, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x74, 0x2d, 0x6d, 0x69, 0x73, 0x6e, 0x65, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x7a, 0x7a, 0x79, 0x73, 0x68, 0x65, 0x65, 0x74, 0x09, 0x09, 0x09, 0x66, 0x7a, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x78, 0x2e, 0x74, 0x75, 0x78, 0x65, 0x64, 0x6f, 0x09, 0x09, 0x74, 0x78, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x63, 0x75, 0x62, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x67, 0x65, 0x62, 0x72, 0x61, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x67, 0x67, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x67, 0x65, 0x62, 0x72, 0x61, 0x2e, 0x74, 0x6f, 0x6f, 0x6c, 0x09, 0x09, 0x09, 0x67, 0x67, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2d, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x09, 0x09, 0x67, 0x65, 0x78, 0x20, 0x67, 0x72, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x6e, 0x65, 0x78, 0x74, 0x09, 0x09, 0x09, 0x09, 0x67, 0x78, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x70, 0x6c, 0x61, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x67, 0x32, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x09, 0x09, 0x09, 0x67, 0x33, 0x77, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6d, 0x67, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6d, 0x67, 0x74, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x6d, 0x78, 0x09, 0x09, 0x09, 0x09, 0x67, 0x6d, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2d, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x6b, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x6b, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2d, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x6b, 0x6d, 0x7a, 0x09, 0x09, 0x6b, 0x6d, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x61, 0x66, 0x65, 0x71, 0x09, 0x09, 0x09, 0x09, 0x67, 0x71, 0x66, 0x20, 0x67, 0x71, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x69, 0x64, 0x6d, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x09, 0x09, 0x09, 0x67, 0x61, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x68, 0x65, 0x6c, 0x70, 0x09, 0x09, 0x09, 0x67, 0x68, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x09, 0x09, 0x67, 0x69, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x09, 0x09, 0x09, 0x67, 0x72, 0x76, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x09, 0x09, 0x67, 0x74, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x09, 0x74, 0x70, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x2d, 0x76, 0x63, 0x61, 0x72, 0x64, 0x09, 0x09, 0x09, 0x76, 0x63, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x61, 0x6c, 0x2b, 0x6a, 0x73, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x61, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x68, 0x61, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x68, 0x65, 0x6c, 0x64, 0x2d, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x7a, 0x6d, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x62, 0x63, 0x69, 0x09, 0x09, 0x09, 0x09, 0x68, 0x62, 0x63, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x63, 0x6c, 0x2d, 0x62, 0x69, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x68, 0x65, 0x2e, 0x6c, 0x65, 0x73, 0x73, 0x6f, 0x6e, 0x2d, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x09, 0x09, 0x6c, 0x65, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x68, 0x70, 0x67, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x68, 0x70, 0x67, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x68, 0x70, 0x69, 0x64, 0x09, 0x09, 0x09, 0x09, 0x68, 0x70, 0x69, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x68, 0x70, 0x73, 0x09, 0x09, 0x09, 0x09, 0x68, 0x70, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x6a, 0x6c, 0x79, 0x74, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x6c, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x70, 0x63, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x70, 0x63, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x70, 0x63, 0x6c, 0x78, 0x6c, 0x09, 0x09, 0x09, 0x70, 0x63, 0x6c, 0x78, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x79, 0x64, 0x72, 0x6f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x78, 0x2e, 0x73, 0x6f, 0x66, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x09, 0x09, 0x73, 0x66, 0x64, 0x2d, 0x68, 0x64, 0x73, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x7a, 0x6e, 0x2d, 0x33, 0x64, 0x2d, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x62, 0x6d, 0x2e, 0x61, 0x66, 0x70, 0x6c, 0x69, 0x6e, 0x65, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x62, 0x6d, 0x2e, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x2d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x62, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x69, 0x70, 0x61, 0x79, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x62, 0x6d, 0x2e, 0x6d, 0x6f, 0x64, 0x63, 0x61, 0x70, 0x09, 0x09, 0x09, 0x61, 0x66, 0x70, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x61, 0x66, 0x70, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x33, 0x38, 0x32, 0x30, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x62, 0x6d, 0x2e, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x09, 0x09, 0x69, 0x72, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x62, 0x6d, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x09, 0x09, 0x73, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x63, 0x63, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x69, 0x63, 0x63, 0x20, 0x69, 0x63, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x67, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x09, 0x09, 0x09, 0x69, 0x67, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6d, 0x6d, 0x65, 0x72, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x69, 0x76, 0x70, 0x09, 0x09, 0x09, 0x69, 0x76, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6d, 0x6d, 0x65, 0x72, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x69, 0x76, 0x75, 0x09, 0x09, 0x09, 0x69, 0x76, 0x75, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x72, 0x6d, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x78, 0x2d, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x61, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x74, 0x65, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x74, 0x65, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x6e, 0x6f, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x77, 0x61, 0x6d, 0x70, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x2e, 0x69, 0x67, 0x6d, 0x09, 0x09, 0x09, 0x69, 0x67, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x6e, 0x65, 0x74, 0x09, 0x09, 0x78, 0x70, 0x77, 0x20, 0x78, 0x70, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x67, 0x65, 0x6f, 0x09, 0x09, 0x09, 0x69, 0x32, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x62, 0x6f, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x6e, 0x63, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x75, 0x2e, 0x71, 0x62, 0x6f, 0x09, 0x09, 0x09, 0x71, 0x62, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x75, 0x2e, 0x71, 0x66, 0x78, 0x09, 0x09, 0x09, 0x71, 0x66, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x67, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x69, 0x74, 0x65, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x67, 0x32, 0x2e, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x69, 0x74, 0x65, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x67, 0x32, 0x2e, 0x6e, 0x65, 0x77, 0x73, 0x69, 0x74, 0x65, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x67, 0x32, 0x2e, 0x6e, 0x65, 0x77, 0x73, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x67, 0x32, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x69, 0x74, 0x65, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x67, 0x32, 0x2e, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x69, 0x74, 0x65, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x75, 0x6e, 0x70, 0x6c, 0x75, 0x67, 0x67, 0x65, 0x64, 0x2e, 0x72, 0x63, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x72, 0x63, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x69, 0x72, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x73, 0x2d, 0x78, 0x70, 0x72, 0x09, 0x09, 0x09, 0x09, 0x78, 0x70, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x73, 0x61, 0x63, 0x2e, 0x66, 0x63, 0x73, 0x09, 0x09, 0x09, 0x66, 0x63, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x61, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x6a, 0x70, 0x6e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2d, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2d, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x74, 0x2d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x77, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x63, 0x70, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x6d, 0x65, 0x2e, 0x6d, 0x69, 0x64, 0x6c, 0x65, 0x74, 0x2d, 0x72, 0x6d, 0x73, 0x09, 0x09, 0x72, 0x6d, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x69, 0x73, 0x70, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x69, 0x73, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6a, 0x6f, 0x6f, 0x73, 0x74, 0x2e, 0x6a, 0x6f, 0x64, 0x61, 0x2d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x09, 0x09, 0x6a, 0x6f, 0x64, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x61, 0x68, 0x6f, 0x6f, 0x74, 0x7a, 0x09, 0x09, 0x09, 0x09, 0x6b, 0x74, 0x7a, 0x20, 0x6b, 0x74, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x09, 0x09, 0x09, 0x6b, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x63, 0x68, 0x61, 0x72, 0x74, 0x09, 0x09, 0x09, 0x63, 0x68, 0x72, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x09, 0x09, 0x09, 0x6b, 0x66, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x69, 0x76, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x6f, 0x6e, 0x74, 0x6f, 0x75, 0x72, 0x09, 0x09, 0x09, 0x6b, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x09, 0x09, 0x09, 0x6b, 0x70, 0x72, 0x20, 0x6b, 0x70, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x09, 0x09, 0x09, 0x6b, 0x73, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x64, 0x65, 0x2e, 0x6b, 0x77, 0x6f, 0x72, 0x64, 0x09, 0x09, 0x09, 0x6b, 0x77, 0x64, 0x20, 0x6b, 0x77, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x61, 0x61, 0x70, 0x70, 0x09, 0x09, 0x09, 0x68, 0x74, 0x6b, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x69, 0x64, 0x73, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x09, 0x6b, 0x69, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x69, 0x6e, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x6b, 0x6e, 0x65, 0x20, 0x6b, 0x6e, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x6f, 0x61, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x73, 0x6b, 0x70, 0x20, 0x73, 0x6b, 0x64, 0x20, 0x73, 0x6b, 0x74, 0x20, 0x73, 0x6b, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6b, 0x6f, 0x64, 0x61, 0x6b, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x09, 0x09, 0x73, 0x73, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x61, 0x73, 0x2e, 0x6c, 0x61, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x6c, 0x61, 0x73, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x69, 0x62, 0x65, 0x72, 0x74, 0x79, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6c, 0x69, 0x66, 0x65, 0x2d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x09, 0x6c, 0x62, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6c, 0x69, 0x66, 0x65, 0x2d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x6c, 0x62, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x31, 0x2d, 0x32, 0x2d, 0x33, 0x09, 0x09, 0x09, 0x31, 0x32, 0x33, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x61, 0x63, 0x68, 0x09, 0x09, 0x09, 0x61, 0x70, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x66, 0x72, 0x65, 0x65, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x09, 0x09, 0x09, 0x70, 0x72, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x09, 0x09, 0x09, 0x6e, 0x73, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x65, 0x72, 0x09, 0x09, 0x09, 0x6f, 0x72, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x63, 0x61, 0x6d, 0x09, 0x09, 0x09, 0x73, 0x63, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x2d, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x09, 0x09, 0x09, 0x6c, 0x77, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x61, 0x63, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x70, 0x6b, 0x67, 0x09, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x70, 0x6b, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x61, 0x72, 0x6c, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x6d, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x61, 0x72, 0x6c, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x61, 0x72, 0x6c, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x6d, 0x2e, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x61, 0x72, 0x6c, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x6d, 0x2e, 0x6d, 0x64, 0x63, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x63, 0x64, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x63, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x63, 0x61, 0x6c, 0x63, 0x64, 0x61, 0x74, 0x61, 0x09, 0x09, 0x09, 0x6d, 0x63, 0x31, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x64, 0x6b, 0x65, 0x79, 0x09, 0x09, 0x63, 0x64, 0x6b, 0x65, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x65, 0x72, 0x69, 0x64, 0x69, 0x61, 0x6e, 0x2d, 0x73, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x68, 0x6f, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x66, 0x65, 0x72, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x77, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x66, 0x6d, 0x70, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x66, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x66, 0x78, 0x2e, 0x66, 0x6c, 0x6f, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x66, 0x78, 0x2e, 0x69, 0x67, 0x78, 0x09, 0x09, 0x09, 0x69, 0x67, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x66, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x68, 0x70, 0x33, 0x30, 0x30, 0x30, 0x2d, 0x73, 0x61, 0x76, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x74, 0x73, 0x75, 0x62, 0x69, 0x73, 0x68, 0x69, 0x2e, 0x6d, 0x69, 0x73, 0x74, 0x79, 0x2d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x77, 0x65, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x64, 0x61, 0x66, 0x09, 0x09, 0x09, 0x64, 0x61, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x64, 0x69, 0x73, 0x09, 0x09, 0x09, 0x64, 0x69, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x6d, 0x62, 0x6b, 0x09, 0x09, 0x09, 0x6d, 0x62, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x6d, 0x71, 0x79, 0x09, 0x09, 0x09, 0x6d, 0x71, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x6d, 0x73, 0x6c, 0x09, 0x09, 0x09, 0x6d, 0x73, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x70, 0x6c, 0x63, 0x09, 0x09, 0x09, 0x70, 0x6c, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x75, 0x73, 0x2e, 0x74, 0x78, 0x66, 0x09, 0x09, 0x09, 0x74, 0x78, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x70, 0x68, 0x75, 0x6e, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x6d, 0x70, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x70, 0x68, 0x75, 0x6e, 0x2e, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x09, 0x09, 0x6d, 0x70, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x2e, 0x61, 0x64, 0x73, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x2e, 0x66, 0x69, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x2e, 0x67, 0x6f, 0x74, 0x61, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x2e, 0x6b, 0x6d, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x2e, 0x74, 0x74, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x69, 0x74, 0x65, 0x2e, 0x77, 0x65, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x69, 0x70, 0x72, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2e, 0x78, 0x75, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x75, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x61, 0x72, 0x74, 0x67, 0x61, 0x6c, 0x72, 0x79, 0x09, 0x09, 0x09, 0x63, 0x69, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x61, 0x73, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x63, 0x61, 0x62, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x63, 0x61, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x69, 0x63, 0x63, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x6c, 0x73, 0x20, 0x78, 0x6c, 0x6d, 0x20, 0x78, 0x6c, 0x61, 0x20, 0x78, 0x6c, 0x63, 0x20, 0x78, 0x6c, 0x74, 0x20, 0x78, 0x6c, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x6c, 0x2e, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x09, 0x78, 0x6c, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x6c, 0x2e, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x78, 0x6c, 0x73, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x6c, 0x2e, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x09, 0x78, 0x6c, 0x73, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x78, 0x6c, 0x74, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x09, 0x09, 0x09, 0x65, 0x6f, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x68, 0x74, 0x6d, 0x6c, 0x68, 0x65, 0x6c, 0x70, 0x09, 0x09, 0x09, 0x63, 0x68, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x69, 0x6d, 0x73, 0x09, 0x09, 0x09, 0x09, 0x69, 0x6d, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x6c, 0x72, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x6c, 0x72, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x78, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x09, 0x09, 0x09, 0x74, 0x68, 0x6d, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x62, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6b, 0x69, 0x2e, 0x73, 0x65, 0x63, 0x63, 0x61, 0x74, 0x09, 0x09, 0x09, 0x63, 0x61, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6b, 0x69, 0x2e, 0x73, 0x74, 0x6c, 0x09, 0x09, 0x09, 0x73, 0x74, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6c, 0x61, 0x79, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x09, 0x09, 0x09, 0x70, 0x70, 0x74, 0x20, 0x70, 0x70, 0x73, 0x20, 0x70, 0x6f, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x09, 0x70, 0x70, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x70, 0x70, 0x74, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x09, 0x73, 0x6c, 0x64, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x73, 0x68, 0x6f, 0x77, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x09, 0x70, 0x70, 0x73, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x09, 0x70, 0x6f, 0x74, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x70, 0x20, 0x6d, 0x70, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x74, 0x6e, 0x65, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x64, 0x72, 0x6d, 0x2e, 0x6c, 0x69, 0x63, 0x2d, 0x63, 0x68, 0x6c, 0x67, 0x2d, 0x72, 0x65, 0x71, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x64, 0x72, 0x6d, 0x2e, 0x6c, 0x69, 0x63, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x64, 0x72, 0x6d, 0x2e, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x68, 0x6c, 0x67, 0x2d, 0x72, 0x65, 0x71, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x64, 0x72, 0x6d, 0x2e, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6f, 0x72, 0x64, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x64, 0x6f, 0x63, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6f, 0x72, 0x64, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x31, 0x32, 0x09, 0x64, 0x6f, 0x74, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x09, 0x09, 0x09, 0x77, 0x70, 0x73, 0x20, 0x77, 0x6b, 0x73, 0x20, 0x77, 0x63, 0x6d, 0x20, 0x77, 0x64, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x77, 0x70, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x77, 0x70, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x78, 0x70, 0x73, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x09, 0x09, 0x09, 0x78, 0x70, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x65, 0x71, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x73, 0x65, 0x71, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x69, 0x67, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x69, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x2d, 0x6e, 0x69, 0x66, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x69, 0x61, 0x6e, 0x09, 0x09, 0x09, 0x6d, 0x75, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x75, 0x76, 0x65, 0x65, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x6d, 0x73, 0x74, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x79, 0x6e, 0x66, 0x63, 0x09, 0x09, 0x09, 0x09, 0x74, 0x61, 0x67, 0x6c, 0x65, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x63, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x63, 0x64, 0x2e, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x74, 0x66, 0x70, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x75, 0x72, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2e, 0x6e, 0x6c, 0x75, 0x09, 0x09, 0x6e, 0x6c, 0x75, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x69, 0x74, 0x66, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x74, 0x66, 0x20, 0x6e, 0x69, 0x74, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x62, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x09, 0x09, 0x6e, 0x6e, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x62, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x2d, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x72, 0x09, 0x09, 0x09, 0x6e, 0x6e, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x62, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x2d, 0x77, 0x65, 0x62, 0x09, 0x09, 0x09, 0x6e, 0x6e, 0x77, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x6d, 0x6c, 0x2b, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x69, 0x73, 0x64, 0x73, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6c, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x72, 0x6b, 0x2b, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6c, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x72, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6c, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x72, 0x6b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6e, 0x2d, 0x67, 0x61, 0x67, 0x65, 0x2e, 0x61, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6e, 0x2d, 0x67, 0x61, 0x67, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x09, 0x09, 0x6e, 0x67, 0x64, 0x61, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6e, 0x2d, 0x67, 0x61, 0x67, 0x65, 0x2e, 0x73, 0x79, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x09, 0x6e, 0x2d, 0x67, 0x61, 0x67, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6e, 0x63, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x70, 0x63, 0x64, 0x2b, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x70, 0x63, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x09, 0x09, 0x72, 0x70, 0x73, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x09, 0x09, 0x72, 0x70, 0x73, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x76, 0x61, 0x64, 0x69, 0x67, 0x6d, 0x2e, 0x65, 0x64, 0x6d, 0x09, 0x09, 0x09, 0x65, 0x64, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x76, 0x61, 0x64, 0x69, 0x67, 0x6d, 0x2e, 0x65, 0x64, 0x78, 0x09, 0x09, 0x09, 0x65, 0x64, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x76, 0x61, 0x64, 0x69, 0x67, 0x6d, 0x2e, 0x65, 0x78, 0x74, 0x09, 0x09, 0x09, 0x65, 0x78, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x74, 0x74, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x74, 0x74, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x73, 0x69, 0x70, 0x2d, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x74, 0x74, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x73, 0x69, 0x70, 0x2d, 0x74, 0x61, 0x5f, 0x74, 0x63, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x74, 0x09, 0x09, 0x6f, 0x64, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x74, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x74, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x09, 0x09, 0x6f, 0x64, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x09, 0x09, 0x6f, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x64, 0x66, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x09, 0x09, 0x6f, 0x64, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x74, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x09, 0x09, 0x6f, 0x64, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x74, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x6f, 0x64, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x74, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x09, 0x09, 0x6f, 0x64, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x74, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x09, 0x09, 0x09, 0x6f, 0x64, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x09, 0x09, 0x6f, 0x64, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x6f, 0x74, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x77, 0x65, 0x62, 0x09, 0x09, 0x6f, 0x74, 0x68, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x62, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x66, 0x74, 0x6e, 0x2e, 0x6c, 0x31, 0x30, 0x6e, 0x2b, 0x6a, 0x73, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x63, 0x73, 0x70, 0x67, 0x2d, 0x68, 0x65, 0x78, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x64, 0x61, 0x65, 0x2e, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x64, 0x61, 0x65, 0x2e, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x6d, 0x69, 0x70, 0x70, 0x76, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x70, 0x61, 0x65, 0x2e, 0x67, 0x65, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x73, 0x70, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x73, 0x70, 0x64, 0x6c, 0x69, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x75, 0x65, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x69, 0x70, 0x66, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6c, 0x70, 0x63, 0x2d, 0x73, 0x75, 0x67, 0x61, 0x72, 0x09, 0x09, 0x09, 0x78, 0x6f, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2d, 0x73, 0x63, 0x77, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2d, 0x73, 0x63, 0x77, 0x73, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2d, 0x73, 0x63, 0x77, 0x73, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x64, 0x75, 0x72, 0x65, 0x2d, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x64, 0x72, 0x6d, 0x2d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x6c, 0x74, 0x6b, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x67, 0x62, 0x6f, 0x6f, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x67, 0x64, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x67, 0x64, 0x75, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x6f, 0x76, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x62, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x6b, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x63, 0x61, 0x62, 0x2d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x6f, 0x6f, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x63, 0x61, 0x62, 0x2d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x63, 0x61, 0x62, 0x2d, 0x70, 0x63, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x63, 0x61, 0x62, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x70, 0x72, 0x65, 0x66, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x64, 0x63, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x64, 0x63, 0x64, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x64, 0x64, 0x32, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x64, 0x64, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x64, 0x72, 0x6d, 0x2e, 0x72, 0x69, 0x73, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x61, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x6f, 0x63, 0x2e, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x6f, 0x63, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x6f, 0x63, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x6f, 0x63, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x6f, 0x63, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x73, 0x63, 0x69, 0x64, 0x6d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x2e, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x64, 0x73, 0x2d, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x64, 0x73, 0x2d, 0x66, 0x69, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x64, 0x73, 0x2d, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x6d, 0x61, 0x6c, 0x6f, 0x63, 0x2d, 0x73, 0x75, 0x70, 0x6c, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x6f, 0x78, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x78, 0x6d, 0x6c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x74, 0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, 0x64, 0x61, 0x74, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6f, 0x75, 0x74, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x70, 0x70, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x09, 0x73, 0x6c, 0x64, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x73, 0x68, 0x6f, 0x77, 0x09, 0x70, 0x70, 0x73, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x73, 0x68, 0x6f, 0x77, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x74, 0x61, 0x67, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x70, 0x6f, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x6c, 0x2e, 0x76, 0x69, 0x65, 0x77, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x63, 0x61, 0x6c, 0x63, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x74, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x63, 0x61, 0x63, 0x68, 0x65, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x6c, 0x6f, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x73, 0x68, 0x65, 0x65, 0x74, 0x09, 0x78, 0x6c, 0x73, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x78, 0x6c, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x76, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6c, 0x65, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x6d, 0x6c, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x6d, 0x6c, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x09, 0x64, 0x6f, 0x63, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x6c, 0x6f, 0x73, 0x73, 0x61, 0x72, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x65, 0x6e, 0x64, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x66, 0x6f, 0x6e, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x66, 0x6f, 0x6f, 0x74, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x64, 0x6f, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x6d, 0x6c, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2d, 0x78, 0x6d, 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x78, 0x6d, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x71, 0x75, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x71, 0x75, 0x6f, 0x78, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x73, 0x61, 0x2e, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x73, 0x67, 0x65, 0x6f, 0x2e, 0x6d, 0x61, 0x70, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x09, 0x09, 0x6d, 0x67, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x73, 0x67, 0x69, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x73, 0x67, 0x69, 0x2e, 0x64, 0x70, 0x09, 0x09, 0x09, 0x09, 0x64, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x73, 0x67, 0x69, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x09, 0x09, 0x09, 0x65, 0x73, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x74, 0x70, 0x73, 0x2e, 0x63, 0x74, 0x2d, 0x6b, 0x69, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x61, 0x6c, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x70, 0x64, 0x62, 0x20, 0x70, 0x71, 0x61, 0x20, 0x6f, 0x70, 0x72, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x61, 0x6f, 0x73, 0x2e, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x61, 0x77, 0x61, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x70, 0x61, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x67, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x09, 0x09, 0x09, 0x73, 0x74, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x67, 0x2e, 0x6f, 0x73, 0x61, 0x73, 0x6c, 0x69, 0x09, 0x09, 0x09, 0x65, 0x69, 0x36, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x69, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x69, 0x63, 0x73, 0x65, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x65, 0x66, 0x69, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6d, 0x69, 0x2e, 0x77, 0x69, 0x64, 0x67, 0x65, 0x74, 0x09, 0x09, 0x09, 0x77, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x63, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x09, 0x09, 0x09, 0x70, 0x6c, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x36, 0x09, 0x09, 0x09, 0x70, 0x62, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x36, 0x2d, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x37, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x37, 0x2d, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x37, 0x35, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x37, 0x35, 0x2d, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x65, 0x6d, 0x69, 0x6e, 0x65, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2e, 0x62, 0x6f, 0x78, 0x09, 0x09, 0x62, 0x6f, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x75, 0x73, 0x2e, 0x6d, 0x61, 0x67, 0x61, 0x7a, 0x69, 0x6e, 0x65, 0x09, 0x09, 0x6d, 0x67, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2d, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2d, 0x74, 0x72, 0x65, 0x65, 0x09, 0x09, 0x71, 0x70, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x76, 0x69, 0x2e, 0x70, 0x74, 0x69, 0x64, 0x31, 0x09, 0x09, 0x09, 0x70, 0x74, 0x69, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x77, 0x67, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x77, 0x67, 0x2d, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x71, 0x75, 0x61, 0x6c, 0x63, 0x6f, 0x6d, 0x6d, 0x2e, 0x62, 0x72, 0x65, 0x77, 0x2d, 0x61, 0x70, 0x70, 0x2d, 0x72, 0x65, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x71, 0x75, 0x61, 0x72, 0x6b, 0x2e, 0x71, 0x75, 0x61, 0x72, 0x6b, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x09, 0x09, 0x71, 0x78, 0x64, 0x20, 0x71, 0x78, 0x74, 0x20, 0x71, 0x77, 0x64, 0x20, 0x71, 0x77, 0x74, 0x20, 0x71, 0x78, 0x6c, 0x20, 0x71, 0x78, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x6f, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x66, 0x61, 0x78, 0x2d, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x66, 0x61, 0x78, 0x2d, 0x73, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x63, 0x76, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x6f, 0x72, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x70, 0x69, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x65, 0x61, 0x6c, 0x76, 0x6e, 0x63, 0x2e, 0x62, 0x65, 0x64, 0x09, 0x09, 0x09, 0x62, 0x65, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x61, 0x72, 0x65, 0x2e, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x6d, 0x78, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x61, 0x72, 0x65, 0x2e, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x78, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x65, 0x6e, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x2e, 0x72, 0x6c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x69, 0x67, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x6e, 0x6f, 0x74, 0x65, 0x09, 0x09, 0x09, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x6e, 0x6f, 0x74, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x69, 0x6d, 0x2e, 0x63, 0x6f, 0x64, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x6e, 0x2d, 0x72, 0x65, 0x61, 0x6c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x09, 0x09, 0x09, 0x72, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x6e, 0x2d, 0x72, 0x65, 0x61, 0x6c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x76, 0x62, 0x72, 0x09, 0x09, 0x72, 0x6d, 0x76, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x36, 0x36, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x36, 0x36, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x36, 0x36, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x73, 0x2d, 0x32, 0x37, 0x34, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x75, 0x63, 0x6b, 0x75, 0x73, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x33, 0x73, 0x6d, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x09, 0x09, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x62, 0x6d, 0x2e, 0x63, 0x69, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x62, 0x6d, 0x2e, 0x6d, 0x69, 0x64, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x63, 0x72, 0x69, 0x62, 0x75, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x33, 0x64, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x63, 0x73, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x64, 0x6f, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x65, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x6d, 0x68, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x6e, 0x65, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x70, 0x70, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x74, 0x69, 0x66, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x6c, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x73, 0x65, 0x61, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x73, 0x65, 0x61, 0x6c, 0x2e, 0x70, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x6d, 0x61, 0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6d, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x6d, 0x64, 0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6d, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x6d, 0x66, 0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6d, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x68, 0x61, 0x6e, 0x61, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x64, 0x61, 0x74, 0x61, 0x09, 0x09, 0x69, 0x66, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x68, 0x61, 0x6e, 0x61, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x69, 0x74, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x68, 0x61, 0x6e, 0x61, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x09, 0x69, 0x69, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x68, 0x61, 0x6e, 0x61, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x09, 0x09, 0x69, 0x70, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x69, 0x6d, 0x74, 0x65, 0x63, 0x68, 0x2d, 0x6d, 0x69, 0x6e, 0x64, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x09, 0x09, 0x74, 0x77, 0x64, 0x20, 0x74, 0x77, 0x64, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x6d, 0x61, 0x66, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6d, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x2e, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x61, 0x63, 0x68, 0x65, 0x72, 0x09, 0x09, 0x09, 0x74, 0x65, 0x61, 0x63, 0x68, 0x65, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x36, 0x30, 0x32, 0x2e, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x36, 0x30, 0x32, 0x2e, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x78, 0x6d, 0x6c, 0x2d, 0x7a, 0x69, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x6f, 0x6c, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x73, 0x64, 0x6b, 0x6d, 0x20, 0x73, 0x64, 0x6b, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x70, 0x6f, 0x74, 0x66, 0x69, 0x72, 0x65, 0x2e, 0x64, 0x78, 0x70, 0x09, 0x09, 0x09, 0x64, 0x78, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x70, 0x6f, 0x74, 0x66, 0x69, 0x72, 0x65, 0x2e, 0x73, 0x66, 0x73, 0x09, 0x09, 0x09, 0x73, 0x66, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x73, 0x73, 0x2d, 0x63, 0x6f, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x73, 0x73, 0x2d, 0x64, 0x74, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x73, 0x73, 0x2d, 0x6e, 0x74, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x61, 0x6c, 0x63, 0x09, 0x09, 0x73, 0x64, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x09, 0x09, 0x73, 0x64, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x69, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x09, 0x09, 0x73, 0x64, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x09, 0x09, 0x73, 0x6d, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x09, 0x09, 0x73, 0x64, 0x77, 0x20, 0x76, 0x6f, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2d, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x09, 0x73, 0x67, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x09, 0x09, 0x73, 0x6d, 0x7a, 0x69, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x63, 0x68, 0x61, 0x72, 0x74, 0x09, 0x09, 0x73, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x63, 0x61, 0x6c, 0x63, 0x09, 0x09, 0x09, 0x73, 0x78, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x63, 0x61, 0x6c, 0x63, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x09, 0x73, 0x74, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x09, 0x09, 0x09, 0x73, 0x78, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x09, 0x73, 0x74, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x69, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x09, 0x09, 0x09, 0x73, 0x78, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x69, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x73, 0x74, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x09, 0x09, 0x09, 0x73, 0x78, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x09, 0x09, 0x09, 0x73, 0x78, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x09, 0x09, 0x73, 0x78, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x09, 0x09, 0x73, 0x74, 0x77, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x77, 0x61, 0x64, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x73, 0x2d, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x09, 0x09, 0x09, 0x73, 0x75, 0x73, 0x20, 0x73, 0x75, 0x73, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x76, 0x64, 0x09, 0x09, 0x09, 0x09, 0x73, 0x76, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x77, 0x69, 0x66, 0x74, 0x76, 0x69, 0x65, 0x77, 0x2d, 0x69, 0x63, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x79, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x09, 0x09, 0x09, 0x73, 0x69, 0x73, 0x20, 0x73, 0x69, 0x73, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x73, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x6d, 0x6c, 0x2e, 0x64, 0x6d, 0x2b, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x62, 0x64, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x6d, 0x6c, 0x2e, 0x64, 0x6d, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x64, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x6d, 0x6c, 0x2e, 0x64, 0x6d, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x6d, 0x6c, 0x2e, 0x64, 0x73, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x61, 0x6f, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x09, 0x74, 0x61, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x63, 0x70, 0x64, 0x75, 0x6d, 0x70, 0x2e, 0x70, 0x63, 0x61, 0x70, 0x09, 0x09, 0x09, 0x70, 0x63, 0x61, 0x70, 0x20, 0x63, 0x61, 0x70, 0x20, 0x64, 0x6d, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2d, 0x6c, 0x69, 0x76, 0x65, 0x74, 0x76, 0x09, 0x09, 0x09, 0x74, 0x6d, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x72, 0x69, 0x64, 0x2e, 0x74, 0x70, 0x74, 0x09, 0x09, 0x09, 0x74, 0x70, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x72, 0x69, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6d, 0x78, 0x73, 0x09, 0x09, 0x09, 0x6d, 0x78, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x72, 0x75, 0x65, 0x61, 0x70, 0x70, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x72, 0x75, 0x65, 0x64, 0x6f, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x62, 0x69, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x77, 0x65, 0x62, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x66, 0x64, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x75, 0x66, 0x64, 0x20, 0x75, 0x66, 0x64, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x69, 0x71, 0x2e, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x09, 0x09, 0x09, 0x75, 0x74, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x6d, 0x61, 0x6a, 0x69, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x75, 0x6d, 0x6a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x09, 0x09, 0x09, 0x09, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x77, 0x65, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x6f, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x75, 0x6f, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x2d, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x2d, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x2d, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2d, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x6f, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x6f, 0x70, 0x2d, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2d, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x63, 0x6d, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x63, 0x6d, 0x64, 0x2d, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x63, 0x78, 0x09, 0x09, 0x09, 0x09, 0x76, 0x63, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x64, 0x2d, 0x73, 0x74, 0x75, 0x64, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x2e, 0x76, 0x63, 0x61, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x69, 0x64, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x76, 0x69, 0x64, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x76, 0x73, 0x64, 0x20, 0x76, 0x73, 0x74, 0x20, 0x76, 0x73, 0x73, 0x20, 0x76, 0x73, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x61, 0x72, 0x79, 0x09, 0x09, 0x09, 0x76, 0x69, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x69, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x73, 0x66, 0x09, 0x09, 0x09, 0x09, 0x76, 0x73, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x73, 0x69, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x73, 0x6c, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x77, 0x6d, 0x6c, 0x63, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x6c, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x77, 0x6d, 0x6c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x63, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x6c, 0x73, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x74, 0x75, 0x72, 0x62, 0x6f, 0x09, 0x09, 0x09, 0x77, 0x74, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x66, 0x61, 0x2e, 0x77, 0x73, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x6d, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x6d, 0x66, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x6f, 0x6c, 0x66, 0x72, 0x61, 0x6d, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x6f, 0x6c, 0x66, 0x72, 0x61, 0x6d, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x6f, 0x6c, 0x66, 0x72, 0x61, 0x6d, 0x2e, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x09, 0x09, 0x09, 0x6e, 0x62, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x09, 0x09, 0x09, 0x77, 0x70, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x71, 0x64, 0x09, 0x09, 0x09, 0x09, 0x77, 0x71, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x72, 0x71, 0x2d, 0x68, 0x70, 0x33, 0x30, 0x30, 0x30, 0x2d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x74, 0x2e, 0x73, 0x74, 0x66, 0x09, 0x09, 0x09, 0x09, 0x73, 0x74, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x76, 0x2e, 0x63, 0x73, 0x70, 0x2b, 0x77, 0x62, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x76, 0x2e, 0x63, 0x73, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x76, 0x2e, 0x73, 0x73, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x61, 0x72, 0x61, 0x09, 0x09, 0x09, 0x09, 0x78, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x66, 0x64, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x66, 0x64, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x66, 0x64, 0x6c, 0x2e, 0x77, 0x65, 0x62, 0x66, 0x6f, 0x72, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x6d, 0x69, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x6d, 0x70, 0x69, 0x65, 0x2e, 0x63, 0x70, 0x6b, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x6d, 0x70, 0x69, 0x65, 0x2e, 0x64, 0x70, 0x6b, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x6d, 0x70, 0x69, 0x65, 0x2e, 0x70, 0x6c, 0x61, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x6d, 0x70, 0x69, 0x65, 0x2e, 0x70, 0x70, 0x6b, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x6d, 0x70, 0x69, 0x65, 0x2e, 0x78, 0x6c, 0x69, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x68, 0x76, 0x2d, 0x64, 0x69, 0x63, 0x09, 0x09, 0x09, 0x68, 0x76, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x68, 0x76, 0x2d, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x09, 0x09, 0x68, 0x76, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x68, 0x76, 0x2d, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x09, 0x09, 0x09, 0x68, 0x76, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x09, 0x09, 0x09, 0x6f, 0x73, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x6f, 0x73, 0x66, 0x70, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x6f, 0x73, 0x66, 0x70, 0x76, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2d, 0x73, 0x65, 0x74, 0x75, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x73, 0x6d, 0x61, 0x66, 0x2d, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x09, 0x09, 0x73, 0x61, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x73, 0x6d, 0x61, 0x66, 0x2d, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x09, 0x09, 0x73, 0x70, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x2d, 0x6e, 0x67, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x61, 0x6d, 0x61, 0x68, 0x61, 0x2e, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x2d, 0x75, 0x64, 0x70, 0x65, 0x6e, 0x63, 0x61, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x09, 0x09, 0x63, 0x6d, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x7a, 0x75, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x7a, 0x69, 0x72, 0x20, 0x7a, 0x69, 0x72, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x7a, 0x7a, 0x61, 0x7a, 0x7a, 0x2e, 0x64, 0x65, 0x63, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x7a, 0x61, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x78, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x76, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x71, 0x2d, 0x72, 0x74, 0x63, 0x70, 0x78, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x68, 0x6f, 0x69, 0x73, 0x70, 0x70, 0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x68, 0x6f, 0x69, 0x73, 0x70, 0x70, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x69, 0x64, 0x67, 0x65, 0x74, 0x09, 0x09, 0x09, 0x09, 0x77, 0x67, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x69, 0x6e, 0x68, 0x6c, 0x70, 0x09, 0x09, 0x09, 0x09, 0x68, 0x6c, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x69, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x6f, 0x72, 0x64, 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x35, 0x2e, 0x31, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x73, 0x64, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x77, 0x73, 0x64, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x77, 0x73, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x77, 0x73, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x37, 0x7a, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x37, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x62, 0x69, 0x77, 0x6f, 0x72, 0x64, 0x09, 0x09, 0x09, 0x09, 0x61, 0x62, 0x77, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x61, 0x63, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x6d, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x64, 0x69, 0x73, 0x6b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x09, 0x09, 0x09, 0x64, 0x6d, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x65, 0x2d, 0x62, 0x69, 0x6e, 0x09, 0x09, 0x09, 0x61, 0x61, 0x62, 0x20, 0x78, 0x33, 0x32, 0x20, 0x75, 0x33, 0x32, 0x20, 0x76, 0x6f, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x61, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x65, 0x2d, 0x73, 0x65, 0x67, 0x09, 0x09, 0x09, 0x61, 0x61, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x62, 0x63, 0x70, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x62, 0x63, 0x70, 0x69, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x62, 0x69, 0x74, 0x74, 0x6f, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x62, 0x6c, 0x6f, 0x72, 0x62, 0x09, 0x09, 0x09, 0x09, 0x62, 0x6c, 0x62, 0x20, 0x62, 0x6c, 0x6f, 0x72, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x62, 0x7a, 0x69, 0x70, 0x09, 0x09, 0x09, 0x09, 0x62, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x62, 0x7a, 0x69, 0x70, 0x32, 0x09, 0x09, 0x09, 0x09, 0x62, 0x7a, 0x32, 0x20, 0x62, 0x6f, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x62, 0x72, 0x09, 0x09, 0x09, 0x09, 0x63, 0x62, 0x72, 0x20, 0x63, 0x62, 0x61, 0x20, 0x63, 0x62, 0x74, 0x20, 0x63, 0x62, 0x7a, 0x20, 0x63, 0x62, 0x37, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x09, 0x09, 0x09, 0x09, 0x76, 0x63, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x66, 0x73, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x63, 0x66, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x68, 0x61, 0x74, 0x09, 0x09, 0x09, 0x09, 0x63, 0x68, 0x61, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x68, 0x65, 0x73, 0x73, 0x2d, 0x70, 0x67, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x70, 0x67, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x09, 0x09, 0x09, 0x6e, 0x73, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x70, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x63, 0x70, 0x69, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x63, 0x73, 0x68, 0x09, 0x09, 0x09, 0x09, 0x63, 0x73, 0x68, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x09, 0x09, 0x09, 0x64, 0x65, 0x62, 0x20, 0x75, 0x64, 0x65, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x67, 0x63, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x64, 0x67, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x09, 0x09, 0x09, 0x64, 0x69, 0x72, 0x20, 0x64, 0x63, 0x72, 0x20, 0x64, 0x78, 0x72, 0x20, 0x63, 0x73, 0x74, 0x20, 0x63, 0x63, 0x74, 0x20, 0x63, 0x78, 0x74, 0x20, 0x77, 0x33, 0x64, 0x20, 0x66, 0x67, 0x64, 0x20, 0x73, 0x77, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x6f, 0x6f, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x77, 0x61, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x74, 0x62, 0x6e, 0x63, 0x78, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x6e, 0x63, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x74, 0x62, 0x6f, 0x6f, 0x6b, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x64, 0x74, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x74, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x64, 0x76, 0x69, 0x09, 0x09, 0x09, 0x09, 0x64, 0x76, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x09, 0x09, 0x09, 0x09, 0x65, 0x76, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x65, 0x76, 0x61, 0x09, 0x09, 0x09, 0x09, 0x65, 0x76, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x62, 0x64, 0x66, 0x09, 0x09, 0x09, 0x09, 0x62, 0x64, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x64, 0x6f, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x6d, 0x61, 0x6b, 0x65, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x09, 0x09, 0x09, 0x67, 0x73, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x6c, 0x69, 0x62, 0x67, 0x72, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2d, 0x70, 0x73, 0x66, 0x09, 0x09, 0x09, 0x70, 0x73, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x6f, 0x74, 0x66, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x74, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x70, 0x63, 0x66, 0x09, 0x09, 0x09, 0x09, 0x70, 0x63, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x6e, 0x66, 0x09, 0x09, 0x09, 0x09, 0x73, 0x6e, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x65, 0x65, 0x64, 0x6f, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x75, 0x6e, 0x6f, 0x73, 0x2d, 0x6e, 0x65, 0x77, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x74, 0x74, 0x66, 0x09, 0x09, 0x09, 0x09, 0x74, 0x74, 0x66, 0x20, 0x74, 0x74, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x31, 0x09, 0x09, 0x09, 0x70, 0x66, 0x61, 0x20, 0x70, 0x66, 0x62, 0x20, 0x70, 0x66, 0x6d, 0x20, 0x61, 0x66, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x6f, 0x66, 0x66, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6f, 0x66, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x76, 0x66, 0x6f, 0x6e, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x72, 0x65, 0x65, 0x61, 0x72, 0x63, 0x09, 0x09, 0x09, 0x09, 0x61, 0x72, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x73, 0x68, 0x09, 0x09, 0x09, 0x73, 0x70, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x63, 0x61, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x67, 0x63, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x6c, 0x75, 0x6c, 0x78, 0x09, 0x09, 0x09, 0x09, 0x75, 0x6c, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x09, 0x09, 0x09, 0x09, 0x67, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x72, 0x61, 0x6d, 0x70, 0x73, 0x2d, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x67, 0x72, 0x61, 0x6d, 0x70, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x74, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x67, 0x74, 0x61, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x7a, 0x69, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x68, 0x64, 0x66, 0x09, 0x09, 0x09, 0x09, 0x68, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x2d, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x09, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x69, 0x73, 0x6f, 0x39, 0x36, 0x36, 0x30, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x09, 0x09, 0x09, 0x69, 0x73, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6a, 0x61, 0x76, 0x61, 0x2d, 0x6a, 0x6e, 0x6c, 0x70, 0x2d, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x6a, 0x6e, 0x6c, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6c, 0x61, 0x74, 0x65, 0x78, 0x09, 0x09, 0x09, 0x09, 0x6c, 0x61, 0x74, 0x65, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6c, 0x7a, 0x68, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x6c, 0x7a, 0x68, 0x20, 0x6c, 0x68, 0x61, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x69, 0x65, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x65, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x6f, 0x62, 0x69, 0x70, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x09, 0x09, 0x09, 0x70, 0x72, 0x63, 0x20, 0x6d, 0x6f, 0x62, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x09, 0x09, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x63, 0x75, 0x74, 0x09, 0x09, 0x09, 0x6c, 0x6e, 0x6b, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x64, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x7a, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x78, 0x62, 0x61, 0x70, 0x09, 0x09, 0x09, 0x09, 0x78, 0x62, 0x61, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x64, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x62, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x63, 0x61, 0x72, 0x64, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x63, 0x72, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x63, 0x6c, 0x69, 0x70, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6c, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x09, 0x09, 0x09, 0x65, 0x78, 0x65, 0x20, 0x64, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x20, 0x62, 0x61, 0x74, 0x20, 0x6d, 0x73, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x76, 0x69, 0x65, 0x77, 0x09, 0x09, 0x09, 0x6d, 0x76, 0x62, 0x20, 0x6d, 0x31, 0x33, 0x20, 0x6d, 0x31, 0x34, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x6d, 0x65, 0x74, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x66, 0x20, 0x77, 0x6d, 0x7a, 0x20, 0x65, 0x6d, 0x66, 0x20, 0x65, 0x6d, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6e, 0x79, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x09, 0x09, 0x09, 0x70, 0x75, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x73, 0x63, 0x64, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x09, 0x09, 0x09, 0x74, 0x72, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x77, 0x72, 0x69, 0x74, 0x65, 0x09, 0x09, 0x09, 0x09, 0x77, 0x72, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6e, 0x65, 0x74, 0x63, 0x64, 0x66, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x63, 0x20, 0x63, 0x64, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6e, 0x7a, 0x62, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x7a, 0x62, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x70, 0x6b, 0x63, 0x73, 0x31, 0x32, 0x09, 0x09, 0x09, 0x09, 0x70, 0x31, 0x32, 0x20, 0x70, 0x66, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x70, 0x6b, 0x63, 0x73, 0x37, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x09, 0x09, 0x70, 0x37, 0x62, 0x20, 0x73, 0x70, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x70, 0x6b, 0x63, 0x73, 0x37, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x72, 0x65, 0x71, 0x72, 0x65, 0x73, 0x70, 0x09, 0x09, 0x09, 0x70, 0x37, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x72, 0x61, 0x72, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x09, 0x09, 0x09, 0x72, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x72, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x09, 0x09, 0x72, 0x69, 0x73, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x68, 0x09, 0x09, 0x09, 0x09, 0x73, 0x68, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x73, 0x68, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x68, 0x6f, 0x63, 0x6b, 0x77, 0x61, 0x76, 0x65, 0x2d, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x09, 0x09, 0x09, 0x73, 0x77, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x09, 0x09, 0x09, 0x78, 0x61, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x71, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x71, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x74, 0x75, 0x66, 0x66, 0x69, 0x74, 0x09, 0x09, 0x09, 0x09, 0x73, 0x69, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x74, 0x75, 0x66, 0x66, 0x69, 0x74, 0x78, 0x09, 0x09, 0x09, 0x09, 0x73, 0x69, 0x74, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x75, 0x62, 0x72, 0x69, 0x70, 0x09, 0x09, 0x09, 0x09, 0x73, 0x72, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x76, 0x34, 0x63, 0x70, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x73, 0x76, 0x34, 0x63, 0x70, 0x69, 0x6f, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x73, 0x76, 0x34, 0x63, 0x72, 0x63, 0x09, 0x09, 0x09, 0x09, 0x73, 0x76, 0x34, 0x63, 0x72, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x33, 0x76, 0x6d, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x09, 0x09, 0x09, 0x74, 0x33, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x61, 0x64, 0x73, 0x09, 0x09, 0x09, 0x09, 0x67, 0x61, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x63, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x74, 0x63, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x65, 0x78, 0x09, 0x09, 0x09, 0x09, 0x74, 0x65, 0x78, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x65, 0x78, 0x2d, 0x74, 0x66, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x74, 0x66, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x65, 0x78, 0x69, 0x6e, 0x66, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x74, 0x65, 0x78, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x74, 0x65, 0x78, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x74, 0x67, 0x69, 0x66, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x62, 0x6a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x75, 0x73, 0x74, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x75, 0x73, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x77, 0x61, 0x69, 0x73, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x09, 0x09, 0x09, 0x73, 0x72, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x78, 0x35, 0x30, 0x39, 0x2d, 0x63, 0x61, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x09, 0x09, 0x09, 0x64, 0x65, 0x72, 0x20, 0x63, 0x72, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x78, 0x66, 0x69, 0x67, 0x09, 0x09, 0x09, 0x09, 0x66, 0x69, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x78, 0x6c, 0x69, 0x66, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x6c, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x78, 0x70, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x70, 0x69, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x78, 0x7a, 0x09, 0x09, 0x09, 0x09, 0x78, 0x7a, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x7a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x09, 0x09, 0x09, 0x09, 0x7a, 0x31, 0x20, 0x7a, 0x32, 0x20, 0x7a, 0x33, 0x20, 0x7a, 0x34, 0x20, 0x7a, 0x35, 0x20, 0x7a, 0x36, 0x20, 0x7a, 0x37, 0x20, 0x7a, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x34, 0x30, 0x30, 0x2d, 0x62, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x61, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x61, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x63, 0x61, 0x70, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x64, 0x69, 0x66, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x78, 0x64, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x65, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x70, 0x2d, 0x6e, 0x73, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x64, 0x69, 0x66, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x65, 0x6e, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x65, 0x6e, 0x63, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x78, 0x68, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2d, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x6d, 0x6c, 0x20, 0x78, 0x73, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x2d, 0x64, 0x74, 0x64, 0x09, 0x09, 0x09, 0x09, 0x64, 0x74, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x2d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x70, 0x61, 0x72, 0x73, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x0a, 0x23, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x70, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6f, 0x70, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x6f, 0x70, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x70, 0x72, 0x6f, 0x63, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x70, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x73, 0x6c, 0x74, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x73, 0x6c, 0x74, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x73, 0x70, 0x66, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x78, 0x73, 0x70, 0x66, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x76, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x78, 0x6d, 0x6c, 0x20, 0x78, 0x68, 0x76, 0x6d, 0x6c, 0x20, 0x78, 0x76, 0x6d, 0x6c, 0x20, 0x78, 0x76, 0x6d, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x79, 0x61, 0x6e, 0x67, 0x09, 0x09, 0x09, 0x09, 0x79, 0x61, 0x6e, 0x67, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x79, 0x69, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x79, 0x69, 0x6e, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x7a, 0x69, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7a, 0x69, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x31, 0x64, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x64, 0x2d, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x33, 0x32, 0x6b, 0x61, 0x64, 0x70, 0x63, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x33, 0x67, 0x70, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x33, 0x67, 0x70, 0x70, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x63, 0x33, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x64, 0x70, 0x63, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x64, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x6d, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x6d, 0x72, 0x2d, 0x77, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x6d, 0x72, 0x2d, 0x77, 0x62, 0x2b, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x73, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x74, 0x72, 0x61, 0x63, 0x2d, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x2d, 0x6c, 0x6f, 0x73, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x74, 0x72, 0x61, 0x63, 0x2d, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x61, 0x74, 0x72, 0x61, 0x63, 0x33, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x62, 0x61, 0x73, 0x69, 0x63, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x75, 0x20, 0x73, 0x6e, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x62, 0x76, 0x31, 0x36, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x62, 0x76, 0x33, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x6d, 0x6f, 0x64, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x63, 0x6e, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x31, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x6c, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x73, 0x72, 0x2d, 0x65, 0x73, 0x32, 0x30, 0x31, 0x31, 0x30, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x73, 0x72, 0x2d, 0x65, 0x73, 0x32, 0x30, 0x32, 0x30, 0x35, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x73, 0x72, 0x2d, 0x65, 0x73, 0x32, 0x30, 0x32, 0x32, 0x31, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x73, 0x72, 0x2d, 0x65, 0x73, 0x32, 0x30, 0x32, 0x32, 0x31, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x76, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x64, 0x76, 0x69, 0x34, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x61, 0x63, 0x33, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x2d, 0x71, 0x63, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x62, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x62, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x77, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x77, 0x62, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x76, 0x72, 0x63, 0x77, 0x62, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x66, 0x77, 0x64, 0x72, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x31, 0x39, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x32, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x33, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x36, 0x2d, 0x31, 0x36, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x36, 0x2d, 0x32, 0x34, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x36, 0x2d, 0x33, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x36, 0x2d, 0x34, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x39, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x39, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x39, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x37, 0x32, 0x39, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x73, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x73, 0x6d, 0x2d, 0x65, 0x66, 0x72, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x67, 0x73, 0x6d, 0x2d, 0x68, 0x72, 0x2d, 0x30, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x69, 0x6c, 0x62, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x69, 0x70, 0x2d, 0x6d, 0x72, 0x5f, 0x76, 0x32, 0x2e, 0x35, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x69, 0x73, 0x61, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6c, 0x31, 0x36, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6c, 0x32, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6c, 0x32, 0x34, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6c, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6c, 0x70, 0x63, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x69, 0x64, 0x69, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x64, 0x20, 0x6d, 0x69, 0x64, 0x69, 0x20, 0x6b, 0x61, 0x72, 0x20, 0x72, 0x6d, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2d, 0x78, 0x6d, 0x66, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x70, 0x34, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x34, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x70, 0x34, 0x61, 0x2d, 0x6c, 0x61, 0x74, 0x6d, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x70, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x70, 0x61, 0x2d, 0x72, 0x6f, 0x62, 0x75, 0x73, 0x74, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x67, 0x61, 0x20, 0x6d, 0x70, 0x32, 0x20, 0x6d, 0x70, 0x32, 0x61, 0x20, 0x6d, 0x70, 0x33, 0x20, 0x6d, 0x32, 0x61, 0x20, 0x6d, 0x33, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x34, 0x2d, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6d, 0x75, 0x73, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6f, 0x67, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x67, 0x61, 0x20, 0x6f, 0x67, 0x67, 0x20, 0x73, 0x70, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x6f, 0x70, 0x75, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x63, 0x6d, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x63, 0x6d, 0x61, 0x2d, 0x77, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x63, 0x6d, 0x75, 0x2d, 0x77, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x63, 0x6d, 0x75, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x73, 0x69, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x71, 0x63, 0x65, 0x6c, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x72, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x72, 0x74, 0x70, 0x2d, 0x65, 0x6e, 0x63, 0x2d, 0x61, 0x65, 0x73, 0x63, 0x6d, 0x31, 0x32, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x72, 0x74, 0x70, 0x2d, 0x6d, 0x69, 0x64, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x72, 0x74, 0x78, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x33, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x33, 0x6d, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x69, 0x6c, 0x6b, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x69, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x6d, 0x76, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x6d, 0x76, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x6d, 0x76, 0x2d, 0x71, 0x63, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x70, 0x2d, 0x6d, 0x69, 0x64, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x73, 0x70, 0x65, 0x65, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x74, 0x31, 0x34, 0x30, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x74, 0x33, 0x38, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x74, 0x6f, 0x6e, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x75, 0x65, 0x6d, 0x63, 0x6c, 0x69, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x75, 0x6c, 0x70, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x64, 0x76, 0x69, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6d, 0x72, 0x2d, 0x77, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x33, 0x67, 0x70, 0x70, 0x2e, 0x69, 0x75, 0x66, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x34, 0x73, 0x62, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x6b, 0x6f, 0x7a, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x65, 0x6c, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2e, 0x6e, 0x73, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6d, 0x6c, 0x65, 0x73, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6e, 0x73, 0x2e, 0x61, 0x6e, 0x70, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6e, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x31, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x61, 0x20, 0x75, 0x76, 0x76, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x2d, 0x77, 0x69, 0x6e, 0x64, 0x73, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6f, 0x6c, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6c, 0x6e, 0x61, 0x2e, 0x61, 0x64, 0x74, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x68, 0x65, 0x61, 0x61, 0x63, 0x2e, 0x31, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x68, 0x65, 0x61, 0x61, 0x63, 0x2e, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x6d, 0x6c, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x6d, 0x70, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x70, 0x6c, 0x32, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x70, 0x6c, 0x32, 0x78, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x70, 0x6c, 0x32, 0x7a, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6f, 0x6c, 0x62, 0x79, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x65, 0x2e, 0x31, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x72, 0x61, 0x09, 0x09, 0x09, 0x09, 0x09, 0x64, 0x72, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x74, 0x73, 0x09, 0x09, 0x09, 0x09, 0x09, 0x64, 0x74, 0x73, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x74, 0x73, 0x2e, 0x68, 0x64, 0x09, 0x09, 0x09, 0x09, 0x64, 0x74, 0x73, 0x68, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x76, 0x65, 0x72, 0x61, 0x64, 0x2e, 0x70, 0x6c, 0x6a, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x6e, 0x73, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x09, 0x09, 0x09, 0x09, 0x6c, 0x76, 0x70, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6c, 0x61, 0x79, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x79, 0x61, 0x09, 0x09, 0x70, 0x79, 0x61, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x2d, 0x78, 0x6d, 0x66, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x72, 0x74, 0x65, 0x6c, 0x2e, 0x76, 0x62, 0x6b, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x75, 0x65, 0x72, 0x61, 0x2e, 0x65, 0x63, 0x65, 0x6c, 0x70, 0x34, 0x38, 0x30, 0x30, 0x09, 0x09, 0x09, 0x65, 0x63, 0x65, 0x6c, 0x70, 0x34, 0x38, 0x30, 0x30, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x75, 0x65, 0x72, 0x61, 0x2e, 0x65, 0x63, 0x65, 0x6c, 0x70, 0x37, 0x34, 0x37, 0x30, 0x09, 0x09, 0x09, 0x65, 0x63, 0x65, 0x6c, 0x70, 0x37, 0x34, 0x37, 0x30, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x75, 0x65, 0x72, 0x61, 0x2e, 0x65, 0x63, 0x65, 0x6c, 0x70, 0x39, 0x36, 0x30, 0x30, 0x09, 0x09, 0x09, 0x65, 0x63, 0x65, 0x6c, 0x70, 0x39, 0x36, 0x30, 0x30, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x63, 0x74, 0x65, 0x6c, 0x2e, 0x73, 0x62, 0x63, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x71, 0x63, 0x65, 0x6c, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x68, 0x65, 0x74, 0x6f, 0x72, 0x65, 0x78, 0x2e, 0x33, 0x32, 0x6b, 0x61, 0x64, 0x70, 0x63, 0x6d, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x69, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x69, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x73, 0x65, 0x61, 0x6c, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x6d, 0x78, 0x2e, 0x63, 0x76, 0x73, 0x64, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x77, 0x65, 0x62, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x65, 0x62, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x61, 0x61, 0x63, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x61, 0x63, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x61, 0x69, 0x66, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x69, 0x66, 0x20, 0x61, 0x69, 0x66, 0x66, 0x20, 0x61, 0x69, 0x66, 0x63, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x63, 0x61, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x61, 0x66, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x66, 0x6c, 0x61, 0x63, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x61, 0x63, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x61, 0x74, 0x72, 0x6f, 0x73, 0x6b, 0x61, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6b, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x70, 0x65, 0x67, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x33, 0x75, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x61, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x61, 0x78, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x61, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x70, 0x6e, 0x2d, 0x72, 0x65, 0x61, 0x6c, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x72, 0x61, 0x6d, 0x20, 0x72, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x70, 0x6e, 0x2d, 0x72, 0x65, 0x61, 0x6c, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x09, 0x09, 0x09, 0x72, 0x6d, 0x70, 0x0a, 0x23, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x74, 0x74, 0x61, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x2d, 0x77, 0x61, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x61, 0x76, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2f, 0x78, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x6d, 0x0a, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x63, 0x64, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x64, 0x78, 0x0a, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x63, 0x69, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x69, 0x66, 0x0a, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x63, 0x6d, 0x64, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6d, 0x64, 0x66, 0x0a, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x63, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6d, 0x6c, 0x0a, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x63, 0x73, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x73, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x70, 0x64, 0x62, 0x0a, 0x63, 0x68, 0x65, 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x78, 0x2d, 0x78, 0x79, 0x7a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x79, 0x7a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x62, 0x6d, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x6d, 0x70, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x63, 0x67, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x67, 0x6d, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x66, 0x69, 0x74, 0x73, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x33, 0x66, 0x61, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x67, 0x33, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x67, 0x69, 0x66, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x69, 0x65, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x65, 0x66, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x32, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x70, 0x65, 0x67, 0x20, 0x6a, 0x70, 0x67, 0x20, 0x6a, 0x70, 0x65, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x6d, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x78, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6b, 0x74, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6b, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6e, 0x61, 0x70, 0x6c, 0x70, 0x73, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 0x6e, 0x67, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x62, 0x74, 0x69, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x74, 0x69, 0x66, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x70, 0x74, 0x69, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x67, 0x69, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x67, 0x69, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x76, 0x67, 0x20, 0x73, 0x76, 0x67, 0x7a, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x33, 0x38, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x69, 0x66, 0x66, 0x20, 0x74, 0x69, 0x66, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2d, 0x66, 0x78, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x09, 0x09, 0x09, 0x70, 0x73, 0x64, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6e, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x32, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x69, 0x20, 0x75, 0x76, 0x76, 0x69, 0x20, 0x75, 0x76, 0x67, 0x20, 0x75, 0x76, 0x76, 0x67, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x73, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x09, 0x73, 0x75, 0x62, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6a, 0x76, 0x75, 0x09, 0x09, 0x09, 0x09, 0x09, 0x64, 0x6a, 0x76, 0x75, 0x20, 0x64, 0x6a, 0x76, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x77, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x64, 0x77, 0x67, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x78, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x64, 0x78, 0x66, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x62, 0x69, 0x64, 0x73, 0x68, 0x65, 0x65, 0x74, 0x09, 0x09, 0x09, 0x09, 0x66, 0x62, 0x73, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x70, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x70, 0x78, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x73, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x73, 0x74, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x65, 0x64, 0x6d, 0x69, 0x63, 0x73, 0x2d, 0x6d, 0x6d, 0x72, 0x09, 0x09, 0x09, 0x6d, 0x6d, 0x72, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x75, 0x6a, 0x69, 0x78, 0x65, 0x72, 0x6f, 0x78, 0x2e, 0x65, 0x64, 0x6d, 0x69, 0x63, 0x73, 0x2d, 0x72, 0x6c, 0x63, 0x09, 0x09, 0x09, 0x72, 0x6c, 0x63, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x67, 0x62, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x69, 0x63, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x69, 0x78, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x64, 0x69, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x77, 0x64, 0x70, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x74, 0x2d, 0x66, 0x70, 0x78, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x70, 0x78, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x70, 0x6e, 0x67, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x73, 0x65, 0x61, 0x6c, 0x2e, 0x67, 0x69, 0x66, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x73, 0x65, 0x61, 0x6c, 0x2e, 0x6a, 0x70, 0x67, 0x0a, 0x23, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x76, 0x66, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x77, 0x62, 0x6d, 0x70, 0x09, 0x09, 0x09, 0x09, 0x77, 0x62, 0x6d, 0x70, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x78, 0x69, 0x66, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x69, 0x66, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x77, 0x65, 0x62, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x65, 0x62, 0x70, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x33, 0x64, 0x73, 0x09, 0x09, 0x09, 0x09, 0x09, 0x33, 0x64, 0x73, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x63, 0x6d, 0x75, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x09, 0x09, 0x09, 0x09, 0x72, 0x61, 0x73, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x63, 0x6d, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6d, 0x78, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x66, 0x72, 0x65, 0x65, 0x68, 0x61, 0x6e, 0x64, 0x09, 0x09, 0x09, 0x09, 0x66, 0x68, 0x20, 0x66, 0x68, 0x63, 0x20, 0x66, 0x68, 0x34, 0x20, 0x66, 0x68, 0x35, 0x20, 0x66, 0x68, 0x37, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x63, 0x6f, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x6d, 0x72, 0x73, 0x69, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x09, 0x09, 0x09, 0x09, 0x73, 0x69, 0x64, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x70, 0x63, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 0x63, 0x78, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x70, 0x69, 0x63, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 0x69, 0x63, 0x20, 0x70, 0x63, 0x74, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x61, 0x6e, 0x79, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x09, 0x70, 0x6e, 0x6d, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x09, 0x70, 0x62, 0x6d, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x67, 0x72, 0x61, 0x79, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x70, 0x67, 0x6d, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x70, 0x69, 0x78, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x09, 0x70, 0x70, 0x6d, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x72, 0x67, 0x62, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x67, 0x62, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x74, 0x67, 0x61, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x67, 0x61, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x78, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x62, 0x6d, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x78, 0x70, 0x69, 0x78, 0x6d, 0x61, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x70, 0x6d, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78, 0x2d, 0x78, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x64, 0x75, 0x6d, 0x70, 0x09, 0x09, 0x09, 0x09, 0x78, 0x77, 0x64, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x63, 0x70, 0x69, 0x6d, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x62, 0x6f, 0x64, 0x79, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2d, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2d, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x69, 0x6d, 0x64, 0x6e, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x72, 0x66, 0x63, 0x38, 0x32, 0x32, 0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6d, 0x6c, 0x20, 0x6d, 0x69, 0x6d, 0x65, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x69, 0x70, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x69, 0x70, 0x66, 0x72, 0x61, 0x67, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x69, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x69, 0x67, 0x65, 0x73, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x67, 0x73, 0x20, 0x69, 0x67, 0x65, 0x73, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x6d, 0x65, 0x73, 0x68, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x73, 0x68, 0x20, 0x6d, 0x65, 0x73, 0x68, 0x20, 0x73, 0x69, 0x6c, 0x6f, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x64, 0x61, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x64, 0x61, 0x65, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x77, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x64, 0x77, 0x66, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x6c, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x64, 0x2e, 0x33, 0x64, 0x6d, 0x6c, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x64, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x67, 0x64, 0x6c, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x73, 0x2d, 0x67, 0x64, 0x6c, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x73, 0x2e, 0x67, 0x64, 0x6c, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x74, 0x77, 0x09, 0x09, 0x09, 0x09, 0x09, 0x67, 0x74, 0x77, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x74, 0x73, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x74, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x61, 0x72, 0x61, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x70, 0x61, 0x72, 0x61, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x74, 0x75, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x74, 0x75, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x72, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x72, 0x6c, 0x20, 0x76, 0x72, 0x6d, 0x6c, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x78, 0x33, 0x64, 0x2b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x09, 0x09, 0x09, 0x09, 0x78, 0x33, 0x64, 0x62, 0x20, 0x78, 0x33, 0x64, 0x62, 0x7a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x78, 0x33, 0x64, 0x2b, 0x76, 0x72, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x33, 0x64, 0x76, 0x20, 0x78, 0x33, 0x64, 0x76, 0x7a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x78, 0x33, 0x64, 0x2b, 0x78, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x78, 0x33, 0x64, 0x20, 0x78, 0x33, 0x64, 0x7a, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x62, 0x79, 0x74, 0x65, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2d, 0x73, 0x65, 0x74, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x31, 0x64, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x64, 0x2d, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x09, 0x09, 0x09, 0x09, 0x61, 0x70, 0x70, 0x63, 0x61, 0x63, 0x68, 0x65, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x63, 0x73, 0x20, 0x69, 0x66, 0x62, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x73, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x73, 0x76, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x64, 0x6e, 0x73, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x63, 0x6d, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x66, 0x77, 0x64, 0x72, 0x65, 0x64, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x68, 0x74, 0x6d, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x6e, 0x33, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x33, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x78, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x64, 0x65, 0x66, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x69, 0x6e, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x66, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x2e, 0x72, 0x73, 0x74, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x72, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x67, 0x09, 0x09, 0x09, 0x09, 0x64, 0x73, 0x63, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x73, 0x79, 0x73, 0x2e, 0x6d, 0x73, 0x6d, 0x6c, 0x2d, 0x62, 0x61, 0x73, 0x69, 0x63, 0x2d, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x72, 0x65, 0x64, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x72, 0x66, 0x63, 0x38, 0x32, 0x32, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x72, 0x69, 0x63, 0x68, 0x74, 0x65, 0x78, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x72, 0x74, 0x66, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x72, 0x74, 0x70, 0x2d, 0x65, 0x6e, 0x63, 0x2d, 0x61, 0x65, 0x73, 0x63, 0x6d, 0x31, 0x32, 0x38, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x72, 0x74, 0x78, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x73, 0x67, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x67, 0x6d, 0x6c, 0x20, 0x73, 0x67, 0x6d, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x31, 0x34, 0x30, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x61, 0x62, 0x2d, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x09, 0x09, 0x09, 0x74, 0x73, 0x76, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x72, 0x6f, 0x66, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x20, 0x74, 0x72, 0x20, 0x72, 0x6f, 0x66, 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x6d, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x75, 0x72, 0x74, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x74, 0x6c, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x75, 0x6c, 0x70, 0x66, 0x65, 0x63, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x75, 0x72, 0x69, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x75, 0x72, 0x69, 0x20, 0x75, 0x72, 0x69, 0x73, 0x20, 0x75, 0x72, 0x6c, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x63, 0x61, 0x72, 0x64, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x63, 0x61, 0x72, 0x64, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x61, 0x62, 0x63, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x75, 0x72, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x2e, 0x64, 0x63, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x64, 0x63, 0x75, 0x72, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x2e, 0x73, 0x63, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x73, 0x63, 0x75, 0x72, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x75, 0x72, 0x6c, 0x2e, 0x6d, 0x63, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x63, 0x75, 0x72, 0x6c, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x73, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x09, 0x73, 0x75, 0x62, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x65, 0x73, 0x6d, 0x65, 0x72, 0x74, 0x65, 0x63, 0x2e, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x6c, 0x79, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x79, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x6d, 0x69, 0x2e, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x74, 0x6f, 0x72, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x78, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x76, 0x69, 0x7a, 0x09, 0x09, 0x09, 0x09, 0x67, 0x76, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x33, 0x64, 0x2e, 0x33, 0x64, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x33, 0x64, 0x6d, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x6e, 0x33, 0x64, 0x2e, 0x73, 0x70, 0x6f, 0x74, 0x09, 0x09, 0x09, 0x09, 0x73, 0x70, 0x6f, 0x74, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x6e, 0x65, 0x77, 0x73, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x63, 0x2e, 0x6e, 0x69, 0x74, 0x66, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6c, 0x61, 0x74, 0x65, 0x78, 0x2d, 0x7a, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x78, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x74, 0x32, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x69, 0x2e, 0x75, 0x72, 0x69, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x75, 0x65, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x75, 0x6e, 0x2e, 0x6a, 0x32, 0x6d, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x09, 0x09, 0x6a, 0x61, 0x64, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x74, 0x65, 0x63, 0x68, 0x2e, 0x6c, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x74, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x73, 0x69, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x73, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x77, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x77, 0x61, 0x70, 0x2e, 0x77, 0x6d, 0x6c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x6c, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x61, 0x73, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x20, 0x61, 0x73, 0x6d, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x63, 0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x20, 0x63, 0x63, 0x20, 0x63, 0x78, 0x78, 0x20, 0x63, 0x70, 0x70, 0x20, 0x68, 0x20, 0x68, 0x68, 0x20, 0x64, 0x69, 0x63, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x66, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x6e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x37, 0x37, 0x20, 0x66, 0x39, 0x30, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x6a, 0x61, 0x76, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x61, 0x76, 0x61, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x6f, 0x70, 0x6d, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x70, 0x6d, 0x6c, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x70, 0x61, 0x73, 0x63, 0x61, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 0x20, 0x70, 0x61, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x6e, 0x66, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6e, 0x66, 0x6f, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x73, 0x65, 0x74, 0x65, 0x78, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x74, 0x78, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x73, 0x66, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x66, 0x76, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x75, 0x75, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x09, 0x09, 0x09, 0x09, 0x09, 0x75, 0x75, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x76, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x09, 0x09, 0x09, 0x09, 0x76, 0x63, 0x73, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x2d, 0x76, 0x63, 0x61, 0x72, 0x64, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x63, 0x66, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x6d, 0x6c, 0x0a, 0x23, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x78, 0x6d, 0x6c, 0x2d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x70, 0x61, 0x72, 0x73, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x31, 0x64, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x64, 0x2d, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x33, 0x67, 0x70, 0x70, 0x09, 0x09, 0x09, 0x09, 0x09, 0x33, 0x67, 0x70, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x33, 0x67, 0x70, 0x70, 0x2d, 0x74, 0x74, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x33, 0x67, 0x70, 0x70, 0x32, 0x09, 0x09, 0x09, 0x09, 0x09, 0x33, 0x67, 0x32, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x62, 0x6d, 0x70, 0x65, 0x67, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x62, 0x74, 0x36, 0x35, 0x36, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x63, 0x65, 0x6c, 0x62, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x64, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x31, 0x09, 0x09, 0x09, 0x09, 0x09, 0x68, 0x32, 0x36, 0x31, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x33, 0x09, 0x09, 0x09, 0x09, 0x09, 0x68, 0x32, 0x36, 0x33, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x33, 0x2d, 0x31, 0x39, 0x39, 0x38, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x33, 0x2d, 0x32, 0x30, 0x30, 0x30, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x34, 0x09, 0x09, 0x09, 0x09, 0x09, 0x68, 0x32, 0x36, 0x34, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x34, 0x2d, 0x72, 0x63, 0x64, 0x6f, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x68, 0x32, 0x36, 0x34, 0x2d, 0x73, 0x76, 0x63, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x70, 0x67, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0x32, 0x30, 0x30, 0x30, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6a, 0x70, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6a, 0x70, 0x6d, 0x20, 0x6a, 0x70, 0x67, 0x6d, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x6a, 0x32, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6a, 0x32, 0x20, 0x6d, 0x6a, 0x70, 0x32, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x31, 0x73, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x32, 0x70, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x32, 0x74, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x34, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x34, 0x20, 0x6d, 0x70, 0x34, 0x76, 0x20, 0x6d, 0x70, 0x67, 0x34, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x34, 0x76, 0x2d, 0x65, 0x73, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x70, 0x65, 0x67, 0x20, 0x6d, 0x70, 0x67, 0x20, 0x6d, 0x70, 0x65, 0x20, 0x6d, 0x31, 0x76, 0x20, 0x6d, 0x32, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x65, 0x67, 0x34, 0x2d, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6d, 0x70, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6e, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x6f, 0x67, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6f, 0x67, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x74, 0x69, 0x6d, 0x65, 0x09, 0x09, 0x09, 0x09, 0x09, 0x71, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x72, 0x61, 0x77, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x72, 0x74, 0x70, 0x2d, 0x65, 0x6e, 0x63, 0x2d, 0x61, 0x65, 0x73, 0x63, 0x6d, 0x31, 0x32, 0x38, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x72, 0x74, 0x78, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x73, 0x6d, 0x70, 0x74, 0x65, 0x32, 0x39, 0x32, 0x6d, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x75, 0x6c, 0x70, 0x66, 0x65, 0x63, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x63, 0x31, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x63, 0x63, 0x74, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x68, 0x64, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x68, 0x20, 0x75, 0x76, 0x76, 0x68, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x6d, 0x20, 0x75, 0x76, 0x76, 0x6d, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x6d, 0x70, 0x34, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x70, 0x64, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x70, 0x20, 0x75, 0x76, 0x76, 0x70, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x73, 0x64, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x73, 0x20, 0x75, 0x76, 0x76, 0x73, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x65, 0x63, 0x65, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x76, 0x20, 0x75, 0x76, 0x76, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x76, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x76, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x2d, 0x74, 0x74, 0x73, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x6c, 0x6e, 0x61, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x2d, 0x74, 0x74, 0x73, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x64, 0x76, 0x62, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x09, 0x09, 0x09, 0x09, 0x64, 0x76, 0x62, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x66, 0x76, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x76, 0x74, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x6e, 0x73, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x66, 0x6f, 0x72, 0x75, 0x6d, 0x2e, 0x31, 0x64, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x2d, 0x31, 0x30, 0x31, 0x30, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x66, 0x6f, 0x72, 0x75, 0x6d, 0x2e, 0x31, 0x64, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x2d, 0x32, 0x30, 0x30, 0x35, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x66, 0x6f, 0x72, 0x75, 0x6d, 0x2e, 0x32, 0x64, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x2d, 0x31, 0x30, 0x31, 0x30, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x66, 0x6f, 0x72, 0x75, 0x6d, 0x2e, 0x32, 0x64, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x66, 0x65, 0x63, 0x2d, 0x32, 0x30, 0x30, 0x35, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x66, 0x6f, 0x72, 0x75, 0x6d, 0x2e, 0x74, 0x74, 0x73, 0x61, 0x76, 0x63, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x69, 0x70, 0x74, 0x76, 0x66, 0x6f, 0x72, 0x75, 0x6d, 0x2e, 0x74, 0x74, 0x73, 0x6d, 0x70, 0x65, 0x67, 0x32, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x70, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x75, 0x72, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x78, 0x75, 0x20, 0x6d, 0x34, 0x75, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6c, 0x61, 0x79, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x79, 0x76, 0x09, 0x09, 0x70, 0x79, 0x76, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x64, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6e, 0x6f, 0x6b, 0x69, 0x61, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x76, 0x6f, 0x69, 0x70, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x31, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x6d, 0x70, 0x65, 0x67, 0x34, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x73, 0x77, 0x66, 0x0a, 0x23, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x73, 0x65, 0x61, 0x6c, 0x2e, 0x6d, 0x6f, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x75, 0x76, 0x76, 0x75, 0x2e, 0x6d, 0x70, 0x34, 0x09, 0x09, 0x09, 0x09, 0x75, 0x76, 0x75, 0x20, 0x75, 0x76, 0x76, 0x75, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x76, 0x69, 0x76, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x69, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x77, 0x65, 0x62, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x65, 0x62, 0x6d, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x66, 0x34, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x34, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x66, 0x6c, 0x69, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x69, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x66, 0x6c, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6c, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x34, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x34, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x61, 0x74, 0x72, 0x6f, 0x73, 0x6b, 0x61, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6b, 0x76, 0x20, 0x6d, 0x6b, 0x33, 0x64, 0x20, 0x6d, 0x6b, 0x73, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x6e, 0x67, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6e, 0x67, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x61, 0x73, 0x66, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x73, 0x66, 0x20, 0x61, 0x73, 0x78, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x76, 0x6f, 0x62, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x6f, 0x62, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x76, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x6d, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x6d, 0x78, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x77, 0x76, 0x78, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 0x76, 0x78, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x76, 0x69, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x73, 0x67, 0x69, 0x2d, 0x6d, 0x6f, 0x76, 0x69, 0x65, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x6f, 0x76, 0x69, 0x65, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x2f, 0x78, 0x2d, 0x73, 0x6d, 0x76, 0x09, 0x09, 0x09, 0x09, 0x09, 0x73, 0x6d, 0x76, 0x0a, 0x78, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2f, 0x78, 0x2d, 0x63, 0x6f, 0x6f, 0x6c, 0x74, 0x61, 0x6c, 0x6b, 0x09, 0x09, 0x09, 0x09, 0x69, 0x63, 0x65, 0x0a }; unsigned int mime_types_len = 53051; ================================================ FILE: mime.types ================================================ # This file maps Internet media types to unique file extension(s). # Although created for httpd, this file is used by many software systems # and has been placed in the public domain for unlimited redisribution. # # The table below contains both registered and (common) unregistered types. # A type that has no unique extension can be ignored -- they are listed # here to guide configurations toward known types and to make it easier to # identify "new" types. File extensions are also commonly used to indicate # content languages and encodings, so choose them carefully. # # Internet media types should be registered as described in RFC 4288. # The registry is at . # # MIME type (lowercased) Extensions # ============================================ ========== # application/1d-interleaved-parityfec # application/3gpp-ims+xml # application/activemessage application/andrew-inset ez # application/applefile application/applixware aw application/atom+xml atom application/atomcat+xml atomcat # application/atomicmail application/atomsvc+xml atomsvc # application/auth-policy+xml # application/batch-smtp # application/beep+xml # application/calendar+xml # application/cals-1840 # application/ccmp+xml application/ccxml+xml ccxml application/cdmi-capability cdmia application/cdmi-container cdmic application/cdmi-domain cdmid application/cdmi-object cdmio application/cdmi-queue cdmiq # application/cea-2018+xml # application/cellml+xml # application/cfw # application/cnrp+xml # application/commonground # application/conference-info+xml # application/cpl+xml # application/csta+xml # application/cstadata+xml application/cu-seeme cu # application/cybercash application/davmount+xml davmount # application/dca-rft # application/dec-dx # application/dialog-info+xml # application/dicom # application/dns application/docbook+xml dbk # application/dskpp+xml application/dssc+der dssc application/dssc+xml xdssc # application/dvcs application/ecmascript ecma # application/edi-consent # application/edi-x12 # application/edifact application/emma+xml emma # application/epp+xml application/epub+zip epub # application/eshop # application/example application/exi exi # application/fastinfoset # application/fastsoap application/fb2 fb2 # application/fits application/font-tdpfr pfr # application/framework-attributes+xml application/gml+xml gml application/gpx+xml gpx application/gxf gxf # application/h224 # application/held+xml # application/http application/hyperstudio stk # application/ibe-key-request+xml # application/ibe-pkg-reply+xml # application/ibe-pp-data # application/iges # application/im-iscomposing+xml # application/index # application/index.cmd # application/index.obj # application/index.response # application/index.vnd application/inkml+xml ink inkml # application/iotp application/ipfix ipfix # application/ipp # application/isup application/java-archive jar application/java-serialized-object ser application/java-vm class application/javascript js application/json json application/jsonml+json jsonml # application/kpml-request+xml # application/kpml-response+xml application/lost+xml lostxml application/mac-binhex40 hqx application/mac-compactpro cpt # application/macwriteii application/mads+xml mads application/marc mrc application/marcxml+xml mrcx application/mathematica ma nb mb # application/mathml-content+xml # application/mathml-presentation+xml application/mathml+xml mathml # application/mbms-associated-procedure-description+xml # application/mbms-deregister+xml # application/mbms-envelope+xml # application/mbms-msk+xml # application/mbms-msk-response+xml # application/mbms-protection-description+xml # application/mbms-reception-report+xml # application/mbms-register+xml # application/mbms-register-response+xml # application/mbms-user-service-description+xml application/mbox mbox # application/media_control+xml application/mediaservercontrol+xml mscml application/metalink+xml metalink application/metalink4+xml meta4 application/mets+xml mets # application/mikey application/mods+xml mods # application/moss-keys # application/moss-signature # application/mosskey-data # application/mosskey-request application/mp21 m21 mp21 application/mp4 mp4s # application/mpeg4-generic # application/mpeg4-iod # application/mpeg4-iod-xmt # application/msc-ivr+xml # application/msc-mixer+xml application/msword doc dot application/mxf mxf # application/nasdata # application/news-checkgroups # application/news-groupinfo # application/news-transmission # application/nss # application/ocsp-request # application/ocsp-response application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy application/oda oda application/oebps-package+xml opf application/ogg ogx application/omdoc+xml omdoc application/onenote onetoc onetoc2 onetmp onepkg application/oxps oxps # application/parityfec application/patch-ops-error+xml xer application/pdf pdf application/pgp-encrypted pgp # application/pgp-keys application/pgp-signature asc sig application/pics-rules prf # application/pidf+xml # application/pidf-diff+xml application/pkcs10 p10 application/pkcs7-mime p7m p7c application/pkcs7-signature p7s application/pkcs8 p8 application/pkix-attr-cert ac application/pkix-cert cer application/pkix-crl crl application/pkix-pkipath pkipath application/pkixcmp pki application/pls+xml pls # application/poc-settings+xml application/postscript ai eps ps # application/prs.alvestrand.titrax-sheet application/prs.cww cww # application/prs.nprend # application/prs.plucker # application/prs.rdf-xml-crypt # application/prs.xsf+xml application/pskc+xml pskcxml # application/qsig application/rdf+xml rdf application/reginfo+xml rif application/relax-ng-compact-syntax rnc # application/remote-printing application/resource-lists+xml rl application/resource-lists-diff+xml rld # application/riscos # application/rlmi+xml application/rls-services+xml rs application/rpki-ghostbusters gbr application/rpki-manifest mft application/rpki-roa roa # application/rpki-updown application/rsd+xml rsd application/rss+xml rss application/rtf rtf # application/rtx # application/samlassertion+xml # application/samlmetadata+xml application/sbml+xml sbml application/scvp-cv-request scq application/scvp-cv-response scs application/scvp-vp-request spq application/scvp-vp-response spp application/sdp sdp # application/set-payment application/set-payment-initiation setpay # application/set-registration application/set-registration-initiation setreg # application/sgml # application/sgml-open-catalog application/shf+xml shf # application/sieve # application/simple-filter+xml # application/simple-message-summary # application/simplesymbolcontainer # application/slate # application/smil application/smil+xml smi smil # application/soap+fastinfoset # application/soap+xml application/sparql-query rq application/sparql-results+xml srx # application/spirits-event+xml application/srgs gram application/srgs+xml grxml application/sru+xml sru application/ssdl+xml ssdl application/ssml+xml ssml # application/tamp-apex-update # application/tamp-apex-update-confirm # application/tamp-community-update # application/tamp-community-update-confirm # application/tamp-error # application/tamp-sequence-adjust # application/tamp-sequence-adjust-confirm # application/tamp-status-query # application/tamp-status-response # application/tamp-update # application/tamp-update-confirm application/tei+xml tei teicorpus application/thraud+xml tfi # application/timestamp-query # application/timestamp-reply application/timestamped-data tsd # application/tve-trigger # application/ulpfec # application/vcard+xml # application/vemmi # application/vividence.scriptfile # application/vnd.3gpp.bsf+xml application/vnd.3gpp.pic-bw-large plb application/vnd.3gpp.pic-bw-small psb application/vnd.3gpp.pic-bw-var pvb # application/vnd.3gpp.sms # application/vnd.3gpp2.bcmcsinfo+xml # application/vnd.3gpp2.sms application/vnd.3gpp2.tcap tcap application/vnd.3m.post-it-notes pwn application/vnd.accpac.simply.aso aso application/vnd.accpac.simply.imp imp application/vnd.acucobol acu application/vnd.acucorp atc acutc application/vnd.adobe.air-application-installer-package+zip air application/vnd.adobe.formscentral.fcdt fcdt application/vnd.adobe.fxp fxp fxpl # application/vnd.adobe.partial-upload application/vnd.adobe.xdp+xml xdp application/vnd.adobe.xfdf xfdf # application/vnd.aether.imp # application/vnd.ah-barcode application/vnd.ahead.space ahead application/vnd.airzip.filesecure.azf azf application/vnd.airzip.filesecure.azs azs application/vnd.amazon.ebook azw application/vnd.americandynamics.acc acc application/vnd.amiga.ami ami # application/vnd.amundsen.maze+xml application/vnd.android.package-archive apk application/vnd.anser-web-certificate-issue-initiation cii application/vnd.anser-web-funds-transfer-initiation fti application/vnd.antix.game-component atx application/vnd.apple.installer+xml mpkg application/vnd.apple.mpegurl m3u8 # application/vnd.arastra.swi application/vnd.aristanetworks.swi swi application/vnd.astraea-software.iota iota application/vnd.audiograph aep # application/vnd.autopackage # application/vnd.avistar+xml application/vnd.blueice.multipass mpm # application/vnd.bluetooth.ep.oob application/vnd.bmi bmi application/vnd.businessobjects rep # application/vnd.cab-jscript # application/vnd.canon-cpdl # application/vnd.canon-lips # application/vnd.cendio.thinlinc.clientconf application/vnd.chemdraw+xml cdxml application/vnd.chipnuts.karaoke-mmd mmd application/vnd.cinderella cdy # application/vnd.cirpack.isdn-ext application/vnd.claymore cla application/vnd.cloanto.rp9 rp9 application/vnd.clonk.c4group c4g c4d c4f c4p c4u application/vnd.cluetrust.cartomobile-config c11amc application/vnd.cluetrust.cartomobile-config-pkg c11amz # application/vnd.collection+json # application/vnd.commerce-battelle application/vnd.commonspace csp application/vnd.contact.cmsg cdbcmsg application/vnd.cosmocaller cmc application/vnd.crick.clicker clkx application/vnd.crick.clicker.keyboard clkk application/vnd.crick.clicker.palette clkp application/vnd.crick.clicker.template clkt application/vnd.crick.clicker.wordbank clkw application/vnd.criticaltools.wbs+xml wbs application/vnd.ctc-posml pml # application/vnd.ctct.ws+xml # application/vnd.cups-pdf # application/vnd.cups-postscript application/vnd.cups-ppd ppd # application/vnd.cups-raster # application/vnd.cups-raw # application/vnd.curl application/vnd.curl.car car application/vnd.curl.pcurl pcurl # application/vnd.cybank application/vnd.dart dart application/vnd.data-vision.rdz rdz application/vnd.dece.data uvf uvvf uvd uvvd application/vnd.dece.ttml+xml uvt uvvt application/vnd.dece.unspecified uvx uvvx application/vnd.dece.zip uvz uvvz application/vnd.denovo.fcselayout-link fe_launch # application/vnd.dir-bi.plate-dl-nosuffix application/vnd.dna dna application/vnd.dolby.mlp mlp # application/vnd.dolby.mobile.1 # application/vnd.dolby.mobile.2 application/vnd.dpgraph dpg application/vnd.dreamfactory dfac application/vnd.ds-keypoint kpxx application/vnd.dvb.ait ait # application/vnd.dvb.dvbj # application/vnd.dvb.esgcontainer # application/vnd.dvb.ipdcdftnotifaccess # application/vnd.dvb.ipdcesgaccess # application/vnd.dvb.ipdcesgaccess2 # application/vnd.dvb.ipdcesgpdd # application/vnd.dvb.ipdcroaming # application/vnd.dvb.iptv.alfec-base # application/vnd.dvb.iptv.alfec-enhancement # application/vnd.dvb.notif-aggregate-root+xml # application/vnd.dvb.notif-container+xml # application/vnd.dvb.notif-generic+xml # application/vnd.dvb.notif-ia-msglist+xml # application/vnd.dvb.notif-ia-registration-request+xml # application/vnd.dvb.notif-ia-registration-response+xml # application/vnd.dvb.notif-init+xml # application/vnd.dvb.pfr application/vnd.dvb.service svc # application/vnd.dxr application/vnd.dynageo geo # application/vnd.easykaraoke.cdgdownload # application/vnd.ecdis-update application/vnd.ecowin.chart mag # application/vnd.ecowin.filerequest # application/vnd.ecowin.fileupdate # application/vnd.ecowin.series # application/vnd.ecowin.seriesrequest # application/vnd.ecowin.seriesupdate # application/vnd.emclient.accessrequest+xml application/vnd.enliven nml # application/vnd.eprints.data+xml application/vnd.epson.esf esf application/vnd.epson.msf msf application/vnd.epson.quickanime qam application/vnd.epson.salt slt application/vnd.epson.ssf ssf # application/vnd.ericsson.quickcall application/vnd.eszigno3+xml es3 et3 # application/vnd.etsi.aoc+xml # application/vnd.etsi.cug+xml # application/vnd.etsi.iptvcommand+xml # application/vnd.etsi.iptvdiscovery+xml # application/vnd.etsi.iptvprofile+xml # application/vnd.etsi.iptvsad-bc+xml # application/vnd.etsi.iptvsad-cod+xml # application/vnd.etsi.iptvsad-npvr+xml # application/vnd.etsi.iptvservice+xml # application/vnd.etsi.iptvsync+xml # application/vnd.etsi.iptvueprofile+xml # application/vnd.etsi.mcid+xml # application/vnd.etsi.overload-control-policy-dataset+xml # application/vnd.etsi.sci+xml # application/vnd.etsi.simservs+xml # application/vnd.etsi.tsl+xml # application/vnd.etsi.tsl.der # application/vnd.eudora.data application/vnd.ezpix-album ez2 application/vnd.ezpix-package ez3 # application/vnd.f-secure.mobile application/vnd.fdf fdf application/vnd.fdsn.mseed mseed application/vnd.fdsn.seed seed dataless # application/vnd.ffsns # application/vnd.fints application/vnd.flographit gph application/vnd.fluxtime.clip ftc # application/vnd.font-fontforge-sfd application/vnd.framemaker fm frame maker book application/vnd.frogans.fnc fnc application/vnd.frogans.ltf ltf application/vnd.fsc.weblaunch fsc application/vnd.fujitsu.oasys oas application/vnd.fujitsu.oasys2 oa2 application/vnd.fujitsu.oasys3 oa3 application/vnd.fujitsu.oasysgp fg5 application/vnd.fujitsu.oasysprs bh2 # application/vnd.fujixerox.art-ex # application/vnd.fujixerox.art4 # application/vnd.fujixerox.hbpl application/vnd.fujixerox.ddd ddd application/vnd.fujixerox.docuworks xdw application/vnd.fujixerox.docuworks.binder xbd # application/vnd.fut-misnet application/vnd.fuzzysheet fzs application/vnd.genomatix.tuxedo txd # application/vnd.geocube+xml application/vnd.geogebra.file ggb application/vnd.geogebra.tool ggt application/vnd.geometry-explorer gex gre application/vnd.geonext gxt application/vnd.geoplan g2w application/vnd.geospace g3w # application/vnd.globalplatform.card-content-mgt # application/vnd.globalplatform.card-content-mgt-response application/vnd.gmx gmx application/vnd.google-earth.kml+xml kml application/vnd.google-earth.kmz kmz application/vnd.grafeq gqf gqs # application/vnd.gridmp application/vnd.groove-account gac application/vnd.groove-help ghf application/vnd.groove-identity-message gim application/vnd.groove-injector grv application/vnd.groove-tool-message gtm application/vnd.groove-tool-template tpl application/vnd.groove-vcard vcg # application/vnd.hal+json application/vnd.hal+xml hal application/vnd.handheld-entertainment+xml zmm application/vnd.hbci hbci # application/vnd.hcl-bireports application/vnd.hhe.lesson-player les application/vnd.hp-hpgl hpgl application/vnd.hp-hpid hpid application/vnd.hp-hps hps application/vnd.hp-jlyt jlt application/vnd.hp-pcl pcl application/vnd.hp-pclxl pclxl # application/vnd.httphone application/vnd.hydrostatix.sof-data sfd-hdstx # application/vnd.hzn-3d-crossword # application/vnd.ibm.afplinedata # application/vnd.ibm.electronic-media application/vnd.ibm.minipay mpy application/vnd.ibm.modcap afp listafp list3820 application/vnd.ibm.rights-management irm application/vnd.ibm.secure-container sc application/vnd.iccprofile icc icm application/vnd.igloader igl application/vnd.immervision-ivp ivp application/vnd.immervision-ivu ivu # application/vnd.informedcontrol.rms+xml # application/vnd.informix-visionary # application/vnd.infotech.project # application/vnd.infotech.project+xml # application/vnd.innopath.wamp.notification application/vnd.insors.igm igm application/vnd.intercon.formnet xpw xpx application/vnd.intergeo i2g # application/vnd.intertrust.digibox # application/vnd.intertrust.nncp application/vnd.intu.qbo qbo application/vnd.intu.qfx qfx # application/vnd.iptc.g2.conceptitem+xml # application/vnd.iptc.g2.knowledgeitem+xml # application/vnd.iptc.g2.newsitem+xml # application/vnd.iptc.g2.newsmessage+xml # application/vnd.iptc.g2.packageitem+xml # application/vnd.iptc.g2.planningitem+xml application/vnd.ipunplugged.rcprofile rcprofile application/vnd.irepository.package+xml irp application/vnd.is-xpr xpr application/vnd.isac.fcs fcs application/vnd.jam jam # application/vnd.japannet-directory-service # application/vnd.japannet-jpnstore-wakeup # application/vnd.japannet-payment-wakeup # application/vnd.japannet-registration # application/vnd.japannet-registration-wakeup # application/vnd.japannet-setstore-wakeup # application/vnd.japannet-verification # application/vnd.japannet-verification-wakeup application/vnd.jcp.javame.midlet-rms rms application/vnd.jisp jisp application/vnd.joost.joda-archive joda application/vnd.kahootz ktz ktr application/vnd.kde.karbon karbon application/vnd.kde.kchart chrt application/vnd.kde.kformula kfo application/vnd.kde.kivio flw application/vnd.kde.kontour kon application/vnd.kde.kpresenter kpr kpt application/vnd.kde.kspread ksp application/vnd.kde.kword kwd kwt application/vnd.kenameaapp htke application/vnd.kidspiration kia application/vnd.kinar kne knp application/vnd.koan skp skd skt skm application/vnd.kodak-descriptor sse application/vnd.las.las+xml lasxml # application/vnd.liberty-request+xml application/vnd.llamagraphics.life-balance.desktop lbd application/vnd.llamagraphics.life-balance.exchange+xml lbe application/vnd.lotus-1-2-3 123 application/vnd.lotus-approach apr application/vnd.lotus-freelance pre application/vnd.lotus-notes nsf application/vnd.lotus-organizer org application/vnd.lotus-screencam scm application/vnd.lotus-wordpro lwp application/vnd.macports.portpkg portpkg # application/vnd.marlin.drm.actiontoken+xml # application/vnd.marlin.drm.conftoken+xml # application/vnd.marlin.drm.license+xml # application/vnd.marlin.drm.mdcf application/vnd.mcd mcd application/vnd.medcalcdata mc1 application/vnd.mediastation.cdkey cdkey # application/vnd.meridian-slingshot application/vnd.mfer mwf application/vnd.mfmp mfm application/vnd.micrografx.flo flo application/vnd.micrografx.igx igx application/vnd.mif mif # application/vnd.minisoft-hp3000-save # application/vnd.mitsubishi.misty-guard.trustweb application/vnd.mobius.daf daf application/vnd.mobius.dis dis application/vnd.mobius.mbk mbk application/vnd.mobius.mqy mqy application/vnd.mobius.msl msl application/vnd.mobius.plc plc application/vnd.mobius.txf txf application/vnd.mophun.application mpn application/vnd.mophun.certificate mpc # application/vnd.motorola.flexsuite # application/vnd.motorola.flexsuite.adsi # application/vnd.motorola.flexsuite.fis # application/vnd.motorola.flexsuite.gotap # application/vnd.motorola.flexsuite.kmr # application/vnd.motorola.flexsuite.ttc # application/vnd.motorola.flexsuite.wem # application/vnd.motorola.iprm application/vnd.mozilla.xul+xml xul application/vnd.ms-artgalry cil # application/vnd.ms-asf application/vnd.ms-cab-compressed cab # application/vnd.ms-color.iccprofile application/vnd.ms-excel xls xlm xla xlc xlt xlw application/vnd.ms-excel.addin.macroenabled.12 xlam application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb application/vnd.ms-excel.sheet.macroenabled.12 xlsm application/vnd.ms-excel.template.macroenabled.12 xltm application/vnd.ms-fontobject eot application/vnd.ms-htmlhelp chm application/vnd.ms-ims ims application/vnd.ms-lrm lrm # application/vnd.ms-office.activex+xml application/vnd.ms-officetheme thmx # application/vnd.ms-opentype # application/vnd.ms-package.obfuscated-opentype application/vnd.ms-pki.seccat cat application/vnd.ms-pki.stl stl # application/vnd.ms-playready.initiator+xml application/vnd.ms-powerpoint ppt pps pot application/vnd.ms-powerpoint.addin.macroenabled.12 ppam application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm application/vnd.ms-powerpoint.slide.macroenabled.12 sldm application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm application/vnd.ms-powerpoint.template.macroenabled.12 potm # application/vnd.ms-printing.printticket+xml application/vnd.ms-project mpp mpt # application/vnd.ms-tnef # application/vnd.ms-wmdrm.lic-chlg-req # application/vnd.ms-wmdrm.lic-resp # application/vnd.ms-wmdrm.meter-chlg-req # application/vnd.ms-wmdrm.meter-resp application/vnd.ms-word.document.macroenabled.12 docm application/vnd.ms-word.template.macroenabled.12 dotm application/vnd.ms-works wps wks wcm wdb application/vnd.ms-wpl wpl application/vnd.ms-xpsdocument xps application/vnd.mseq mseq # application/vnd.msign # application/vnd.multiad.creator # application/vnd.multiad.creator.cif # application/vnd.music-niff application/vnd.musician mus application/vnd.muvee.style msty application/vnd.mynfc taglet # application/vnd.ncd.control # application/vnd.ncd.reference # application/vnd.nervana # application/vnd.netfpx application/vnd.neurolanguage.nlu nlu application/vnd.nitf ntf nitf application/vnd.noblenet-directory nnd application/vnd.noblenet-sealer nns application/vnd.noblenet-web nnw # application/vnd.nokia.catalogs # application/vnd.nokia.conml+wbxml # application/vnd.nokia.conml+xml # application/vnd.nokia.isds-radio-presets # application/vnd.nokia.iptv.config+xml # application/vnd.nokia.landmark+wbxml # application/vnd.nokia.landmark+xml # application/vnd.nokia.landmarkcollection+xml # application/vnd.nokia.n-gage.ac+xml application/vnd.nokia.n-gage.data ngdat application/vnd.nokia.n-gage.symbian.install n-gage # application/vnd.nokia.ncd # application/vnd.nokia.pcd+wbxml # application/vnd.nokia.pcd+xml application/vnd.nokia.radio-preset rpst application/vnd.nokia.radio-presets rpss application/vnd.novadigm.edm edm application/vnd.novadigm.edx edx application/vnd.novadigm.ext ext # application/vnd.ntt-local.file-transfer # application/vnd.ntt-local.sip-ta_remote # application/vnd.ntt-local.sip-ta_tcp_stream application/vnd.oasis.opendocument.chart odc application/vnd.oasis.opendocument.chart-template otc application/vnd.oasis.opendocument.database odb application/vnd.oasis.opendocument.formula odf application/vnd.oasis.opendocument.formula-template odft application/vnd.oasis.opendocument.graphics odg application/vnd.oasis.opendocument.graphics-template otg application/vnd.oasis.opendocument.image odi application/vnd.oasis.opendocument.image-template oti application/vnd.oasis.opendocument.presentation odp application/vnd.oasis.opendocument.presentation-template otp application/vnd.oasis.opendocument.spreadsheet ods application/vnd.oasis.opendocument.spreadsheet-template ots application/vnd.oasis.opendocument.text odt application/vnd.oasis.opendocument.text-master odm application/vnd.oasis.opendocument.text-template ott application/vnd.oasis.opendocument.text-web oth # application/vnd.obn # application/vnd.oftn.l10n+json # application/vnd.oipf.contentaccessdownload+xml # application/vnd.oipf.contentaccessstreaming+xml # application/vnd.oipf.cspg-hexbinary # application/vnd.oipf.dae.svg+xml # application/vnd.oipf.dae.xhtml+xml # application/vnd.oipf.mippvcontrolmessage+xml # application/vnd.oipf.pae.gem # application/vnd.oipf.spdiscovery+xml # application/vnd.oipf.spdlist+xml # application/vnd.oipf.ueprofile+xml # application/vnd.oipf.userprofile+xml application/vnd.olpc-sugar xo # application/vnd.oma-scws-config # application/vnd.oma-scws-http-request # application/vnd.oma-scws-http-response # application/vnd.oma.bcast.associated-procedure-parameter+xml # application/vnd.oma.bcast.drm-trigger+xml # application/vnd.oma.bcast.imd+xml # application/vnd.oma.bcast.ltkm # application/vnd.oma.bcast.notification+xml # application/vnd.oma.bcast.provisioningtrigger # application/vnd.oma.bcast.sgboot # application/vnd.oma.bcast.sgdd+xml # application/vnd.oma.bcast.sgdu # application/vnd.oma.bcast.simple-symbol-container # application/vnd.oma.bcast.smartcard-trigger+xml # application/vnd.oma.bcast.sprov+xml # application/vnd.oma.bcast.stkm # application/vnd.oma.cab-address-book+xml # application/vnd.oma.cab-feature-handler+xml # application/vnd.oma.cab-pcc+xml # application/vnd.oma.cab-user-prefs+xml # application/vnd.oma.dcd # application/vnd.oma.dcdc application/vnd.oma.dd2+xml dd2 # application/vnd.oma.drm.risd+xml # application/vnd.oma.group-usage-list+xml # application/vnd.oma.pal+xml # application/vnd.oma.poc.detailed-progress-report+xml # application/vnd.oma.poc.final-report+xml # application/vnd.oma.poc.groups+xml # application/vnd.oma.poc.invocation-descriptor+xml # application/vnd.oma.poc.optimized-progress-report+xml # application/vnd.oma.push # application/vnd.oma.scidm.messages+xml # application/vnd.oma.xcap-directory+xml # application/vnd.omads-email+xml # application/vnd.omads-file+xml # application/vnd.omads-folder+xml # application/vnd.omaloc-supl-init application/vnd.openofficeorg.extension oxt # application/vnd.openxmlformats-officedocument.custom-properties+xml # application/vnd.openxmlformats-officedocument.customxmlproperties+xml # application/vnd.openxmlformats-officedocument.drawing+xml # application/vnd.openxmlformats-officedocument.drawingml.chart+xml # application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml # application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml # application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml # application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml # application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml # application/vnd.openxmlformats-officedocument.extended-properties+xml # application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml # application/vnd.openxmlformats-officedocument.presentationml.comments+xml # application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml # application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml # application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml application/vnd.openxmlformats-officedocument.presentationml.presentation pptx # application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml # application/vnd.openxmlformats-officedocument.presentationml.presprops+xml application/vnd.openxmlformats-officedocument.presentationml.slide sldx # application/vnd.openxmlformats-officedocument.presentationml.slide+xml # application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml # application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx # application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml # application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml # application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml # application/vnd.openxmlformats-officedocument.presentationml.tags+xml application/vnd.openxmlformats-officedocument.presentationml.template potx # application/vnd.openxmlformats-officedocument.presentationml.template.main+xml # application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx # application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx # application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml # application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml # application/vnd.openxmlformats-officedocument.theme+xml # application/vnd.openxmlformats-officedocument.themeoverride+xml # application/vnd.openxmlformats-officedocument.vmldrawing # application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml application/vnd.openxmlformats-officedocument.wordprocessingml.document docx # application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx # application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml # application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml # application/vnd.openxmlformats-package.core-properties+xml # application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml # application/vnd.openxmlformats-package.relationships+xml # application/vnd.quobject-quoxdocument # application/vnd.osa.netdeploy application/vnd.osgeo.mapguide.package mgp # application/vnd.osgi.bundle application/vnd.osgi.dp dp application/vnd.osgi.subsystem esa # application/vnd.otps.ct-kip+xml application/vnd.palm pdb pqa oprc # application/vnd.paos.xml application/vnd.pawaafile paw application/vnd.pg.format str application/vnd.pg.osasli ei6 # application/vnd.piaccess.application-licence application/vnd.picsel efif application/vnd.pmi.widget wg # application/vnd.poc.group-advertisement+xml application/vnd.pocketlearn plf application/vnd.powerbuilder6 pbd # application/vnd.powerbuilder6-s # application/vnd.powerbuilder7 # application/vnd.powerbuilder7-s # application/vnd.powerbuilder75 # application/vnd.powerbuilder75-s # application/vnd.preminet application/vnd.previewsystems.box box application/vnd.proteus.magazine mgz application/vnd.publishare-delta-tree qps application/vnd.pvi.ptid1 ptid # application/vnd.pwg-multiplexed # application/vnd.pwg-xhtml-print+xml # application/vnd.qualcomm.brew-app-res application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb # application/vnd.radisys.moml+xml # application/vnd.radisys.msml+xml # application/vnd.radisys.msml-audit+xml # application/vnd.radisys.msml-audit-conf+xml # application/vnd.radisys.msml-audit-conn+xml # application/vnd.radisys.msml-audit-dialog+xml # application/vnd.radisys.msml-audit-stream+xml # application/vnd.radisys.msml-conf+xml # application/vnd.radisys.msml-dialog+xml # application/vnd.radisys.msml-dialog-base+xml # application/vnd.radisys.msml-dialog-fax-detect+xml # application/vnd.radisys.msml-dialog-fax-sendrecv+xml # application/vnd.radisys.msml-dialog-group+xml # application/vnd.radisys.msml-dialog-speech+xml # application/vnd.radisys.msml-dialog-transform+xml # application/vnd.rainstor.data # application/vnd.rapid application/vnd.realvnc.bed bed application/vnd.recordare.musicxml mxl application/vnd.recordare.musicxml+xml musicxml # application/vnd.renlearn.rlprint application/vnd.rig.cryptonote cryptonote application/vnd.rim.cod cod application/vnd.rn-realmedia rm application/vnd.rn-realmedia-vbr rmvb application/vnd.route66.link66+xml link66 # application/vnd.rs-274x # application/vnd.ruckus.download # application/vnd.s3sms application/vnd.sailingtracker.track st # application/vnd.sbm.cid # application/vnd.sbm.mid2 # application/vnd.scribus # application/vnd.sealed.3df # application/vnd.sealed.csf # application/vnd.sealed.doc # application/vnd.sealed.eml # application/vnd.sealed.mht # application/vnd.sealed.net # application/vnd.sealed.ppt # application/vnd.sealed.tiff # application/vnd.sealed.xls # application/vnd.sealedmedia.softseal.html # application/vnd.sealedmedia.softseal.pdf application/vnd.seemail see application/vnd.sema sema application/vnd.semd semd application/vnd.semf semf application/vnd.shana.informed.formdata ifm application/vnd.shana.informed.formtemplate itp application/vnd.shana.informed.interchange iif application/vnd.shana.informed.package ipk application/vnd.simtech-mindmapper twd twds application/vnd.smaf mmf # application/vnd.smart.notebook application/vnd.smart.teacher teacher # application/vnd.software602.filler.form+xml # application/vnd.software602.filler.form-xml-zip application/vnd.solent.sdkm+xml sdkm sdkd application/vnd.spotfire.dxp dxp application/vnd.spotfire.sfs sfs # application/vnd.sss-cod # application/vnd.sss-dtf # application/vnd.sss-ntf application/vnd.stardivision.calc sdc application/vnd.stardivision.draw sda application/vnd.stardivision.impress sdd application/vnd.stardivision.math smf application/vnd.stardivision.writer sdw vor application/vnd.stardivision.writer-global sgl application/vnd.stepmania.package smzip application/vnd.stepmania.stepchart sm # application/vnd.street-stream application/vnd.sun.xml.calc sxc application/vnd.sun.xml.calc.template stc application/vnd.sun.xml.draw sxd application/vnd.sun.xml.draw.template std application/vnd.sun.xml.impress sxi application/vnd.sun.xml.impress.template sti application/vnd.sun.xml.math sxm application/vnd.sun.xml.writer sxw application/vnd.sun.xml.writer.global sxg application/vnd.sun.xml.writer.template stw # application/vnd.sun.wadl+xml application/vnd.sus-calendar sus susp application/vnd.svd svd # application/vnd.swiftview-ics application/vnd.symbian.install sis sisx application/vnd.syncml+xml xsm application/vnd.syncml.dm+wbxml bdm application/vnd.syncml.dm+xml xdm # application/vnd.syncml.dm.notification # application/vnd.syncml.ds.notification application/vnd.tao.intent-module-archive tao application/vnd.tcpdump.pcap pcap cap dmp application/vnd.tmobile-livetv tmo application/vnd.trid.tpt tpt application/vnd.triscape.mxs mxs application/vnd.trueapp tra # application/vnd.truedoc # application/vnd.ubisoft.webplayer application/vnd.ufdl ufd ufdl application/vnd.uiq.theme utz application/vnd.umajin umj application/vnd.unity unityweb application/vnd.uoml+xml uoml # application/vnd.uplanet.alert # application/vnd.uplanet.alert-wbxml # application/vnd.uplanet.bearer-choice # application/vnd.uplanet.bearer-choice-wbxml # application/vnd.uplanet.cacheop # application/vnd.uplanet.cacheop-wbxml # application/vnd.uplanet.channel # application/vnd.uplanet.channel-wbxml # application/vnd.uplanet.list # application/vnd.uplanet.list-wbxml # application/vnd.uplanet.listcmd # application/vnd.uplanet.listcmd-wbxml # application/vnd.uplanet.signal application/vnd.vcx vcx # application/vnd.vd-study # application/vnd.vectorworks # application/vnd.verimatrix.vcas # application/vnd.vidsoft.vidconference application/vnd.visio vsd vst vss vsw application/vnd.visionary vis # application/vnd.vividence.scriptfile application/vnd.vsf vsf # application/vnd.wap.sic # application/vnd.wap.slc application/vnd.wap.wbxml wbxml application/vnd.wap.wmlc wmlc application/vnd.wap.wmlscriptc wmlsc application/vnd.webturbo wtb # application/vnd.wfa.wsc # application/vnd.wmc # application/vnd.wmf.bootstrap # application/vnd.wolfram.mathematica # application/vnd.wolfram.mathematica.package application/vnd.wolfram.player nbp application/vnd.wordperfect wpd application/vnd.wqd wqd # application/vnd.wrq-hp3000-labelled application/vnd.wt.stf stf # application/vnd.wv.csp+wbxml # application/vnd.wv.csp+xml # application/vnd.wv.ssp+xml application/vnd.xara xar application/vnd.xfdl xfdl # application/vnd.xfdl.webform # application/vnd.xmi+xml # application/vnd.xmpie.cpkg # application/vnd.xmpie.dpkg # application/vnd.xmpie.plan # application/vnd.xmpie.ppkg # application/vnd.xmpie.xlim application/vnd.yamaha.hv-dic hvd application/vnd.yamaha.hv-script hvs application/vnd.yamaha.hv-voice hvp application/vnd.yamaha.openscoreformat osf application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg # application/vnd.yamaha.remote-setup application/vnd.yamaha.smaf-audio saf application/vnd.yamaha.smaf-phrase spf # application/vnd.yamaha.through-ngn # application/vnd.yamaha.tunnel-udpencap application/vnd.yellowriver-custom-menu cmp application/vnd.zul zir zirz application/vnd.zzazz.deck+xml zaz application/voicexml+xml vxml # application/vq-rtcpxr # application/watcherinfo+xml # application/whoispp-query # application/whoispp-response application/widget wgt application/winhlp hlp # application/wita # application/wordperfect5.1 application/wsdl+xml wsdl application/wspolicy+xml wspolicy application/x-7z-compressed 7z application/x-abiword abw application/x-ace-compressed ace # application/x-amf application/x-apple-diskimage dmg application/x-authorware-bin aab x32 u32 vox application/x-authorware-map aam application/x-authorware-seg aas application/x-bcpio bcpio application/x-bittorrent torrent application/x-blorb blb blorb application/x-bzip bz application/x-bzip2 bz2 boz application/x-cbr cbr cba cbt cbz cb7 application/x-cdlink vcd application/x-cfs-compressed cfs application/x-chat chat application/x-chess-pgn pgn application/x-conference nsc # application/x-compress application/x-cpio cpio application/x-csh csh application/x-debian-package deb udeb application/x-dgc-compressed dgc application/x-director dir dcr dxr cst cct cxt w3d fgd swa application/x-doom wad application/x-dtbncx+xml ncx application/x-dtbook+xml dtb application/x-dtbresource+xml res application/x-dvi dvi application/x-envoy evy application/x-eva eva application/x-font-bdf bdf # application/x-font-dos # application/x-font-framemaker application/x-font-ghostscript gsf # application/x-font-libgrx application/x-font-linux-psf psf application/x-font-otf otf application/x-font-pcf pcf application/x-font-snf snf # application/x-font-speedo # application/x-font-sunos-news application/x-font-ttf ttf ttc application/x-font-type1 pfa pfb pfm afm application/font-woff woff # application/x-font-vfont application/x-freearc arc application/x-futuresplash spl application/x-gca-compressed gca application/x-glulx ulx application/x-gnumeric gnumeric application/x-gramps-xml gramps application/x-gtar gtar # application/x-gzip application/x-hdf hdf application/x-install-instructions install application/x-iso9660-image iso application/x-java-jnlp-file jnlp application/x-latex latex application/x-lzh-compressed lzh lha application/x-mie mie application/x-mobipocket-ebook prc mobi application/x-ms-application application application/x-ms-shortcut lnk application/x-ms-wmd wmd application/x-ms-wmz wmz application/x-ms-xbap xbap application/x-msaccess mdb application/x-msbinder obd application/x-mscardfile crd application/x-msclip clp application/x-msdownload exe dll com bat msi application/x-msmediaview mvb m13 m14 application/x-msmetafile wmf wmz emf emz application/x-msmoney mny application/x-mspublisher pub application/x-msschedule scd application/x-msterminal trm application/x-mswrite wri application/x-netcdf nc cdf application/x-nzb nzb application/x-pkcs12 p12 pfx application/x-pkcs7-certificates p7b spc application/x-pkcs7-certreqresp p7r application/x-rar-compressed rar application/x-research-info-systems ris application/x-sh sh application/x-shar shar application/x-shockwave-flash swf application/x-silverlight-app xap application/x-sql sql application/x-stuffit sit application/x-stuffitx sitx application/x-subrip srt application/x-sv4cpio sv4cpio application/x-sv4crc sv4crc application/x-t3vm-image t3 application/x-tads gam application/x-tar tar application/x-tcl tcl application/x-tex tex application/x-tex-tfm tfm application/x-texinfo texinfo texi application/x-tgif obj application/x-ustar ustar application/x-wais-source src application/x-x509-ca-cert der crt application/x-xfig fig application/x-xliff+xml xlf application/x-xpinstall xpi application/x-xz xz application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 # application/x400-bp application/xaml+xml xaml # application/xcap-att+xml # application/xcap-caps+xml application/xcap-diff+xml xdf # application/xcap-el+xml # application/xcap-error+xml # application/xcap-ns+xml # application/xcon-conference-info-diff+xml # application/xcon-conference-info+xml application/xenc+xml xenc application/xhtml+xml xhtml xht # application/xhtml-voice+xml application/xml xml xsl application/xml-dtd dtd # application/xml-external-parsed-entity # application/xmpp+xml application/xop+xml xop application/xproc+xml xpl application/xslt+xml xslt application/xspf+xml xspf application/xv+xml mxml xhvml xvml xvm application/yang yang application/yin+xml yin application/zip zip # audio/1d-interleaved-parityfec # audio/32kadpcm # audio/3gpp # audio/3gpp2 # audio/ac3 audio/adpcm adp # audio/amr # audio/amr-wb # audio/amr-wb+ # audio/asc # audio/atrac-advanced-lossless # audio/atrac-x # audio/atrac3 audio/basic au snd # audio/bv16 # audio/bv32 # audio/clearmode # audio/cn # audio/dat12 # audio/dls # audio/dsr-es201108 # audio/dsr-es202050 # audio/dsr-es202211 # audio/dsr-es202212 # audio/dv # audio/dvi4 # audio/eac3 # audio/evrc # audio/evrc-qcp # audio/evrc0 # audio/evrc1 # audio/evrcb # audio/evrcb0 # audio/evrcb1 # audio/evrcwb # audio/evrcwb0 # audio/evrcwb1 # audio/example # audio/fwdred # audio/g719 # audio/g722 # audio/g7221 # audio/g723 # audio/g726-16 # audio/g726-24 # audio/g726-32 # audio/g726-40 # audio/g728 # audio/g729 # audio/g7291 # audio/g729d # audio/g729e # audio/gsm # audio/gsm-efr # audio/gsm-hr-08 # audio/ilbc # audio/ip-mr_v2.5 # audio/isac # audio/l16 # audio/l20 # audio/l24 # audio/l8 # audio/lpc audio/midi mid midi kar rmi # audio/mobile-xmf audio/mp4 mp4a # audio/mp4a-latm # audio/mpa # audio/mpa-robust audio/mpeg mpga mp2 mp2a mp3 m2a m3a # audio/mpeg4-generic # audio/musepack audio/ogg oga ogg spx # audio/opus # audio/parityfec # audio/pcma # audio/pcma-wb # audio/pcmu-wb # audio/pcmu # audio/prs.sid # audio/qcelp # audio/red # audio/rtp-enc-aescm128 # audio/rtp-midi # audio/rtx audio/s3m s3m audio/silk sil # audio/smv # audio/smv0 # audio/smv-qcp # audio/sp-midi # audio/speex # audio/t140c # audio/t38 # audio/telephone-event # audio/tone # audio/uemclip # audio/ulpfec # audio/vdvi # audio/vmr-wb # audio/vnd.3gpp.iufp # audio/vnd.4sb # audio/vnd.audiokoz # audio/vnd.celp # audio/vnd.cisco.nse # audio/vnd.cmles.radio-events # audio/vnd.cns.anp1 # audio/vnd.cns.inf1 audio/vnd.dece.audio uva uvva audio/vnd.digital-winds eol # audio/vnd.dlna.adts # audio/vnd.dolby.heaac.1 # audio/vnd.dolby.heaac.2 # audio/vnd.dolby.mlp # audio/vnd.dolby.mps # audio/vnd.dolby.pl2 # audio/vnd.dolby.pl2x # audio/vnd.dolby.pl2z # audio/vnd.dolby.pulse.1 audio/vnd.dra dra audio/vnd.dts dts audio/vnd.dts.hd dtshd # audio/vnd.dvb.file # audio/vnd.everad.plj # audio/vnd.hns.audio audio/vnd.lucent.voice lvp audio/vnd.ms-playready.media.pya pya # audio/vnd.nokia.mobile-xmf # audio/vnd.nortel.vbk audio/vnd.nuera.ecelp4800 ecelp4800 audio/vnd.nuera.ecelp7470 ecelp7470 audio/vnd.nuera.ecelp9600 ecelp9600 # audio/vnd.octel.sbc # audio/vnd.qcelp # audio/vnd.rhetorex.32kadpcm audio/vnd.rip rip # audio/vnd.sealedmedia.softseal.mpeg # audio/vnd.vmx.cvsd # audio/vorbis # audio/vorbis-config audio/webm weba audio/x-aac aac audio/x-aiff aif aiff aifc audio/x-caf caf audio/x-flac flac audio/x-matroska mka audio/x-mpegurl m3u audio/x-ms-wax wax audio/x-ms-wma wma audio/x-pn-realaudio ram ra audio/x-pn-realaudio-plugin rmp # audio/x-tta audio/x-wav wav audio/xm xm chemical/x-cdx cdx chemical/x-cif cif chemical/x-cmdf cmdf chemical/x-cml cml chemical/x-csml csml # chemical/x-pdb chemical/x-xyz xyz image/bmp bmp image/cgm cgm # image/example # image/fits image/g3fax g3 image/gif gif image/ief ief # image/jp2 image/jpeg jpeg jpg jpe # image/jpm # image/jpx image/ktx ktx # image/naplps image/png png image/prs.btif btif # image/prs.pti image/sgi sgi image/svg+xml svg svgz # image/t38 image/tiff tiff tif # image/tiff-fx image/vnd.adobe.photoshop psd # image/vnd.cns.inf2 image/vnd.dece.graphic uvi uvvi uvg uvvg image/vnd.dvb.subtitle sub image/vnd.djvu djvu djv image/vnd.dwg dwg image/vnd.dxf dxf image/vnd.fastbidsheet fbs image/vnd.fpx fpx image/vnd.fst fst image/vnd.fujixerox.edmics-mmr mmr image/vnd.fujixerox.edmics-rlc rlc # image/vnd.globalgraphics.pgb # image/vnd.microsoft.icon # image/vnd.mix image/vnd.ms-modi mdi image/vnd.ms-photo wdp image/vnd.net-fpx npx # image/vnd.radiance # image/vnd.sealed.png # image/vnd.sealedmedia.softseal.gif # image/vnd.sealedmedia.softseal.jpg # image/vnd.svf image/vnd.wap.wbmp wbmp image/vnd.xiff xif image/webp webp image/x-3ds 3ds image/x-cmu-raster ras image/x-cmx cmx image/x-freehand fh fhc fh4 fh5 fh7 image/x-icon ico image/x-mrsid-image sid image/x-pcx pcx image/x-pict pic pct image/x-portable-anymap pnm image/x-portable-bitmap pbm image/x-portable-graymap pgm image/x-portable-pixmap ppm image/x-rgb rgb image/x-tga tga image/x-xbitmap xbm image/x-xpixmap xpm image/x-xwindowdump xwd # message/cpim # message/delivery-status # message/disposition-notification # message/example # message/external-body # message/feedback-report # message/global # message/global-delivery-status # message/global-disposition-notification # message/global-headers # message/http # message/imdn+xml # message/news # message/partial message/rfc822 eml mime # message/s-http # message/sip # message/sipfrag # message/tracking-status # message/vnd.si.simp # model/example model/iges igs iges model/mesh msh mesh silo model/vnd.collada+xml dae model/vnd.dwf dwf # model/vnd.flatland.3dml model/vnd.gdl gdl # model/vnd.gs-gdl # model/vnd.gs.gdl model/vnd.gtw gtw # model/vnd.moml+xml model/vnd.mts mts # model/vnd.parasolid.transmit.binary # model/vnd.parasolid.transmit.text model/vnd.vtu vtu model/vrml wrl vrml model/x3d+binary x3db x3dbz model/x3d+vrml x3dv x3dvz model/x3d+xml x3d x3dz # multipart/alternative # multipart/appledouble # multipart/byteranges # multipart/digest # multipart/encrypted # multipart/example # multipart/form-data # multipart/header-set # multipart/mixed # multipart/parallel # multipart/related # multipart/report # multipart/signed # multipart/voice-message # text/1d-interleaved-parityfec text/cache-manifest appcache text/calendar ics ifb text/css css text/csv csv # text/directory # text/dns # text/ecmascript # text/enriched # text/example # text/fwdred text/html html htm # text/javascript text/n3 n3 # text/parityfec text/plain txt text conf def list log in # text/prs.fallenstein.rst text/prs.lines.tag dsc # text/vnd.radisys.msml-basic-layout # text/red # text/rfc822-headers text/richtext rtx # text/rtf # text/rtp-enc-aescm128 # text/rtx text/sgml sgml sgm # text/t140 text/tab-separated-values tsv text/troff t tr roff man me ms text/turtle ttl # text/ulpfec text/uri-list uri uris urls text/vcard vcard # text/vnd.abc text/vnd.curl curl text/vnd.curl.dcurl dcurl text/vnd.curl.scurl scurl text/vnd.curl.mcurl mcurl # text/vnd.dmclientscript text/vnd.dvb.subtitle sub # text/vnd.esmertec.theme-descriptor text/vnd.fly fly text/vnd.fmi.flexstor flx text/vnd.graphviz gv text/vnd.in3d.3dml 3dml text/vnd.in3d.spot spot # text/vnd.iptc.newsml # text/vnd.iptc.nitf # text/vnd.latex-z # text/vnd.motorola.reflex # text/vnd.ms-mediapackage # text/vnd.net2phone.commcenter.command # text/vnd.si.uricatalogue text/vnd.sun.j2me.app-descriptor jad # text/vnd.trolltech.linguist # text/vnd.wap.si # text/vnd.wap.sl text/vnd.wap.wml wml text/vnd.wap.wmlscript wmls text/x-asm s asm text/x-c c cc cxx cpp h hh dic text/x-fortran f for f77 f90 text/x-java-source java text/x-opml opml text/x-pascal p pas text/x-nfo nfo text/x-setext etx text/x-sfv sfv text/x-uuencode uu text/x-vcalendar vcs text/x-vcard vcf # text/xml # text/xml-external-parsed-entity # video/1d-interleaved-parityfec video/3gpp 3gp # video/3gpp-tt video/3gpp2 3g2 # video/bmpeg # video/bt656 # video/celb # video/dv # video/example video/h261 h261 video/h263 h263 # video/h263-1998 # video/h263-2000 video/h264 h264 # video/h264-rcdo # video/h264-svc video/jpeg jpgv # video/jpeg2000 video/jpm jpm jpgm video/mj2 mj2 mjp2 # video/mp1s # video/mp2p # video/mp2t video/mp4 mp4 mp4v mpg4 # video/mp4v-es video/mpeg mpeg mpg mpe m1v m2v # video/mpeg4-generic # video/mpv # video/nv video/ogg ogv # video/parityfec # video/pointer video/quicktime qt mov # video/raw # video/rtp-enc-aescm128 # video/rtx # video/smpte292m # video/ulpfec # video/vc1 # video/vnd.cctv video/vnd.dece.hd uvh uvvh video/vnd.dece.mobile uvm uvvm # video/vnd.dece.mp4 video/vnd.dece.pd uvp uvvp video/vnd.dece.sd uvs uvvs video/vnd.dece.video uvv uvvv # video/vnd.directv.mpeg # video/vnd.directv.mpeg-tts # video/vnd.dlna.mpeg-tts video/vnd.dvb.file dvb video/vnd.fvt fvt # video/vnd.hns.video # video/vnd.iptvforum.1dparityfec-1010 # video/vnd.iptvforum.1dparityfec-2005 # video/vnd.iptvforum.2dparityfec-1010 # video/vnd.iptvforum.2dparityfec-2005 # video/vnd.iptvforum.ttsavc # video/vnd.iptvforum.ttsmpeg2 # video/vnd.motorola.video # video/vnd.motorola.videop video/vnd.mpegurl mxu m4u video/vnd.ms-playready.media.pyv pyv # video/vnd.nokia.interleaved-multimedia # video/vnd.nokia.videovoip # video/vnd.objectvideo # video/vnd.sealed.mpeg1 # video/vnd.sealed.mpeg4 # video/vnd.sealed.swf # video/vnd.sealedmedia.softseal.mov video/vnd.uvvu.mp4 uvu uvvu video/vnd.vivo viv video/webm webm video/x-f4v f4v video/x-fli fli video/x-flv flv video/x-m4v m4v video/x-matroska mkv mk3d mks video/x-mng mng video/x-ms-asf asf asx video/x-ms-vob vob video/x-ms-wm wm video/x-ms-wmv wmv video/x-ms-wmx wmx video/x-ms-wvx wvx video/x-msvideo avi video/x-sgi-movie movie video/x-smv smv x-conference/x-cooltalk ice ================================================ FILE: mtproto-client.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Nikolay Durov, Andrey Lopatin 2012-2013 Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #ifdef WIN32 #include #else #include #include #include #include #include #endif #include "crypto/rand.h" #include "crypto/rsa_pem.h" #include "crypto/sha.h" //#include "telegram.h" #include "queries.h" //#include "loop.h" #include "tgl-structures.h" #include "tgl-binlog.h" #include "auto.h" #include "auto/auto-types.h" #include "auto/auto-skip.h" #include "tgl.h" #include "mtproto-client.h" #include "tools.h" #include "tree.h" #include "updates.h" #include "mtproto-utils.h" #include "auto.h" #include "tgl-methods-in.h" #include "mtproto-common.h" #define MAX_NET_RES (1L << 16) //extern int log_level; static long long generate_next_msg_id (struct tgl_state *TLS, struct tgl_dc *DC, struct tgl_session *S); static double get_server_time (struct tgl_dc *DC); // for statistic only static int total_packets_sent; static long long total_data_sent; static int rpc_execute (struct tgl_state *TLS, struct connection *c, int op, int len); static int rpc_becomes_ready (struct tgl_state *TLS, struct connection *c); static int rpc_close (struct tgl_state *TLS, struct connection *c); static double get_utime (int clock_id) { struct timespec T; tgl_my_clock_gettime (clock_id, &T); return T.tv_sec + (double) T.tv_nsec * 1e-9; } #define MAX_RESPONSE_SIZE (1L << 24) static TGLC_rsa *rsa_load_public_key (struct tgl_state *TLS, const char *public_key_name) { FILE *f = fopen (public_key_name, "r"); if (f == NULL) { vlogprintf (E_WARNING, "Couldn't open public key file: %s\n", public_key_name); return NULL; } TGLC_rsa *res = TGLC_pem_read_RSAPublicKey (f); fclose (f); if (res == NULL) { vlogprintf (E_WARNING, "TGLC_pem_read_RSAPublicKey returns NULL.\n"); return NULL; } vlogprintf (E_NOTICE, "public key '%s' loaded successfully\n", public_key_name); return res; } /* * * UNAUTHORIZED (DH KEY EXCHANGE) PROTOCOL PART * */ #define ENCRYPT_BUFFER_INTS 16384 static int encrypt_buffer[ENCRYPT_BUFFER_INTS]; #define DECRYPT_BUFFER_INTS 16384 static int decrypt_buffer[ENCRYPT_BUFFER_INTS]; static int encrypt_packet_buffer (struct tgl_state *TLS, struct tgl_dc *DC) { TGLC_rsa *key = TLS->rsa_key_loaded[DC->rsa_key_idx]; return tgl_pad_rsa_encrypt (TLS, (char *) packet_buffer, (packet_ptr - packet_buffer) * 4, (char *) encrypt_buffer, ENCRYPT_BUFFER_INTS * 4, TGLC_rsa_n (key), TGLC_rsa_e (key)); } static int encrypt_packet_buffer_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32]) { tgl_init_aes_unauth (server_nonce, hidden_client_nonce, 1); return tgl_pad_aes_encrypt ((char *) packet_buffer, (packet_ptr - packet_buffer) * 4, (char *) encrypt_buffer, ENCRYPT_BUFFER_INTS * 4); } // // Used in unauthorized part of protocol // static int rpc_send_packet (struct tgl_state *TLS, struct connection *c) { static struct { long long auth_key_id; long long out_msg_id; int msg_len; } unenc_msg_header; int len = (packet_ptr - packet_buffer) * 4; TLS->net_methods->incr_out_packet_num (c); struct tgl_dc *DC = TLS->net_methods->get_dc (c); struct tgl_session *S = TLS->net_methods->get_session (c); unenc_msg_header.out_msg_id = generate_next_msg_id (TLS, DC, S); unenc_msg_header.msg_len = len; int total_len = len + 20; assert (total_len > 0 && !(total_len & 0xfc000003)); total_len >>= 2; vlogprintf (E_DEBUG, "writing packet: total_len = %d, len = %d\n", total_len, len); if (total_len < 0x7f) { assert (TLS->net_methods->write_out (c, &total_len, 1) == 1); } else { total_len = (total_len << 8) | 0x7f; assert (TLS->net_methods->write_out (c, &total_len, 4) == 4); } TLS->net_methods->write_out (c, &unenc_msg_header, 20); TLS->net_methods->write_out (c, packet_buffer, len); TLS->net_methods->flush_out (c); total_packets_sent ++; total_data_sent += total_len; return 1; } static int rpc_send_message (struct tgl_state *TLS, struct connection *c, void *data, int len) { assert (len > 0 && !(len & 0xfc000003)); int total_len = len >> 2; if (total_len < 0x7f) { assert (TLS->net_methods->write_out (c, &total_len, 1) == 1); } else { total_len = (total_len << 8) | 0x7f; assert (TLS->net_methods->write_out (c, &total_len, 4) == 4); } TLS->net_methods->incr_out_packet_num (c); assert (TLS->net_methods->write_out (c, data, len) == len); TLS->net_methods->flush_out (c); total_packets_sent ++; total_data_sent += total_len; return 1; } // // State machine. See description at // https://core.telegram.org/mtproto/auth_key // static int check_unauthorized_header (struct tgl_state *TLS) { long long auth_key_id = fetch_long (); if (auth_key_id) { vlogprintf (E_ERROR, "ERROR: auth_key_id should be NULL\n"); return -1; } fetch_long (); // msg_id int len = fetch_int (); if (len != 4 * (in_end - in_ptr)) { vlogprintf (E_ERROR, "ERROR: length mismatch\n"); return -1; } return 0; } /* {{{ REQ_PQ */ // req_pq#60469778 nonce:int128 = ResPQ static int send_req_pq_packet (struct tgl_state *TLS, struct connection *c) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); assert (DC->state == st_init); tglt_secure_random (DC->nonce, 16); clear_packet (); out_int (CODE_req_pq); out_ints ((int *)DC->nonce, 4); rpc_send_packet (TLS, c); DC->state = st_reqpq_sent; return 1; } // req_pq#60469778 nonce:int128 = ResPQ static int send_req_pq_temp_packet (struct tgl_state *TLS, struct connection *c) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); assert (DC->state == st_authorized); tglt_secure_random (DC->nonce, 16); clear_packet (); out_int (CODE_req_pq); out_ints ((int *)DC->nonce, 4); rpc_send_packet (TLS, c); DC->state = st_reqpq_sent_temp; return 1; } /* }}} */ /* {{{ REQ DH */ // req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params; // p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data; // p_q_inner_data_temp#3c6a84d4 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data; static void send_req_dh_packet (struct tgl_state *TLS, struct connection *c, TGLC_bn *pq, int temp_key) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); TGLC_bn *p = TGLC_bn_new (); TGLC_bn *q = TGLC_bn_new (); assert (bn_factorize (pq, p, q) >= 0); clear_packet (); packet_ptr += 5; out_int (temp_key ? CODE_p_q_inner_data_temp : CODE_p_q_inner_data); out_bignum (pq); out_bignum (p); out_bignum (q); out_ints ((int *) DC->nonce, 4); out_ints ((int *) DC->server_nonce, 4); tglt_secure_random (DC->new_nonce, 32); out_ints ((int *) DC->new_nonce, 8); if (temp_key) { out_int (TLS->temp_key_expire_time); } TGLC_sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer); int l = encrypt_packet_buffer (TLS, DC); clear_packet (); out_int (CODE_req_DH_params); out_ints ((int *) DC->nonce, 4); out_ints ((int *) DC->server_nonce, 4); out_bignum (p); out_bignum (q); out_long (TLS->rsa_key_fingerprint[DC->rsa_key_idx]); out_cstring ((char *) encrypt_buffer, l); TGLC_bn_free (p); TGLC_bn_free (q); DC->state = temp_key ? st_reqdh_sent_temp : st_reqdh_sent; rpc_send_packet (TLS, c); } /* }}} */ /* {{{ SEND DH PARAMS */ // set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer; // client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data static void send_dh_params (struct tgl_state *TLS, struct connection *c, TGLC_bn *dh_prime, TGLC_bn *g_a, int g, int temp_key) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); clear_packet (); packet_ptr += 5; out_int (CODE_client_DH_inner_data); out_ints ((int *) DC->nonce, 4); out_ints ((int *) DC->server_nonce, 4); out_long (0); TGLC_bn *dh_g = TGLC_bn_new (); ensure (TGLC_bn_set_word (dh_g, g)); static unsigned char s_power[256]; tglt_secure_random (s_power, 256); TGLC_bn *dh_power = TGLC_bn_bin2bn ((unsigned char *)s_power, 256, 0); ensure_ptr (dh_power); TGLC_bn *y = TGLC_bn_new (); ensure_ptr (y); ensure (TGLC_bn_mod_exp (y, dh_g, dh_power, dh_prime, TLS->TGLC_bn_ctx)); out_bignum (y); TGLC_bn_free (y); TGLC_bn *auth_key_num = TGLC_bn_new (); ensure (TGLC_bn_mod_exp (auth_key_num, g_a, dh_power, dh_prime, TLS->TGLC_bn_ctx)); int l = TGLC_bn_num_bytes (auth_key_num); assert (l >= 250 && l <= 256); assert (TGLC_bn_bn2bin (auth_key_num, (unsigned char *)(temp_key ? DC->temp_auth_key : DC->auth_key))); if (l < 256) { char *key = temp_key ? DC->temp_auth_key : DC->auth_key; memmove (key + 256 - l, key, l); memset (key, 0, 256 - l); } TGLC_bn_free (dh_power); TGLC_bn_free (auth_key_num); TGLC_bn_free (dh_g); TGLC_sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer); l = encrypt_packet_buffer_aes_unauth (DC->server_nonce, DC->new_nonce); clear_packet (); out_int (CODE_set_client_DH_params); out_ints ((int *) DC->nonce, 4); out_ints ((int *) DC->server_nonce, 4); out_cstring ((char *) encrypt_buffer, l); DC->state = temp_key ? st_client_dh_sent_temp : st_client_dh_sent;; rpc_send_packet (TLS, c); } /* }}} */ /* {{{ RECV RESPQ */ // resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector long = ResPQ static int process_respq_answer (struct tgl_state *TLS, struct connection *c, char *packet, int len, int temp_key) { assert (!(len & 3)); in_ptr = (int *)packet; in_end = in_ptr + (len / 4); if (check_unauthorized_header (TLS) < 0) { return -1; } int *in_save = in_ptr; if (skip_type_any (TYPE_TO_PARAM (res_p_q)) < 0 || in_ptr != in_end) { vlogprintf (E_ERROR, "can not parse req_p_q answer\n"); return -1; } in_ptr = in_save; struct tgl_dc *DC = TLS->net_methods->get_dc (c); assert (fetch_int() == CODE_res_p_q); static int tmp[4]; fetch_ints (tmp, 4); if (memcmp (tmp, DC->nonce, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } fetch_ints (DC->server_nonce, 4); TGLC_bn *pq = TGLC_bn_new (); assert (fetch_bignum (pq) >= 0); assert (fetch_int () == CODE_vector); int fingerprints_num = fetch_int (); assert (fingerprints_num >= 0); DC->rsa_key_idx = -1; int i; for (i = 0; i < fingerprints_num; i++) { int j; long long fprint = fetch_long (); for (j = 0; j < TLS->rsa_key_num; j++) { if (TLS->rsa_key_loaded[j]) { if (fprint == TLS->rsa_key_fingerprint[j]) { DC->rsa_key_idx = j; break; } } } } assert (in_ptr == in_end); if (DC->rsa_key_idx == -1) { vlogprintf (E_ERROR, "fatal: don't have any matching keys\n"); return -1; } send_req_dh_packet (TLS, c, pq, temp_key); TGLC_bn_free (pq); return 1; } /* }}} */ /* {{{ RECV DH */ // server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params; // server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params; // server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data; static int process_dh_answer (struct tgl_state *TLS, struct connection *c, char *packet, int len, int temp_key) { assert (!(len & 3)); in_ptr = (int *)packet; in_end = in_ptr + (len / 4); if (check_unauthorized_header (TLS) < 0) { return -1; } int *in_save = in_ptr; if (skip_type_any (TYPE_TO_PARAM (server_d_h_params)) < 0 || in_ptr != in_end) { vlogprintf (E_ERROR, "can not parse server_DH_params answer\n"); return -1; } in_ptr = in_save; struct tgl_dc *DC = TLS->net_methods->get_dc (c); unsigned op = fetch_int (); assert (op == CODE_server__d_h_params_ok || op == CODE_server__d_h_params_fail); int tmp[4]; fetch_ints (tmp, 4); if (memcmp (tmp, DC->nonce, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } assert (!memcmp (tmp, DC->nonce, 16)); fetch_ints (tmp, 4); if (memcmp (tmp, DC->server_nonce, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } assert (!memcmp (tmp, DC->server_nonce, 16)); if (op == CODE_server__d_h_params_fail) { vlogprintf (E_ERROR, "DH params fail\n"); return -1; } tgl_init_aes_unauth (DC->server_nonce, DC->new_nonce, 0); int l = prefetch_strlen (); assert (l >= 0); if (!l) { vlogprintf (E_ERROR, "non-empty encrypted part expected\n"); return -1; } l = tgl_pad_aes_decrypt (fetch_str (l), l, (char *) decrypt_buffer, DECRYPT_BUFFER_INTS * 4 - 16); assert (in_ptr == in_end); in_ptr = decrypt_buffer + 5; in_end = decrypt_buffer + (l >> 2); if (skip_type_any (TYPE_TO_PARAM (server_d_h_inner_data)) < 0) { vlogprintf (E_ERROR, "can not parse server_DH_inner_data answer\n"); return -1; } in_ptr = decrypt_buffer + 5; assert (fetch_int () == (int)CODE_server_DH_inner_data); fetch_ints (tmp, 4); if (memcmp (tmp, DC->nonce, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } assert (!memcmp (tmp, DC->nonce, 16)); fetch_ints (tmp, 4); if (memcmp (tmp, DC->server_nonce, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } assert (!memcmp (tmp, DC->server_nonce, 16)); int g = fetch_int (); TGLC_bn *dh_prime = TGLC_bn_new (); TGLC_bn *g_a = TGLC_bn_new (); assert (fetch_bignum (dh_prime) > 0); assert (fetch_bignum (g_a) > 0); if (tglmp_check_DH_params (TLS, dh_prime, g) < 0) { vlogprintf (E_ERROR, "bad DH params\n"); return -1; } if (tglmp_check_g_a (TLS, dh_prime, g_a) < 0) { vlogprintf (E_ERROR, "bad dh_prime\n"); return -1; } int server_time = fetch_int (); assert (in_ptr <= in_end); static char sha1_buffer[20]; TGLC_sha1 ((unsigned char *) decrypt_buffer + 20, (in_ptr - decrypt_buffer - 5) * 4, (unsigned char *) sha1_buffer); if (memcmp (decrypt_buffer, sha1_buffer, 20)) { vlogprintf (E_ERROR, "bad encrypted message SHA1\n"); return -1; } if ((char *) in_end - (char *) in_ptr >= 16) { vlogprintf (E_ERROR, "too much padding\n"); return -1; } DC->server_time_delta = server_time - get_utime (CLOCK_REALTIME); DC->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC); send_dh_params (TLS, c, dh_prime, g_a, g, temp_key); TGLC_bn_free (dh_prime); TGLC_bn_free (g_a); return 1; } /* }}} */ static void create_temp_auth_key (struct tgl_state *TLS, struct connection *c) { assert (TLS->enable_pfs); send_req_pq_temp_packet (TLS, c); } int tglmp_encrypt_inner_temp (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id); static long long msg_id_override; static void mpc_on_get_config (struct tgl_state *TLS, void *extra, int success); static void bind_temp_auth_key (struct tgl_state *TLS, struct connection *c); /* {{{ RECV AUTH COMPLETE */ // dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer; // dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer; // dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer; static int process_auth_complete (struct tgl_state *TLS, struct connection *c, char *packet, int len, int temp_key) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); assert (!(len & 3)); in_ptr = (int *)packet; in_end = in_ptr + (len / 4); if (check_unauthorized_header (TLS) < 0) { return -1; } int *in_save = in_ptr; if (skip_type_any (TYPE_TO_PARAM (set_client_d_h_params_answer)) < 0 || in_ptr != in_end) { vlogprintf (E_ERROR, "can not parse server_DH_params answer\n"); return -1; } in_ptr = in_save; unsigned op = fetch_int (); assert (op == CODE_dh_gen_ok || op == CODE_dh_gen_retry || op == CODE_dh_gen_fail); int tmp[4]; fetch_ints (tmp, 4); if (memcmp (DC->nonce, tmp, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } fetch_ints (tmp, 4); if (memcmp (DC->server_nonce, tmp, 16)) { vlogprintf (E_ERROR, "nonce mismatch\n"); return -1; } if (op != CODE_dh_gen_ok) { vlogprintf (E_ERROR, "something bad. Retry regen\n"); return -1; } fetch_ints (tmp, 4); static unsigned char th[44], sha1_buffer[20]; memcpy (th, DC->new_nonce, 32); th[32] = 1; if (!temp_key) { TGLC_sha1 ((unsigned char *)DC->auth_key, 256, sha1_buffer); } else { TGLC_sha1 ((unsigned char *)DC->temp_auth_key, 256, sha1_buffer); } memcpy (th + 33, sha1_buffer, 8); TGLC_sha1 (th, 41, sha1_buffer); if (memcmp (tmp, sha1_buffer + 4, 16)) { vlogprintf (E_ERROR, "hash mismatch\n"); return -1; } if (!temp_key) { bl_do_set_auth_key (TLS, DC->id, (unsigned char *)DC->auth_key); TGLC_sha1 ((unsigned char *)DC->auth_key, 256, sha1_buffer); } else { TGLC_sha1 ((unsigned char *)DC->temp_auth_key, 256, sha1_buffer); DC->temp_auth_key_id = *(long long *)(sha1_buffer + 12); } DC->server_salt = *(long long *)DC->server_nonce ^ *(long long *)DC->new_nonce; DC->state = st_authorized; vlogprintf (E_DEBUG, "Auth success\n"); if (temp_key) { bind_temp_auth_key (TLS, c); } else { DC->flags |= 1; if (TLS->enable_pfs) { assert (TLS->enable_pfs); create_temp_auth_key (TLS, c); } else { DC->temp_auth_key_id = DC->auth_key_id; memcpy (DC->temp_auth_key, DC->auth_key, 256); DC->flags |= 2; if (!(DC->flags & 4)) { tgl_do_help_get_config_dc (TLS, DC, mpc_on_get_config, DC); } } } return 1; } /* }}} */ static void bind_temp_auth_key (struct tgl_state *TLS, struct connection *c) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); if (DC->temp_auth_key_bind_query_id) { tglq_query_delete (TLS, DC->temp_auth_key_bind_query_id); } struct tgl_session *S = TLS->net_methods->get_session (c); long long msg_id = generate_next_msg_id (TLS, DC, S); clear_packet (); out_int (CODE_bind_auth_key_inner); long long rand; tglt_secure_random (&rand, 8); out_long (rand); out_long (DC->temp_auth_key_id); out_long (DC->auth_key_id); if (!S->session_id) { tglt_secure_random (&S->session_id, 8); } out_long (S->session_id); int expires = time (0) + DC->server_time_delta + TLS->temp_key_expire_time; out_int (expires); static int data[1000]; int len = tglmp_encrypt_inner_temp (TLS, c, packet_buffer, packet_ptr - packet_buffer, 0, data, msg_id); msg_id_override = msg_id; DC->temp_auth_key_bind_query_id = msg_id; tgl_do_send_bind_temp_key (TLS, DC, rand, expires, (void *)data, len, msg_id); msg_id_override = 0; } /* * * AUTHORIZED (MAIN) PROTOCOL PART * */ static struct encrypted_message enc_msg; static double get_server_time (struct tgl_dc *DC) { //if (!DC->server_time_udelta) { // DC->server_time_udelta = get_utime (CLOCK_REALTIME) - get_utime (CLOCK_MONOTONIC); //} return get_utime (CLOCK_MONOTONIC) + DC->server_time_udelta; } static long long generate_next_msg_id (struct tgl_state *TLS, struct tgl_dc *DC, struct tgl_session *S) { long long next_id = (long long) (get_server_time (DC) * (1LL << 32)) & -4; if (next_id <= S->last_msg_id) { next_id = S->last_msg_id += 4; } else { S->last_msg_id = next_id; } return next_id; } static void init_enc_msg (struct tgl_state *TLS, struct tgl_session *S, int useful) { struct tgl_dc *DC = S->dc; assert (DC->state == st_authorized); assert (DC->temp_auth_key_id); vlogprintf (E_DEBUG, "temp_auth_key_id = 0x%016" INT64_PRINTF_MODIFIER "x, auth_key_id = 0x%016" INT64_PRINTF_MODIFIER "x\n", DC->temp_auth_key_id, DC->auth_key_id); enc_msg.auth_key_id = DC->temp_auth_key_id; enc_msg.server_salt = DC->server_salt; if (!S->session_id) { tglt_secure_random (&S->session_id, 8); } enc_msg.session_id = S->session_id; enc_msg.msg_id = msg_id_override ? msg_id_override : generate_next_msg_id (TLS, DC, S); enc_msg.seq_no = S->seq_no; if (useful) { enc_msg.seq_no |= 1; } S->seq_no += 2; }; static void init_enc_msg_inner_temp (struct tgl_dc *DC, long long msg_id) { enc_msg.auth_key_id = DC->auth_key_id; tglt_secure_random (&enc_msg.server_salt, 8); tglt_secure_random (&enc_msg.session_id, 8); enc_msg.msg_id = msg_id; enc_msg.seq_no = 0; }; static int aes_encrypt_message (struct tgl_state *TLS, char *key, struct encrypted_message *enc) { unsigned char sha1_buffer[20]; const int MINSZ = offsetof (struct encrypted_message, message); const int UNENCSZ = offsetof (struct encrypted_message, server_salt); int enc_len = (MINSZ - UNENCSZ) + enc->msg_len; assert (enc->msg_len >= 0 && enc->msg_len <= MAX_MESSAGE_INTS * 4 - 16 && !(enc->msg_len & 3)); TGLC_sha1 ((unsigned char *) &enc->server_salt, enc_len, sha1_buffer); vlogprintf (E_DEBUG, "sending message with sha1 %08x\n", *(int *)sha1_buffer); memcpy (enc->msg_key, sha1_buffer + 4, 16); tgl_init_aes_auth (key, enc->msg_key, 1); return tgl_pad_aes_encrypt ((char *) &enc->server_salt, enc_len, (char *) &enc->server_salt, MAX_MESSAGE_INTS * 4 + (MINSZ - UNENCSZ)); } long long tglmp_encrypt_send_message (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int flags) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); struct tgl_session *S = TLS->net_methods->get_session (c); assert (S); if (!(DC->flags & 4) && !(flags & 2)) { return generate_next_msg_id (TLS, DC, S); } const int UNENCSZ = offsetof (struct encrypted_message, server_salt); if (msg_ints <= 0 || msg_ints > MAX_MESSAGE_INTS - 4) { return -1; } if (msg) { memcpy (enc_msg.message, msg, msg_ints * 4); enc_msg.msg_len = msg_ints * 4; } else { if ((enc_msg.msg_len & 0x80000003) || enc_msg.msg_len > MAX_MESSAGE_INTS * 4 - 16) { return -1; } } init_enc_msg (TLS, S, flags & 1); int l = aes_encrypt_message (TLS, DC->temp_auth_key, &enc_msg); assert (l > 0); rpc_send_message (TLS, c, &enc_msg, l + UNENCSZ); return S->last_msg_id; } int tglmp_encrypt_inner_temp (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); struct tgl_session *S = TLS->net_methods->get_session (c); assert (S); const int UNENCSZ = offsetof (struct encrypted_message, server_salt); if (msg_ints <= 0 || msg_ints > MAX_MESSAGE_INTS - 4) { return -1; } memcpy (enc_msg.message, msg, msg_ints * 4); enc_msg.msg_len = msg_ints * 4; init_enc_msg_inner_temp (DC, msg_id); int l = aes_encrypt_message (TLS, DC->auth_key, &enc_msg); assert (l > 0); //rpc_send_message (c, &enc_msg, l + UNENCSZ); memcpy (data, &enc_msg, l + UNENCSZ); return l + UNENCSZ; } static int rpc_execute_answer (struct tgl_state *TLS, struct connection *c, long long msg_id); static int work_container (struct tgl_state *TLS, struct connection *c, long long msg_id) { vlogprintf (E_DEBUG, "work_container: msg_id = %" INT64_PRINTF_MODIFIER "d\n", msg_id); assert (fetch_int () == CODE_msg_container); int n = fetch_int (); int i; for (i = 0; i < n; i++) { long long id = fetch_long (); //int seqno = fetch_int (); fetch_int (); // seq_no if (id & 1) { tgln_insert_msg_id (TLS, TLS->net_methods->get_session (c), id); } int bytes = fetch_int (); int *t = in_end; in_end = in_ptr + (bytes / 4); int r = rpc_execute_answer (TLS, c, id); if (r < 0) { return -1; } assert (in_ptr == in_end); in_end = t; } return 0; } static int work_new_session_created (struct tgl_state *TLS, struct connection *c, long long msg_id) { struct tgl_session *S = TLS->net_methods->get_session (c); struct tgl_dc *DC = TLS->net_methods->get_dc (c); vlogprintf (E_NOTICE, "work_new_session_created: msg_id = %" INT64_PRINTF_MODIFIER "d, dc = %d\n", msg_id, DC->id); assert (fetch_int () == (int)CODE_new_session_created); fetch_long (); // first message id fetch_long (); // unique_id TLS->net_methods->get_dc (c)->server_salt = fetch_long (); tglq_regen_queries_from_old_session (TLS, DC, S); if (TLS->started && !(TLS->locks & TGL_LOCK_DIFF) && (TLS->DC_working->flags & TGLDCF_LOGGED_IN)) { tgl_do_get_difference (TLS, 0, 0, 0); } return 0; } static int work_msgs_ack (struct tgl_state *TLS, struct connection *c, long long msg_id) { vlogprintf (E_DEBUG, "work_msgs_ack: msg_id = %" INT64_PRINTF_MODIFIER "d\n", msg_id); assert (fetch_int () == CODE_msgs_ack); assert (fetch_int () == CODE_vector); int n = fetch_int (); int i; for (i = 0; i < n; i++) { long long id = fetch_long (); vlogprintf (E_DEBUG + 1, "ack for %" INT64_PRINTF_MODIFIER "d\n", id); tglq_query_ack (TLS, id); } return 0; } static int work_rpc_result (struct tgl_state *TLS, struct connection *c, long long msg_id) { vlogprintf (E_DEBUG, "work_rpc_result: msg_id = %" INT64_PRINTF_MODIFIER "d\n", msg_id); assert (fetch_int () == (int)CODE_rpc_result); long long id = fetch_long (); int op = prefetch_int (); if (op == CODE_rpc_error) { return tglq_query_error (TLS, id); } else { return tglq_query_result (TLS, id); } } #define MAX_PACKED_SIZE (1 << 24) static int work_packed (struct tgl_state *TLS, struct connection *c, long long msg_id) { assert (fetch_int () == CODE_gzip_packed); static int in_gzip; static int buf[MAX_PACKED_SIZE >> 2]; assert (!in_gzip); in_gzip = 1; int l = prefetch_strlen (); char *s = fetch_str (l); int total_out = tgl_inflate (s, l, buf, MAX_PACKED_SIZE); int *end = in_ptr; int *eend = in_end; //assert (total_out % 4 == 0); in_ptr = buf; in_end = in_ptr + total_out / 4; int r = rpc_execute_answer (TLS, c, msg_id); in_ptr = end; in_end = eend; in_gzip = 0; return r; } static int work_bad_server_salt (struct tgl_state *TLS, struct connection *c, long long msg_id) { assert (fetch_int () == (int)CODE_bad_server_salt); long long id = fetch_long (); fetch_int (); // seq_no fetch_int (); // error_code long long new_server_salt = fetch_long (); TLS->net_methods->get_dc (c)->server_salt = new_server_salt; tglq_query_restart (TLS, id); return 0; } static int work_pong (struct tgl_state *TLS, struct connection *c, long long msg_id) { assert (fetch_int () == CODE_pong); fetch_long (); // msg_id fetch_long (); // ping_id return 0; } static int work_detailed_info (struct tgl_state *TLS, struct connection *c, long long msg_id) { assert (fetch_int () == CODE_msg_detailed_info); fetch_long (); // msg_id fetch_long (); // answer_msg_id fetch_int (); // bytes fetch_int (); // status return 0; } static int work_new_detailed_info (struct tgl_state *TLS, struct connection *c, long long msg_id) { assert (fetch_int () == (int)CODE_msg_new_detailed_info); fetch_long (); // answer_msg_id fetch_int (); // bytes fetch_int (); // status return 0; } static int work_bad_msg_notification (struct tgl_state *TLS, struct connection *c, long long msg_id) { assert (fetch_int () == (int)CODE_bad_msg_notification); long long m1 = fetch_long (); int s = fetch_int (); int e = fetch_int (); vlogprintf (E_NOTICE, "bad_msg_notification: msg_id = %" INT64_PRINTF_MODIFIER "d, seq = %d, error = %d\n", m1, s, e); switch (e) { // Too low msg id case 16: tglq_regen_query (TLS, m1); break; // Too high msg id case 17: tglq_regen_query (TLS, m1); break; // Bad container case 64: vlogprintf (E_NOTICE, "bad_msg_notification: msg_id = %" INT64_PRINTF_MODIFIER "d, seq = %d, error = %d\n", m1, s, e); tglq_regen_query (TLS, m1); break; default: vlogprintf (E_NOTICE, "bad_msg_notification: msg_id = %" INT64_PRINTF_MODIFIER "d, seq = %d, error = %d\n", m1, s, e); break; } return -1; } static int rpc_execute_answer (struct tgl_state *TLS, struct connection *c, long long msg_id) { int op = prefetch_int (); switch (op) { case CODE_msg_container: return work_container (TLS, c, msg_id); case CODE_new_session_created: return work_new_session_created (TLS, c, msg_id); case CODE_msgs_ack: return work_msgs_ack (TLS, c, msg_id); case CODE_rpc_result: return work_rpc_result (TLS, c, msg_id); case CODE_update_short: case CODE_updates: case CODE_update_short_message: case CODE_update_short_chat_message: case CODE_updates_too_long: tglu_work_any_updates_buf (TLS); return 0; case CODE_gzip_packed: return work_packed (TLS, c, msg_id); case CODE_bad_server_salt: return work_bad_server_salt (TLS, c, msg_id); case CODE_pong: return work_pong (TLS, c, msg_id); case CODE_msg_detailed_info: return work_detailed_info (TLS, c, msg_id); case CODE_msg_new_detailed_info: return work_new_detailed_info (TLS, c, msg_id); case CODE_bad_msg_notification: return work_bad_msg_notification (TLS, c, msg_id); } vlogprintf (E_WARNING, "Unknown message: %08x\n", op); in_ptr = in_end; // Will not fail due to assertion in_ptr == in_end return 0; } static struct mtproto_methods mtproto_methods; void tgls_free_session (struct tgl_state *TLS, struct tgl_session *S); /* static char *get_ipv6 (struct tgl_state *TLS, int num) { static char res[1<< 10]; if (TLS->test_mode) { switch (num) { case 1: strcpy (res, TG_SERVER_TEST_IPV6_1); break; case 2: strcpy (res, TG_SERVER_TEST_IPV6_2); break; case 3: strcpy (res, TG_SERVER_TEST_IPV6_3); break; default: assert (0); } } else { switch (num) { case 1: strcpy (res, TG_SERVER_IPV6_1); break; case 2: strcpy (res, TG_SERVER_IPV6_2); break; case 3: strcpy (res, TG_SERVER_IPV6_3); break; case 4: strcpy (res, TG_SERVER_IPV6_4); break; case 5: strcpy (res, TG_SERVER_IPV6_5); break; default: assert (0); } } return res; } */ static void create_session_connect (struct tgl_state *TLS, struct tgl_session *S) { struct tgl_dc *DC = S->dc; if (TLS->ipv6_enabled) { S->c = TLS->net_methods->create_connection (TLS, DC->options[1]->ip, DC->options[1]->port, S, DC, &mtproto_methods); } else { S->c = TLS->net_methods->create_connection (TLS, DC->options[0]->ip, DC->options[0]->port, S, DC, &mtproto_methods); } } static void fail_connection (struct tgl_state *TLS, struct connection *c) { struct tgl_session *S = TLS->net_methods->get_session (c); TLS->net_methods->free (c); create_session_connect (TLS, S); } static void fail_session (struct tgl_state *TLS, struct tgl_session *S) { vlogprintf (E_NOTICE, "failing session %" INT64_PRINTF_MODIFIER "d\n", S->session_id); struct tgl_dc *DC = S->dc; tgls_free_session (TLS, S); DC->sessions[0] = NULL; tglmp_dc_create_session (TLS, DC); } static int process_rpc_message (struct tgl_state *TLS, struct connection *c, struct encrypted_message *enc, int len) { const int MINSZ = offsetof (struct encrypted_message, message); const int UNENCSZ = offsetof (struct encrypted_message, server_salt); vlogprintf (E_DEBUG, "process_rpc_message(), len=%d\n", len); if (len < MINSZ || (len & 15) != (UNENCSZ & 15)) { vlogprintf (E_WARNING, "Incorrect packet from server. Closing connection\n"); fail_connection (TLS, c); return -1; } assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15)); struct tgl_dc *DC = TLS->net_methods->get_dc (c); if (enc->auth_key_id != DC->temp_auth_key_id && enc->auth_key_id != DC->auth_key_id) { vlogprintf (E_WARNING, "received msg from dc %d with auth_key_id %" INT64_PRINTF_MODIFIER "d (perm_auth_key_id %" INT64_PRINTF_MODIFIER "d temp_auth_key_id %" INT64_PRINTF_MODIFIER "d). Dropping\n", DC->id, enc->auth_key_id, DC->auth_key_id, DC->temp_auth_key_id); return 0; } if (enc->auth_key_id == DC->temp_auth_key_id) { assert (enc->auth_key_id == DC->temp_auth_key_id); assert (DC->temp_auth_key_id); tgl_init_aes_auth (DC->temp_auth_key + 8, enc->msg_key, 0); } else { assert (enc->auth_key_id == DC->auth_key_id); assert (DC->auth_key_id); tgl_init_aes_auth (DC->auth_key + 8, enc->msg_key, 0); } int l = tgl_pad_aes_decrypt ((char *)&enc->server_salt, len - UNENCSZ, (char *)&enc->server_salt, len - UNENCSZ); assert (l == len - UNENCSZ); if (!(!(enc->msg_len & 3) && enc->msg_len > 0 && enc->msg_len <= len - MINSZ && len - MINSZ - enc->msg_len <= 12)) { vlogprintf (E_WARNING, "Incorrect packet from server. Closing connection\n"); fail_connection (TLS, c); return -1; } assert (!(enc->msg_len & 3) && enc->msg_len > 0 && enc->msg_len <= len - MINSZ && len - MINSZ - enc->msg_len <= 12); struct tgl_session *S = TLS->net_methods->get_session (c); if (!S || S->session_id != enc->session_id) { vlogprintf (E_WARNING, "Message to bad session. Drop.\n"); return 0; } static unsigned char sha1_buffer[20]; TGLC_sha1 ((void *)&enc->server_salt, enc->msg_len + (MINSZ - UNENCSZ), sha1_buffer); if (memcmp (&enc->msg_key, sha1_buffer + 4, 16)) { vlogprintf (E_WARNING, "Incorrect packet from server. Closing connection\n"); fail_connection (TLS, c); return -1; } assert (!memcmp (&enc->msg_key, sha1_buffer + 4, 16)); int this_server_time = enc->msg_id >> 32LL; if (!S->received_messages) { DC->server_time_delta = this_server_time - get_utime (CLOCK_REALTIME); if (DC->server_time_udelta) { vlogprintf (E_WARNING, "adjusting CLOCK_MONOTONIC delta to %lf\n", DC->server_time_udelta - this_server_time + get_utime (CLOCK_MONOTONIC)); } DC->server_time_udelta = this_server_time - get_utime (CLOCK_MONOTONIC); } double st = get_server_time (DC); if (this_server_time < st - 300 || this_server_time > st + 30) { vlogprintf (E_WARNING, "bad msg time: salt = %" INT64_PRINTF_MODIFIER "d, session_id = %" INT64_PRINTF_MODIFIER "d, msg_id = %" INT64_PRINTF_MODIFIER "d, seq_no = %d, st = %lf, now = %lf\n", enc->server_salt, enc->session_id, enc->msg_id, enc->seq_no, st, get_utime (CLOCK_REALTIME)); fail_session (TLS, S); return -1; } S->received_messages ++; if (DC->server_salt != enc->server_salt) { DC->server_salt = enc->server_salt; } assert (this_server_time >= st - 300 && this_server_time <= st + 30); //assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1); vlogprintf (E_DEBUG, "received mesage id %016" INT64_PRINTF_MODIFIER "x\n", enc->msg_id); //server_last_msg_id = enc->msg_id; //*(long long *)(longpoll_query + 3) = *(long long *)((char *)(&enc->msg_id) + 0x3c); //*(long long *)(longpoll_query + 5) = *(long long *)((char *)(&enc->msg_id) + 0x3c); assert (l >= (MINSZ - UNENCSZ) + 8); //assert (enc->message[0] == CODE_rpc_result && *(long long *)(enc->message + 1) == client_last_msg_id); in_ptr = enc->message; in_end = in_ptr + (enc->msg_len / 4); if (enc->msg_id & 1) { tgln_insert_msg_id (TLS, S, enc->msg_id); } assert (S->session_id == enc->session_id); if (rpc_execute_answer (TLS, c, enc->msg_id) < 0) { fail_session (TLS, S); return -1; } assert (in_ptr == in_end); return 0; } static int rpc_execute (struct tgl_state *TLS, struct connection *c, int op, int len) { struct tgl_dc *DC = TLS->net_methods->get_dc (c); if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) { vlogprintf (E_WARNING, "answer too long (%d bytes), skipping\n", len); return 0; } int Response_len = len; static char Response[MAX_RESPONSE_SIZE]; vlogprintf (E_DEBUG, "Response_len = %d\n", Response_len); assert (TLS->net_methods->read_in (c, Response, Response_len) == Response_len); #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) // setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif int o = DC->state; //if (DC->flags & 1) { o = st_authorized;} if (o != st_authorized) { vlogprintf (E_DEBUG, "%s: state = %d\n", __func__, o); } switch (o) { case st_reqpq_sent: process_respq_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 0); return 0; case st_reqdh_sent: process_dh_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 0); return 0; case st_client_dh_sent: process_auth_complete (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 0); return 0; case st_reqpq_sent_temp: process_respq_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 1); return 0; case st_reqdh_sent_temp: process_dh_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 1); return 0; case st_client_dh_sent_temp: process_auth_complete (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 1); return 0; case st_authorized: if (op < 0 && op >= -999) { vlogprintf (E_WARNING, "Server error %d\n", op); } else { return process_rpc_message (TLS, c, (void *)(Response/* + 8*/), Response_len/* - 12*/); } return 0; default: vlogprintf (E_ERROR, "fatal: cannot receive answer in state %d\n", DC->state); exit (2); } return 0; } static int tc_close (struct tgl_state *TLS, struct connection *c, int who) { vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d : closing by %d\n", TLS->net_methods->get_dc(c)->id, who); return 0; } static void mpc_on_get_config (struct tgl_state *TLS, void *extra, int success) { assert (success); struct tgl_dc *DC = extra; DC->flags |= 4; } static int tc_becomes_ready (struct tgl_state *TLS, struct connection *c) { vlogprintf (E_NOTICE, "outbound rpc connection from dc #%d becomed ready\n", TLS->net_methods->get_dc(c)->id); //char byte = 0xef; //assert (TLS->net_methods->write_out (c, &byte, 1) == 1); //TLS->net_methods->flush_out (c); struct tgl_dc *DC = TLS->net_methods->get_dc (c); if (DC->flags & 1) { DC->state = st_authorized; } int o = DC->state; if (o == st_authorized && !TLS->enable_pfs) { DC->temp_auth_key_id = DC->auth_key_id; memcpy (DC->temp_auth_key, DC->auth_key, 256); DC->flags |= 2; } switch (o) { case st_init: send_req_pq_packet (TLS, c); break; case st_authorized: if (!(DC->flags & 2)) { assert (TLS->enable_pfs); if (!DC->temp_auth_key_id) { assert (!DC->temp_auth_key_id); assert (TLS->enable_pfs); create_temp_auth_key (TLS, c); } else { bind_temp_auth_key (TLS, c); } } else if (!(DC->flags & 4)) { tgl_do_help_get_config_dc (TLS, DC, mpc_on_get_config, DC); } break; default: vlogprintf (E_DEBUG, "c_state = %d\n", DC->state); DC->state = st_init; // previous connection was reset send_req_pq_packet (TLS, c); break; } return 0; } static int rpc_becomes_ready (struct tgl_state *TLS, struct connection *c) { return tc_becomes_ready (TLS, c); } static int rpc_close (struct tgl_state *TLS, struct connection *c) { return tc_close (TLS, c, 0); } #define RANDSEED_PASSWORD_FILENAME NULL #define RANDSEED_PASSWORD_LENGTH 0 int tglmp_on_start (struct tgl_state *TLS) { tgl_prng_seed (TLS, RANDSEED_PASSWORD_FILENAME, RANDSEED_PASSWORD_LENGTH); int i; int ok = 0; for (i = 0; i < TLS->rsa_key_num; i++) { char *key = TLS->rsa_key_list[i]; if (!key) { /* This key was provided using 'tgl_set_rsa_key_direct'. */ TGLC_rsa *rsa = TLS->rsa_key_loaded[i]; assert (rsa); TLS->rsa_key_fingerprint[i] = tgl_do_compute_rsa_key_fingerprint (rsa); vlogprintf (E_NOTICE, "'direct' public key loaded successfully\n"); ok = 1; } else { TGLC_rsa *res = rsa_load_public_key (TLS, key); if (!res) { vlogprintf (E_WARNING, "Can not load key %s\n", key); TLS->rsa_key_loaded[i] = NULL; } else { ok = 1; TLS->rsa_key_loaded[i] = res; TLS->rsa_key_fingerprint[i] = tgl_do_compute_rsa_key_fingerprint (res); } } } if (!ok) { vlogprintf (E_ERROR, "No public keys found\n"); TLS->error = tstrdup ("No public keys found"); TLS->error_code = ENOTCONN; return -1; } return 0; } void tgl_dc_authorize (struct tgl_state *TLS, struct tgl_dc *DC) { //c_state = 0; if (!DC->sessions[0]) { tglmp_dc_create_session (TLS, DC); } vlogprintf (E_DEBUG, "Starting authorization for DC #%d\n", DC->id); //net_loop (0, auth_ok); } #define long_cmp(a,b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1) DEFINE_TREE(long,long long,long_cmp,0) static int send_all_acks (struct tgl_state *TLS, struct tgl_session *S) { clear_packet (); out_int (CODE_msgs_ack); out_int (CODE_vector); out_int (tree_count_long (S->ack_tree)); while (S->ack_tree) { long long x = tree_get_min_long (S->ack_tree); out_long (x); S->ack_tree = tree_delete_long (S->ack_tree, x); } tglmp_encrypt_send_message (TLS, S->c, packet_buffer, packet_ptr - packet_buffer, 0); return 0; } static void send_all_acks_gateway (struct tgl_state *TLS, void *arg) { send_all_acks (TLS, arg); } void tgln_insert_msg_id (struct tgl_state *TLS, struct tgl_session *S, long long id) { if (!S->ack_tree) { TLS->timer_methods->insert (S->ev, ACK_TIMEOUT); } if (!tree_lookup_long (S->ack_tree, id)) { S->ack_tree = tree_insert_long (S->ack_tree, id, rand ()); } } //extern struct tgl_dc *DC_list[]; static void regen_temp_key_gw (struct tgl_state *TLS, void *arg) { tglmp_regenerate_temp_auth_key (TLS, arg); } struct tgl_dc *tglmp_alloc_dc (struct tgl_state *TLS, int flags, int id, char *ip, int port) { //assert (!TLS->DC_list[id]); if (!TLS->DC_list[id]) { struct tgl_dc *DC = talloc0 (sizeof (*DC)); DC->id = id; TLS->DC_list[id] = DC; if (id > TLS->max_dc_num) { TLS->max_dc_num = id; } if (TLS->enable_pfs) { DC->ev = TLS->timer_methods->alloc (TLS, regen_temp_key_gw, DC); TLS->timer_methods->insert (DC->ev, 0); } } struct tgl_dc *DC = TLS->DC_list[id]; struct tgl_dc_option *O = DC->options[flags & 3]; struct tgl_dc_option *O2 = O; while (O2) { if (!strcmp (O2->ip, ip)) { tfree_str (ip); return DC; } O2 = O2->next; } struct tgl_dc_option *T = talloc (sizeof (*T)); T->ip = ip; T->port = port; T->next = O; DC->options[flags & 3] = T; return DC; } static struct mtproto_methods mtproto_methods = { .execute = rpc_execute, .ready = rpc_becomes_ready, .close = rpc_close }; void tglmp_dc_create_session (struct tgl_state *TLS, struct tgl_dc *DC) { struct tgl_session *S = talloc0 (sizeof (*S)); assert (TGLC_rand_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0); S->dc = DC; //S->c = TLS->net_methods->create_connection (TLS, DC->ip, DC->port, S, DC, &mtproto_methods); create_session_connect (TLS, S); S->ev = TLS->timer_methods->alloc (TLS, send_all_acks_gateway, S); assert (!DC->sessions[0]); DC->sessions[0] = S; } void tgl_do_send_ping (struct tgl_state *TLS, struct connection *c) { int x[3]; x[0] = CODE_ping; *(long long *)(x + 1) = rand () * (1ll << 32) + rand (); tglmp_encrypt_send_message (TLS, c, x, 3, 0); } void tgl_dc_iterator (struct tgl_state *TLS, void (*iterator)(struct tgl_dc *DC)) { int i; for (i = 0; i <= TLS->max_dc_num; i++) { iterator (TLS->DC_list[i]); } } void tgl_dc_iterator_ex (struct tgl_state *TLS, void (*iterator)(struct tgl_dc *DC, void *extra), void *extra) { int i; for (i = 0; i <= TLS->max_dc_num; i++) { iterator (TLS->DC_list[i], extra); } } void tglmp_regenerate_temp_auth_key (struct tgl_state *TLS, struct tgl_dc *DC) { DC->flags &= ~6; DC->temp_auth_key_id = 0; memset (DC->temp_auth_key, 0, 256); if (!DC->sessions[0]) { tgl_dc_authorize (TLS, DC); return; } struct tgl_session *S = DC->sessions[0]; tglt_secure_random (&S->session_id, 8); S->seq_no = 0; TLS->timer_methods->remove (S->ev); S->ack_tree = tree_clear_long (S->ack_tree); if (DC->state != st_authorized) { return; } if (!TLS->enable_pfs) { return; } if (S->c) { assert (TLS->enable_pfs); create_temp_auth_key (TLS, S->c); } } void tgls_free_session (struct tgl_state *TLS, struct tgl_session *S) { S->ack_tree = tree_clear_long (S->ack_tree); if (S->ev) { TLS->timer_methods->free (S->ev); } if (S->c) { TLS->net_methods->free (S->c); } tfree (S, sizeof (*S)); } void tgls_free_dc (struct tgl_state *TLS, struct tgl_dc *DC) { //if (DC->ip) { tfree_str (DC->ip); } struct tgl_session *S = DC->sessions[0]; if (S) { tgls_free_session (TLS, S); } int i; for (i = 0; i < 4; i++) { struct tgl_dc_option *O = DC->options[i]; while (O) { struct tgl_dc_option *N = O->next; tfree_str (O->ip); tfree (O, sizeof (*O)); O = N; } } if (DC->ev) { TLS->timer_methods->free (DC->ev); } tfree (DC, sizeof (*DC)); } void tgls_free_pubkey (struct tgl_state *TLS) { int i; for (i = 0; i < TLS->rsa_key_num; i++) { if (TLS->rsa_key_loaded[i]) { TGLC_rsa_free (TLS->rsa_key_loaded[i]); TLS->rsa_key_loaded[i] = NULL; } } } ================================================ FILE: mtproto-client.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Nikolay Durov, Andrey Lopatin 2012-2013 Vitaly Valtman 2013-2015 */ #ifndef __MTPROTO_CLIENT_H__ #define __MTPROTO_CLIENT_H__ //#include "net.h" #include "crypto/bn.h" //void on_start (void); //..long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful); //void dc_authorize (struct tgl_dc *DC); //void work_update (struct connection *c, long long msg_id); //void work_update_binlog (void); //int check_g (unsigned char p[256], BIGNUM *g); //int check_g_bn (BIGNUM *p, BIGNUM *g); //int check_DH_params (BIGNUM *p, int g); //void secure_random (void *s, int l); #include "tgl.h" struct connection; struct tgl_dc; //#include "queries.h" #define TG_APP_HASH "844584f2b1fd2daecee726166dcc1ef8" #define TG_APP_ID 10534 #define ACK_TIMEOUT 1 #define MAX_DC_ID 10 struct connection; long long tglmp_encrypt_send_message (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int flags); void tglmp_dc_create_session (struct tgl_state *TLS, struct tgl_dc *DC); //int tglmp_check_g (struct tgl_state *TLS, unsigned char p[256], BIGNUM *g); //int tglmp_check_DH_params (struct tgl_state *TLS, BIGNUM *p, int g); struct tgl_dc *tglmp_alloc_dc (struct tgl_state *TLS, int flags, int id, char *ip, int port); void tglmp_regenerate_temp_auth_key (struct tgl_state *TLS, struct tgl_dc *D); void tgln_insert_msg_id (struct tgl_state *TLS, struct tgl_session *S, long long id); int tglmp_on_start (struct tgl_state *TLS); void tgl_dc_authorize (struct tgl_state *TLS, struct tgl_dc *DC); void tgls_free_dc (struct tgl_state *TLS, struct tgl_dc *DC); void tgls_free_pubkey (struct tgl_state *TLS); void tgl_do_send_ping (struct tgl_state *TLS, struct connection *c); #endif ================================================ FILE: mtproto-common.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Nikolay Durov, Andrey Lopatin 2012-2013 Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #ifdef WIN32 #include #else #include #endif #include "crypto/aes.h" #include "crypto/rand.h" #include "crypto/sha.h" #include "mtproto-common.h" #include "tools.h" #ifdef __MACH__ #include #include #endif #include #ifndef O_BINARY #define O_BINARY 0 #endif static int __packet_buffer[PACKET_BUFFER_SIZE + 16]; int *tgl_packet_ptr; int *tgl_packet_buffer = __packet_buffer + 16; static long long rsa_encrypted_chunks, rsa_decrypted_chunks; //int verbosity; #ifndef WIN32 static int get_random_bytes (struct tgl_state *TLS, unsigned char *buf, int n) { int r = 0, h = open ("/dev/random", O_RDONLY | O_NONBLOCK); if (h >= 0) { r = read (h, buf, n); if (r > 0) { vlogprintf (E_DEBUG, "added %d bytes of real entropy to secure random numbers seed\n", r); } else { r = 0; } close (h); } if (r < n) { h = open ("/dev/urandom", O_RDONLY); if (h < 0) { return r; } int s = read (h, buf + r, n - r); close (h); if (s > 0) { r += s; } } if (r >= (int) sizeof (long)) { *(long *)buf ^= lrand48 (); srand48 (*(long *)buf); } return r; } #else static HCRYPTPROV hCryptoServiceProvider = 0; static int get_random_bytes (struct tgl_state *TLS, unsigned char *buf, int n) { if (hCryptoServiceProvider == 0) { /* Crypto init */ CryptAcquireContextA(&hCryptoServiceProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); } if (!CryptGenRandom(hCryptoServiceProvider, n, buf)) { return -1; } return n; } #endif /* RDTSC */ #if defined(__i386__) #define HAVE_RDTSC static __inline__ unsigned long long rdtsc (void) { unsigned long long int x; __asm__ volatile ("rdtsc" : "=A" (x)); return x; } #elif defined(__x86_64__) #define HAVE_RDTSC static __inline__ unsigned long long rdtsc (void) { unsigned hi, lo; __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); return ((unsigned long long) lo) | (((unsigned long long) hi) << 32); } #endif void tgl_prng_seed (struct tgl_state *TLS, const char *password_filename, int password_length) { struct timespec T; tgl_my_clock_gettime (CLOCK_REALTIME, &T); TGLC_rand_add (&T, sizeof (T), 4.0); #ifdef HAVE_RDTSC unsigned long long r = rdtsc (); TGLC_rand_add (&r, 8, 4.0); #endif unsigned short p = getpid (); TGLC_rand_add (&p, sizeof (p), 0.0); #ifndef WIN32 p = getppid (); TGLC_rand_add (&p, sizeof (p), 0.0); #endif unsigned char rb[32]; int s = get_random_bytes (TLS, rb, 32); if (s > 0) { TGLC_rand_add (rb, s, s); } memset (rb, 0, sizeof (rb)); if (password_filename && password_length > 0) { int fd = open (password_filename, O_RDONLY | O_BINARY); if (fd < 0) { vlogprintf (E_WARNING, "Warning: fail to open password file - \"%s\", %s.\n", password_filename, strerror(errno)); } else { unsigned char *a = talloc0 (password_length); int l = read (fd, a, password_length); if (l < 0) { vlogprintf (E_WARNING, "Warning: fail to read password file - \"%s\", %s.\n", password_filename, strerror(errno)); } else { vlogprintf (E_DEBUG, "read %d bytes from password file.\n", l); TGLC_rand_add (a, l, l); } close (fd); tfree_secure (a, password_length); } } TLS->TGLC_bn_ctx = TGLC_bn_ctx_new (); ensure_ptr (TLS->TGLC_bn_ctx); } int tgl_serialize_bignum (TGLC_bn *b, char *buffer, int maxlen) { int itslen = TGLC_bn_num_bytes (b); int reqlen; if (itslen < 254) { reqlen = itslen + 1; } else { reqlen = itslen + 4; } int newlen = (reqlen + 3) & -4; int pad = newlen - reqlen; reqlen = newlen; if (reqlen > maxlen) { return -reqlen; } if (itslen < 254) { *buffer++ = itslen; } else { *(int *)buffer = (itslen << 8) + 0xfe; buffer += 4; } int l = TGLC_bn_bn2bin (b, (unsigned char *)buffer); assert (l == itslen); buffer += l; while (pad --> 0) { *buffer++ = 0; } return reqlen; } long long tgl_do_compute_rsa_key_fingerprint (TGLC_rsa *key) { static char tempbuff[4096]; static unsigned char sha[20]; assert (TGLC_rsa_n (key) && TGLC_rsa_e (key)); int l1 = tgl_serialize_bignum (TGLC_rsa_n (key), tempbuff, 4096); assert (l1 > 0); int l2 = tgl_serialize_bignum (TGLC_rsa_e (key), tempbuff + l1, 4096 - l1); assert (l2 > 0 && l1 + l2 <= 4096); TGLC_sha1 ((unsigned char *)tempbuff, l1 + l2, sha); return *(long long *)(sha + 12); } void tgl_out_cstring (const char *str, long len) { assert (len >= 0 && len < (1 << 24)); assert ((char *) packet_ptr + len + 8 < (char *) (packet_buffer + PACKET_BUFFER_SIZE)); char *dest = (char *) packet_ptr; if (len < 254) { *dest++ = len; } else { *packet_ptr = (len << 8) + 0xfe; dest += 4; } memcpy (dest, str, len); dest += len; while ((long) dest & 3) { *dest++ = 0; } packet_ptr = (int *) dest; } void tgl_out_cstring_careful (const char *str, long len) { assert (len >= 0 && len < (1 << 24)); assert ((char *) packet_ptr + len + 8 < (char *) (packet_buffer + PACKET_BUFFER_SIZE)); char *dest = (char *) packet_ptr; if (len < 254) { dest++; if (dest != str) { memmove (dest, str, len); } dest[-1] = len; } else { dest += 4; if (dest != str) { memmove (dest, str, len); } *packet_ptr = (len << 8) + 0xfe; } dest += len; while ((long) dest & 3) { *dest++ = 0; } packet_ptr = (int *) dest; } void tgl_out_data (const void *data, long len) { assert (len >= 0 && len < (1 << 24) && !(len & 3)); assert ((char *) packet_ptr + len + 8 < (char *) (packet_buffer + PACKET_BUFFER_SIZE)); memcpy (packet_ptr, data, len); packet_ptr += len >> 2; } int *tgl_in_ptr, *tgl_in_end; int tgl_fetch_bignum (TGLC_bn *x) { int l = prefetch_strlen (); if (l < 0) { return l; } char *str = fetch_str (l); assert (TGLC_bn_bin2bn ((unsigned char *) str, l, x) == x); return l; } int tgl_pad_rsa_encrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, TGLC_bn *N, TGLC_bn *E) { int pad = (255000 - from_len - 32) % 255 + 32; int chunks = (from_len + pad) / 255; int bits = TGLC_bn_num_bits (N); assert (bits >= 2041 && bits <= 2048); assert (from_len > 0 && from_len <= 2550); assert (size >= chunks * 256); assert (TGLC_rand_pseudo_bytes ((unsigned char *) from + from_len, pad) >= 0); int i; TGLC_bn *x = TGLC_bn_new (); TGLC_bn *y = TGLC_bn_new (); assert(x); assert(y); rsa_encrypted_chunks += chunks; for (i = 0; i < chunks; i++) { TGLC_bn_bin2bn ((unsigned char *) from, 255, x); assert (TGLC_bn_mod_exp (y, x, E, N, TLS->TGLC_bn_ctx) == 1); unsigned l = 256 - TGLC_bn_num_bytes (y); assert (l <= 256); memset (to, 0, l); TGLC_bn_bn2bin (y, (unsigned char *) to + l); to += 256; } TGLC_bn_free (x); TGLC_bn_free (y); return chunks * 256; } int tgl_pad_rsa_decrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, TGLC_bn *N, TGLC_bn *D) { if (from_len < 0 || from_len > 0x1000 || (from_len & 0xff)) { return -1; } int chunks = (from_len >> 8); int bits = TGLC_bn_num_bits (N); assert (bits >= 2041 && bits <= 2048); assert (size >= chunks * 255); int i; TGLC_bn *x = TGLC_bn_new (); TGLC_bn *y = TGLC_bn_new (); assert(x); assert(y); for (i = 0; i < chunks; i++) { ++rsa_decrypted_chunks; TGLC_bn_bin2bn ((unsigned char *) from, 256, x); assert (TGLC_bn_mod_exp (y, x, D, N, TLS->TGLC_bn_ctx) == 1); int l = TGLC_bn_num_bytes (y); if (l > 255) { TGLC_bn_free (x); TGLC_bn_free (y); return -1; } assert (l >= 0 && l <= 255); memset (to, 0, 255 - l); TGLC_bn_bn2bin (y, (unsigned char *) to + 255 - l); to += 255; } TGLC_bn_free (x); TGLC_bn_free (y); return chunks * 255; } static unsigned char aes_key_raw[32], aes_iv[32]; static TGLC_aes_key aes_key; void tgl_init_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32], int encrypt) { static unsigned char buffer[64], hash[20]; memcpy (buffer, hidden_client_nonce, 32); memcpy (buffer + 32, server_nonce, 16); TGLC_sha1 (buffer, 48, aes_key_raw); memcpy (buffer + 32, hidden_client_nonce, 32); TGLC_sha1 (buffer, 64, aes_iv + 8); memcpy (buffer, server_nonce, 16); memcpy (buffer + 16, hidden_client_nonce, 32); TGLC_sha1 (buffer, 48, hash); memcpy (aes_key_raw + 20, hash, 12); memcpy (aes_iv, hash + 12, 8); memcpy (aes_iv + 28, hidden_client_nonce, 4); if (encrypt) { TGLC_aes_set_encrypt_key (aes_key_raw, 32*8, &aes_key); } else { TGLC_aes_set_decrypt_key (aes_key_raw, 32*8, &aes_key); } memset (aes_key_raw, 0, sizeof (aes_key_raw)); } void tgl_init_aes_auth (char auth_key[192], char msg_key[16], int encrypt) { static unsigned char buffer[48], hash[20]; // sha1_a = SHA1 (msg_key + substr (auth_key, 0, 32)); // sha1_b = SHA1 (substr (auth_key, 32, 16) + msg_key + substr (auth_key, 48, 16)); // sha1_с = SHA1 (substr (auth_key, 64, 32) + msg_key); // sha1_d = SHA1 (msg_key + substr (auth_key, 96, 32)); // aes_key = substr (sha1_a, 0, 8) + substr (sha1_b, 8, 12) + substr (sha1_c, 4, 12); // aes_iv = substr (sha1_a, 8, 12) + substr (sha1_b, 0, 8) + substr (sha1_c, 16, 4) + substr (sha1_d, 0, 8); memcpy (buffer, msg_key, 16); memcpy (buffer + 16, auth_key, 32); TGLC_sha1 (buffer, 48, hash); memcpy (aes_key_raw, hash, 8); memcpy (aes_iv, hash + 8, 12); memcpy (buffer, auth_key + 32, 16); memcpy (buffer + 16, msg_key, 16); memcpy (buffer + 32, auth_key + 48, 16); TGLC_sha1 (buffer, 48, hash); memcpy (aes_key_raw + 8, hash + 8, 12); memcpy (aes_iv + 12, hash, 8); memcpy (buffer, auth_key + 64, 32); memcpy (buffer + 32, msg_key, 16); TGLC_sha1 (buffer, 48, hash); memcpy (aes_key_raw + 20, hash + 4, 12); memcpy (aes_iv + 20, hash + 16, 4); memcpy (buffer, msg_key, 16); memcpy (buffer + 16, auth_key + 96, 32); TGLC_sha1 (buffer, 48, hash); memcpy (aes_iv + 24, hash, 8); if (encrypt) { TGLC_aes_set_encrypt_key (aes_key_raw, 32*8, &aes_key); } else { TGLC_aes_set_decrypt_key (aes_key_raw, 32*8, &aes_key); } memset (aes_key_raw, 0, sizeof (aes_key_raw)); } int tgl_pad_aes_encrypt (char *from, int from_len, char *to, int size) { int padded_size = (from_len + 15) & -16; assert (from_len > 0 && padded_size <= size); if (from_len < padded_size) { assert (TGLC_rand_pseudo_bytes ((unsigned char *) from + from_len, padded_size - from_len) >= 0); } TGLC_aes_ige_encrypt ((unsigned char *) from, (unsigned char *) to, padded_size, &aes_key, aes_iv, 1); return padded_size; } int tgl_pad_aes_decrypt (char *from, int from_len, char *to, int size) { if (from_len <= 0 || from_len > size || (from_len & 15)) { return -1; } TGLC_aes_ige_encrypt ((unsigned char *) from, (unsigned char *) to, from_len, &aes_key, aes_iv, 0); return from_len; } ================================================ FILE: mtproto-common.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Nikolay Durov, Andrey Lopatin 2012-2013 Vitaly Valtman 2013-2015 */ #ifndef __MTPROTO_COMMON_H__ #define __MTPROTO_COMMON_H__ #include #include "crypto/rsa_pem.h" #include "crypto/bn.h" #include #include #if defined(_MSC_VER) || defined(__MINGW32__) #define INT64_PRINTF_MODIFIER "I64" #else #define INT64_PRINTF_MODIFIER "ll" #endif //#include "interface.h" #include "tools.h" #include "auto/constants.h" #include "tgl.h" #include "tgl-inner.h" /* DH key exchange protocol data structures */ #define CODE_req_pq 0x60469778 #define CODE_resPQ 0x05162463 #define CODE_req_DH_params 0xd712e4be #define CODE_p_q_inner_data 0x83c95aec #define CODE_p_q_inner_data_temp 0x3c6a84d4 #define CODE_server_DH_inner_data 0xb5890dba #define CODE_server_DH_params_fail 0x79cb045d #define CODE_server_DH_params_ok 0xd0e8075c #define CODE_set_client_DH_params 0xf5045f1f #define CODE_client_DH_inner_data 0x6643b654 #define CODE_dh_gen_ok 0x3bcbf734 #define CODE_dh_gen_retry 0x46dc1fb9 #define CODE_dh_gen_fail 0xa69dae02 #define CODE_bind_auth_key_inner 0x75a3f765 /* service messages */ #define CODE_rpc_result 0xf35c6d01 #define CODE_rpc_error 0x2144ca19 #define CODE_msg_container 0x73f1f8dc #define CODE_msg_copy 0xe06046b2 #define CODE_msgs_ack 0x62d6b459 #define CODE_bad_msg_notification 0xa7eff811 #define CODE_bad_server_salt 0xedab447b #define CODE_msgs_state_req 0xda69fb52 #define CODE_msgs_state_info 0x04deb57d #define CODE_msgs_all_info 0x8cc0d131 #define CODE_new_session_created 0x9ec20908 #define CODE_msg_resend_req 0x7d861a08 #define CODE_ping 0x7abe77ec #define CODE_pong 0x347773c5 #define CODE_destroy_session 0xe7512126 #define CODE_destroy_session_ok 0xe22045fc #define CODE_destroy_session_none 0x62d350c9 #define CODE_destroy_sessions 0x9a6face8 #define CODE_destroy_sessions_res 0xa8164668 #define CODE_get_future_salts 0xb921bd04 #define CODE_future_salt 0x0949d9dc #define CODE_future_salts 0xae500895 #define CODE_rpc_drop_answer 0x58e4a740 #define CODE_rpc_answer_unknown 0x5e2ad36e #define CODE_rpc_answer_dropped_running 0xcd78e586 #define CODE_rpc_answer_dropped 0xa43ad8b7 #define CODE_msg_detailed_info 0x276d3ec6 #define CODE_msg_new_detailed_info 0x809db6df #define CODE_ping_delay_disconnect 0xf3427b8c #define CODE_gzip_packed 0x3072cfa1 #define CODE_input_peer_notify_settings_old 0x3cf4b1be #define CODE_peer_notify_settings_old 0xddbcd4a5 #define CODE_user_profile_photo_old 0x990d1493 #define CODE_config_old 0x232d5905 #define CODE_msg_new_detailed_info 0x809db6df #define CODE_msg_detailed_info 0x276d3ec6 /* not really a limit, for struct encrypted_message only */ // #define MAX_MESSAGE_INTS 16384 #define MAX_MESSAGE_INTS 1048576 #define MAX_PROTO_MESSAGE_INTS 1048576 #define PACKET_BUFFER_SIZE (16384 * 100 + 16) // temp fix #pragma pack(push,4) struct encrypted_message { // unencrypted header long long auth_key_id; char msg_key[16]; // encrypted part, starts with encrypted header long long server_salt; long long session_id; // long long auth_key_id2; // removed // first message follows long long msg_id; int seq_no; int msg_len; // divisible by 4 int message[MAX_MESSAGE_INTS]; }; #pragma pack(pop) //TGLC_bn_ctx *bn_ctx; void tgl_prng_seed (struct tgl_state *TLS, const char *password_filename, int password_length); int tgl_serialize_bignum (TGLC_bn *b, char *buffer, int maxlen); long long tgl_do_compute_rsa_key_fingerprint (TGLC_rsa *key); #define packet_buffer tgl_packet_buffer #define packet_ptr tgl_packet_ptr extern int *tgl_packet_buffer; extern int *tgl_packet_ptr; static inline void out_ints (const int *what, int len) { assert (packet_ptr + len <= packet_buffer + PACKET_BUFFER_SIZE); memcpy (packet_ptr, what, len * 4); packet_ptr += len; } static inline void out_int (int x) { assert (packet_ptr + 1 <= packet_buffer + PACKET_BUFFER_SIZE); *packet_ptr++ = x; } static inline void out_long (long long x) { assert (packet_ptr + 2 <= packet_buffer + PACKET_BUFFER_SIZE); *(long long *)packet_ptr = x; packet_ptr += 2; } static inline void out_double (double x) { assert (packet_ptr + 2 <= packet_buffer + PACKET_BUFFER_SIZE); *(double *)packet_ptr = x; packet_ptr += 2; } static inline void clear_packet (void) { packet_ptr = packet_buffer; } void tgl_out_cstring (const char *str, long len); void tgl_out_cstring_careful (const char *str, long len); void tgl_out_data (const void *data, long len); #define out_cstring tgl_out_cstring #define out_cstring_careful tgl_out_cstring_careful #define out_data tgl_out_data static inline void out_string (const char *str) { out_cstring (str, strlen (str)); } static inline void out_bignum (TGLC_bn *n) { int l = tgl_serialize_bignum (n, (char *)packet_ptr, (PACKET_BUFFER_SIZE - (packet_ptr - packet_buffer)) * 4); assert (l > 0); packet_ptr += l >> 2; } #define in_ptr tgl_in_ptr #define in_end tgl_in_end extern int *tgl_in_ptr, *tgl_in_end; //void fetch_pts (void); //void fetch_qts (void); //void fetch_date (void); //void fetch_seq (void); static inline int prefetch_strlen (void) { if (in_ptr >= in_end) { return -1; } unsigned l = *in_ptr; if ((l & 0xff) < 0xfe) { l &= 0xff; return (in_end >= in_ptr + (l >> 2) + 1) ? (int)l : -1; } else if ((l & 0xff) == 0xfe) { l >>= 8; return (l >= 254 && in_end >= in_ptr + ((l + 7) >> 2)) ? (int)l : -1; } else { return -1; } } static inline char *fetch_str (int len) { assert (len >= 0); if (len < 254) { char *str = (char *) in_ptr + 1; in_ptr += 1 + (len >> 2); return str; } else { char *str = (char *) in_ptr + 4; in_ptr += (len + 7) >> 2; return str; } } static inline char *fetch_str_dup (void) { int l = prefetch_strlen (); assert (l >= 0); int i; char *s = fetch_str (l); for (i = 0; i < l; i++) { if (!s[i]) { break; } } char *r = talloc (i + 1); memcpy (r, s, i); r[i] = 0; return r; } static inline int fetch_update_str (char **s) { if (!*s) { *s = fetch_str_dup (); return 1; } int l = prefetch_strlen (); char *r = fetch_str (l); if (memcmp (*s, r, l) || (*s)[l]) { tfree_str (*s); *s = talloc (l + 1); memcpy (*s, r, l); (*s)[l] = 0; return 1; } return 0; } static inline int fetch_update_int (int *value) { if (*value == *in_ptr) { in_ptr ++; return 0; } else { *value = *(in_ptr ++); return 1; } } static inline int fetch_update_long (long long *value) { if (*value == *(long long *)in_ptr) { in_ptr += 2; return 0; } else { *value = *(long long *)(in_ptr); in_ptr += 2; return 1; } } static inline int set_update_int (int *value, int new_value) { if (*value == new_value) { return 0; } else { *value = new_value; return 1; } } static inline void fetch_skip (int n) { in_ptr += n; assert (in_ptr <= in_end); } static inline void fetch_skip_str (void) { int l = prefetch_strlen (); assert (l >= 0); fetch_str (l); } static inline long have_prefetch_ints (void) { return in_end - in_ptr; } int tgl_fetch_bignum (TGLC_bn *x); #define fetch_bignum tgl_fetch_bignum static inline int fetch_int (void) { assert (in_ptr + 1 <= in_end); return *(in_ptr ++); } static inline int fetch_bool (void) { assert (in_ptr + 1 <= in_end); assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false); return *(in_ptr ++) == (int)CODE_bool_true; } static inline int prefetch_int (void) { assert (in_ptr < in_end); return *(in_ptr); } static inline void prefetch_data (void *data, int size) { assert (in_ptr + (size >> 2) <= in_end); memcpy (data, in_ptr, size); } static inline void fetch_data (void *data, int size) { assert (in_ptr + (size >> 2) <= in_end); memcpy (data, in_ptr, size); assert (!(size & 3)); in_ptr += (size >> 2); } static inline long long fetch_long (void) { assert (in_ptr + 2 <= in_end); long long r = *(long long *)in_ptr; in_ptr += 2; return r; } static inline double fetch_double (void) { assert (in_ptr + 2 <= in_end); double r = *(double *)in_ptr; in_ptr += 2; return r; } static inline void fetch_ints (void *data, int count) { assert (in_ptr + count <= in_end); memcpy (data, in_ptr, 4 * count); in_ptr += count; } static inline void fetch256 (void *buf) { int l = prefetch_strlen (); assert (l >= 0); char *s = fetch_str (l); if (l < 256) { memcpy (buf + 256 - l, s, l); memset (buf, 0, 256 - l); } else { memcpy (buf, s + (l - 256), 256); } } static inline int in_remaining (void) { return 4 * (in_end - in_ptr); } //int get_random_bytes (unsigned char *buf, int n); int tgl_pad_rsa_encrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, TGLC_bn *N, TGLC_bn *E); int tgl_pad_rsa_decrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, TGLC_bn *N, TGLC_bn *D); //extern long long rsa_encrypted_chunks, rsa_decrypted_chunks; //extern unsigned char aes_key_raw[32], aes_iv[32]; //extern TGLC_aes_key aes_key; void tgl_init_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32], int encrypt); void tgl_init_aes_auth (char auth_key[192], char msg_key[16], int encrypt); int tgl_pad_aes_encrypt (char *from, int from_len, char *to, int size); int tgl_pad_aes_decrypt (char *from, int from_len, char *to, int size); /* static inline void hexdump_in (void) { hexdump (in_ptr, in_end); } static inline void hexdump_out (void) { hexdump (packet_buffer, packet_ptr); }*/ #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 #define CLOCK_MONOTONIC 1 #endif #endif ================================================ FILE: mtproto-key.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2015 */ const unsigned char _mtproto_default_key[] = { 0xc1, 0x50, 0x02, 0x3e, 0x2f, 0x70, 0xdb, 0x79, 0x85, 0xde, 0xd0, 0x64, 0x75, 0x9c, 0xfe, 0xcf, 0x0a, 0xf3, 0x28, 0xe6, 0x9a, 0x41, 0xda, 0xf4, 0xd6, 0xf0, 0x1b, 0x53, 0x81, 0x35, 0xa6, 0xf9, 0x1f, 0x8f, 0x8b, 0x2a, 0x0e, 0xc9, 0xba, 0x97, 0x20, 0xce, 0x35, 0x2e, 0xfc, 0xf6, 0xc5, 0x68, 0x0f, 0xfc, 0x42, 0x4b, 0xd6, 0x34, 0x86, 0x49, 0x02, 0xde, 0x0b, 0x4b, 0xd6, 0xd4, 0x9f, 0x4e, 0x58, 0x02, 0x30, 0xe3, 0xae, 0x97, 0xd9, 0x5c, 0x8b, 0x19, 0x44, 0x2b, 0x3c, 0x0a, 0x10, 0xd8, 0xf5, 0x63, 0x3f, 0xec, 0xed, 0xd6, 0x92, 0x6a, 0x7f, 0x6d, 0xab, 0x0d, 0xdb, 0x7d, 0x45, 0x7f, 0x9e, 0xa8, 0x1b, 0x84, 0x65, 0xfc, 0xd6, 0xff, 0xfe, 0xed, 0x11, 0x40, 0x11, 0xdf, 0x91, 0xc0, 0x59, 0xca, 0xed, 0xaf, 0x97, 0x62, 0x5f, 0x6c, 0x96, 0xec, 0xc7, 0x47, 0x25, 0x55, 0x69, 0x34, 0xef, 0x78, 0x1d, 0x86, 0x6b, 0x34, 0xf0, 0x11, 0xfc, 0xe4, 0xd8, 0x35, 0xa0, 0x90, 0x19, 0x6e, 0x9a, 0x5f, 0x0e, 0x44, 0x49, 0xaf, 0x7e, 0xb6, 0x97, 0xdd, 0xb9, 0x07, 0x64, 0x94, 0xca, 0x5f, 0x81, 0x10, 0x4a, 0x30, 0x5b, 0x6d, 0xd2, 0x76, 0x65, 0x72, 0x2c, 0x46, 0xb6, 0x0e, 0x5d, 0xf6, 0x80, 0xfb, 0x16, 0xb2, 0x10, 0x60, 0x7e, 0xf2, 0x17, 0x65, 0x2e, 0x60, 0x23, 0x6c, 0x25, 0x5f, 0x6a, 0x28, 0x31, 0x5f, 0x40, 0x83, 0xa9, 0x67, 0x91, 0xd7, 0x21, 0x4b, 0xf6, 0x4c, 0x1d, 0xf4, 0xfd, 0x0d, 0xb1, 0x94, 0x4f, 0xb2, 0x6a, 0x2a, 0x57, 0x03, 0x1b, 0x32, 0xee, 0xe6, 0x4a, 0xd1, 0x5a, 0x8b, 0xa6, 0x88, 0x85, 0xcd, 0xe7, 0x4a, 0x5b, 0xfc, 0x92, 0x0f, 0x6a, 0xbf, 0x59, 0xba, 0x5c, 0x75, 0x50, 0x63, 0x73, 0xe7, 0x13, 0x0f, 0x90, 0x42, 0xda, 0x92, 0x21, 0x79, 0x25, 0x1f }; const unsigned int _mtproto_default_key_len = 256; const long long _mtproto_default_e = 65537; const unsigned char *tglmp_get_default_key (void) { return _mtproto_default_key; } unsigned int tglmp_get_default_key_len (void) { return _mtproto_default_key_len; } long long tglmp_get_default_e (void) { return _mtproto_default_e; } ================================================ FILE: mtproto-key.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2015 */ #ifndef __MTPROTO_KEY_H__ #define __MTPROTO_KEY_H__ const unsigned char *tglmp_get_default_key (void); unsigned int tglmp_get_default_key_len (void); long long tglmp_get_default_e (void); #endif ================================================ FILE: mtproto-utils.c ================================================ #include "config.h" #include "crypto/bn.h" #include "tl-parser/portable_endian.h" #include "tgl.h" #include "tools.h" #include "mtproto-utils.h" static unsigned long long gcd (unsigned long long a, unsigned long long b) { return b ? gcd (b, a % b) : a; } static int check_prime (struct tgl_state *TLS, TGLC_bn *p) { int r = TGLC_bn_is_prime (p, /* "use default" */ 0, 0, TLS->TGLC_bn_ctx, 0); ensure (r >= 0); return r; } // Complete set of checks see at https://core.telegram.org/mtproto/security_guidelines // Checks that (p,g) is acceptable pair for DH int tglmp_check_DH_params (struct tgl_state *TLS, TGLC_bn *p, int g) { if (g < 2 || g > 7) { return -1; } if (TGLC_bn_num_bits (p) != 2048) { return -1; } TGLC_bn *t = TGLC_bn_new (); TGLC_bn *dh_g = TGLC_bn_new (); ensure (TGLC_bn_set_word (dh_g, 4 * g)); ensure (TGLC_bn_mod (t, p, dh_g, TLS->TGLC_bn_ctx)); int x = TGLC_bn_get_word (t); assert (x >= 0 && x < 4 * g); TGLC_bn_free (dh_g); int res = 0; switch (g) { case 2: if (x != 7) { res = -1; } break; case 3: if (x % 3 != 2) { res = -1; } break; case 4: break; case 5: if (x % 5 != 1 && x % 5 != 4) { res = -1; } break; case 6: if (x != 19 && x != 23) { res = -1; } break; case 7: if (x % 7 != 3 && x % 7 != 5 && x % 7 != 6) { res = -1; } break; } if (res < 0 || !check_prime (TLS, p)) { TGLC_bn_free (t); return -1; } TGLC_bn *b = TGLC_bn_new (); ensure (TGLC_bn_set_word (b, 2)); ensure (TGLC_bn_div (t, 0, p, b, TLS->TGLC_bn_ctx)); if (!check_prime (TLS, t)) { res = -1; } TGLC_bn_free (b); TGLC_bn_free (t); return res; } // checks that g_a is acceptable for DH int tglmp_check_g_a (struct tgl_state *TLS, TGLC_bn *p, TGLC_bn *g_a) { if (TGLC_bn_num_bytes (g_a) > 256) { return -1; } if (TGLC_bn_num_bits (g_a) < 2048 - 64) { return -1; } if (TGLC_bn_cmp (p, g_a) <= 0) { return -1; } TGLC_bn *dif = TGLC_bn_new (); TGLC_bn_sub (dif, p, g_a); if (TGLC_bn_num_bits (dif) < 2048 - 64) { TGLC_bn_free (dif); return -1; } TGLC_bn_free (dif); return 0; } static unsigned long long BN2ull (TGLC_bn *b) { if (sizeof (unsigned long) == 8) { return TGLC_bn_get_word (b); } else if (sizeof (unsigned long long) == 8) { assert (0); // As long as nobody ever uses this code, assume it is broken. unsigned long long tmp; /* Here be dragons, but it should be okay due to be64toh */ TGLC_bn_bn2bin (b, (unsigned char *) &tmp); return be64toh (tmp); } else { assert (0); } } static void ull2BN (TGLC_bn *b, unsigned long long val) { if (sizeof (unsigned long) == 8 || val < (1ll << 32)) { TGLC_bn_set_word (b, val); } else if (sizeof (unsigned long long) == 8) { assert (0); // As long as nobody ever uses this code, assume it is broken. htobe64(val); /* Here be dragons, but it should be okay due to htobe64 */ TGLC_bn_bin2bn ((unsigned char *) &val, 8, b); } else { assert (0); } } int bn_factorize (TGLC_bn *pq, TGLC_bn *p, TGLC_bn *q) { // Should work in any case // Rewrite this code unsigned long long what = BN2ull (pq); int it = 0; unsigned long long g = 0; int i; for (i = 0; i < 3 || it < 1000; i++) { int q = ((rand() & 15) + 17) % what; unsigned long long x = (long long)rand () % (what - 1) + 1, y = x; int lim = 1 << (i + 18); int j; for (j = 1; j < lim; j++) { ++it; unsigned long long a = x, b = x, c = q; while (b) { if (b & 1) { c += a; if (c >= what) { c -= what; } } a += a; if (a >= what) { a -= what; } b >>= 1; } x = c; unsigned long long z = x < y ? what + x - y : x - y; g = gcd (z, what); if (g != 1) { break; } if (!(j & (j - 1))) { y = x; } } if (g > 1 && g < what) break; } assert (g > 1 && g < what); unsigned long long p1 = g; unsigned long long p2 = what / g; if (p1 > p2) { unsigned long long t = p1; p1 = p2; p2 = t; } ull2BN (p, p1); ull2BN (q, p2); return 0; } ================================================ FILE: mtproto-utils.h ================================================ #ifndef __MTPROTO_UTILS_H__ #define __MTPROTO_UTILS_H__ #include "crypto/bn.h" int tglmp_check_DH_params (struct tgl_state *TLS, TGLC_bn *p, int g); int tglmp_check_g_a (struct tgl_state *TLS, TGLC_bn *p, TGLC_bn *g_a); int bn_factorize (TGLC_bn *pq, TGLC_bn *p, TGLC_bn *q); #endif ================================================ FILE: mtproto.tl ================================================ ---types--- resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:(Vector long) = ResPQ; server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params; server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params; p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data; p_q_inner_data_temp#3c6a84d4 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data; client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data; dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer; dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer; dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer; server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data; ---functions--- req_pq#60469778 nonce:int128 = ResPQ; req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params; set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer; ================================================ FILE: no-preview.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ // Just sample jpg file 90x90 int thumb_file_size = (82 * 6 - 2) * 4; int thumb_file [] = { 0xe0ffd8ff, 0x464a1000, 0x01004649, 0x64000101, 0x00006400, 0xa002e2ff, 0x5f434349, 0x464f5250, 0x00454c49, 0x00000101, 0x636c9002, 0x3004736d, 0x6e6d0000, 0x47527274, 0x59582042, 0xdd07205a, 0x04000b00, 0x1b001600, 0x63612400, 0x50417073, 0x00004c50, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0100d6f6, 0x00000000, 0x636c2dd3, 0x0000736d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x65640b00, 0x00006373, 0x00000801, 0x70633800, 0x00007472, 0x00004001, 0x74774e00, 0x00007470, 0x00009001, 0x68631400, 0x00006461, 0x0000a401, 0x58722c00, 0x00005a59, 0x0000d001, 0x58621400, 0x00005a59, 0x0000e401, 0x58671400, 0x00005a59, 0x0000f801, 0x54721400, 0x00004352, 0x00000c02, 0x54672000, 0x00004352, 0x00002c02, 0x54622000, 0x00004352, 0x00004c02, 0x68632000, 0x00006d72, 0x00006c02, 0x6c6d2400, 0x00006375, 0x00000000, 0x00000100, 0x6e650c00, 0x00005355, 0x00001c00, 0x73001c00, 0x47005200, 0x20004200, 0x75006200, 0x6c006900, 0x2d007400, 0x6e006900, 0x6c6d0000, 0x00006375, 0x00000000, 0x00000100, 0x6e650c00, 0x00005355, 0x00003200, 0x4e001c00, 0x20006f00, 0x6f006300, 0x79007000, 0x69007200, 0x68006700, 0x2c007400, 0x75002000, 0x65007300, 0x66002000, 0x65007200, 0x6c006500, 0x00007900, 0x59580000, 0x0000205a, 0x00000000, 0x0100d6f6, 0x00000000, 0x66732dd3, 0x00003233, 0x01000000, 0x00004a0c, 0xffffe305, 0x00002af3, 0x00009b07, 0xffff87fd, 0xffffa2fb, 0x0000a3fd, 0x0000d803, 0x595894c0, 0x0000205a, 0x00000000, 0x0000946f, 0x0000ee38, 0x59589003, 0x0000205a, 0x00000000, 0x00009d24, 0x0000830f, 0x5958beb6, 0x0000205a, 0x00000000, 0x0000a562, 0x000090b7, 0x6170de18, 0x00006172, 0x03000000, 0x02000000, 0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013, 0x61705b0a, 0x00006172, 0x03000000, 0x02000000, 0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013, 0x61705b0a, 0x00006172, 0x03000000, 0x02000000, 0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013, 0x68635b0a, 0x00006d72, 0x03000000, 0x00000000, 0x0000d7a3, 0x00007b54, 0x0000cd4c, 0x00009a99, 0x00006626, 0xdbff5c0f, 0x14004300, 0x0f120f0e, 0x1112140d, 0x14161712, 0x21331f18, 0x1f1c1c1f, 0x252f2d3f, 0x4e414a33, 0x4841494d, 0x765c5246, 0x6f575264, 0x66484658, 0x7a6f688c, 0x8485847d, 0x9b91634f, 0x769a808f, 0xff7f8481, 0x014300db, 0x1f171716, 0x213c1f1b, 0x547f3c21, 0x7f7f5448, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x1100c0ff, 0x005a0008, 0x2201035a, 0x01110200, 0xff011103, 0x001900c4, 0x01010101, 0x00000101, 0x00000000, 0x00000000, 0x02030400, 0xc4ff0605, 0x00103600, 0x02010401, 0x06050304, 0x00000306, 0x01000000, 0x11030200, 0x05211204, 0x13514131, 0x32146122, 0x23918171, 0x72423424, 0x432515a1, 0xa2827444, 0xc4fff0b3, 0x01011400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1400c4ff, 0x00000111, 0x00000000, 0x00000000, 0x00000000, 0xdaff0000, 0x01030c00, 0x03110200, 0x003f0011, 0x404434fb, 0xbcb4875c, 0x006b38b0, 0x03dcdb12, 0xf4637f74, 0xe519f153, 0x09d7c5c7, 0x47d29160, 0x20692f18, 0xd06d786a, 0x53f7f922, 0x17b3e260, 0x2fe8668c, 0x1786a473, 0x9775efbd, 0xe917e43a, 0x1d0a1bb0, 0x114d0f82, 0x14651110, 0x35f299ed, 0xe9b09680, 0xf5a4fc2f, 0xe975bd03, 0xb506737b, 0x04444440, 0x5c444044, 0x8e8dedbd, 0xc61adc7b, 0x689c738b, 0x92a0dc01, 0x58e2b77f, 0x7bfb37d1, 0xb5b5e79d, 0xdbf968cc, 0xead3f48d, 0x38ed1313, 0xdea77c86, 0xae089963, 0xc743435a, 0x403fe4ce, 0x392ee1b9, 0xed39e718, 0xd6517e2d, 0x7fc4aa03, 0xb7ad7590, 0x77e7e6ab, 0x34bf705d, 0x7c77ca53, 0x3dea1299, 0x7fb0bcf4, 0x241fadc5, 0x95a7a816, 0x13fbe6f3, 0x3182b135, 0xd1b4b224, 0x1b0d48a2, 0xbf9d26d8, 0x82dc3640, 0x63569a2a, 0xbbd224c3, 0xb9b4714c, 0x1680aec6, 0x3d311856, 0x9b59be91, 0x09876ca6, 0x61d86564, 0x5a9f06d2, 0x36f51b0d, 0x8682e476, 0xacb1b131, 0xd1584363, 0x00456b4d, 0x22d2053b, 0x22202202, 0xf3f30222, 0xe3e513e5, 0xf1e6e1f0, 0x2380496e, 0x5fdcdb68, 0x549b3a27, 0x825e6a6c, 0x6522028b, 0xaf91ccc8, 0x341cf26b, 0x58dbc4b5, 0xf2289add, 0x0854ddbd, 0x0b9247d5, 0xf02b5c54, 0x3f917f92, 0xaf56affd, 0xe3760637, 0x05cebde0, 0xed4c76ce, 0x3cef1b63, 0x7fd8aff8, 0xa0c902ea, 0x7e730d0a, 0x435834f3, 0x26edbb76, 0xd3ec00fd, 0x76d48efa, 0xa8560f2d, 0x0e766331, 0xd319993c, 0x20243209, 0x61b7e6c8, 0x998331d0, 0x640ee802, 0x47a3d493, 0xfab99413, 0x4fd871f1, 0xe9443792, 0x627e051c, 0xd8f3051c, 0x2f28f558, 0x64b51745, 0x1b2bfee3, 0xb8783953, 0x9900fff6, 0xd8176a65, 0x5a3bf56a, 0x1b331fdb, 0x64b3572f, 0xd59a3643, 0xaf3abce1, 0x11dd20bd, 0x01111110, 0x5c141011, 0xb3e3083f, 0xd9b19cc4, 0x17edb20e, 0xa78e9aa1, 0x4ef4de06, 0x00c0bfe7, 0x7e1e442d, 0x9221fe38, 0xedb5c7dc, 0x6338078a, 0x62495b8d, 0xc11d9b8c, 0x49e81b16, 0x51d02bea, 0x3eb86d70, 0xc8bc4f13, 0xa10ec758, 0xd40751c0, 0x5ac94710, 0xc4c8b080, 0x95492b83, 0x975ee696, 0xb7bd96b4, 0x17379cce, 0x82e856e8, 0xe4c2c82a, 0x398e935f, 0x632437ea, 0x7c9c87d2, 0xdc1ddb7c, 0x65a80a48, 0x2309f164, 0x51fab475, 0x081dc11d, 0xda45573b, 0x6622f3f3, 0x48f1b214, 0x676c4edb, 0x243468c7, 0x00ffde60, 0xf1630350, 0xa0076c1d, 0x8f2c0c8b, 0x2383c26b, 0x361a8f4e, 0xaceea6c9, 0x01dd5a5d, 0x11111011, 0xc3780c04, 0xbf093ee2, 0xc7972c0b, 0x00d99040, 0xc0c20eb7, 0x659d3bd4, 0x269ab85e, 0x468e114f, 0x11ad4fdb, 0x83d083d8, 0x8c52f4bd, 0x3c9664bf, 0xa4f9c77c, 0x22a68876, 0xadb18784, 0xf480be83, 0x885a00ea, 0x220e0a88, 0xc303e4f6, 0xc866e058, 0xdddbd661, 0xdf395db1, 0xbad64343, 0xe6e65b03, 0x668e81c3, 0xad619e98, 0xeeb94563, 0xd4d19a3c, 0x3316ce95, 0x9d65f1e1, 0x3bf324fe, 0x0e468f53, 0xc386068c, 0xa89e24f7, 0xf0c7c73b, 0xb60e391f, 0x1b8827cb, 0x58601954, 0xc54f90f9, 0x80886ec5, 0x88088888, 0x1b7bb980, 0xb4c71c23, 0xe6148e39, 0xb12358b8, 0xbd08225d, 0x0ffef085, 0x72b4f025, 0x635ce389, 0xb90277e4, 0x0d05e000, 0x9bf9dbb9, 0x8e749fbc, 0x7ee6abbf, 0x4ddbf4af, 0x728df7f3, 0x10b59adf, 0xe3c38f49, 0xb23c638a, 0xdb3d9349, 0x66899a64, 0x00004dd5, 0xf51b5adf, 0x2220a255, 0xd9ff0f22}; ================================================ FILE: queries-encrypted.c ================================================ /* {{{ Encrypt decrypted */ static int *encr_extra; static int *encr_ptr; static int *encr_end; static char *encrypt_decrypted_message (struct tgl_secret_chat *E) { static int msg_key[4]; static unsigned char sha1a_buffer[20]; static unsigned char sha1b_buffer[20]; static unsigned char sha1c_buffer[20]; static unsigned char sha1d_buffer[20]; int x = *(encr_ptr); assert (x >= 0 && !(x & 3)); TGLC_sha1 ((void *)encr_ptr, 4 + x, sha1a_buffer); memcpy (msg_key, sha1a_buffer + 4, 16); static unsigned char buf[64]; memcpy (buf, msg_key, 16); memcpy (buf + 16, E->key, 32); TGLC_sha1 (buf, 48, sha1a_buffer); memcpy (buf, E->key + 8, 16); memcpy (buf + 16, msg_key, 16); memcpy (buf + 32, E->key + 12, 16); TGLC_sha1 (buf, 48, sha1b_buffer); memcpy (buf, E->key + 16, 32); memcpy (buf + 32, msg_key, 16); TGLC_sha1 (buf, 48, sha1c_buffer); memcpy (buf, msg_key, 16); memcpy (buf + 16, E->key + 24, 32); TGLC_sha1 (buf, 48, sha1d_buffer); static unsigned char key[32]; memcpy (key, sha1a_buffer + 0, 8); memcpy (key + 8, sha1b_buffer + 8, 12); memcpy (key + 20, sha1c_buffer + 4, 12); static unsigned char iv[32]; memcpy (iv, sha1a_buffer + 8, 12); memcpy (iv + 12, sha1b_buffer + 0, 8); memcpy (iv + 20, sha1c_buffer + 16, 4); memcpy (iv + 24, sha1d_buffer + 0, 8); TGLC_aes_key aes_key; TGLC_aes_set_encrypt_key (key, 256, &aes_key); TGLC_aes_ige_encrypt ((void *)encr_ptr, (void *)encr_ptr, 4 * (encr_end - encr_ptr), &aes_key, iv, 1); memset (&aes_key, 0, sizeof (aes_key)); return (void *)msg_key; } static void encr_start (void) { encr_extra = packet_ptr; packet_ptr += 1; // str len packet_ptr += 2; // fingerprint packet_ptr += 4; // msg_key packet_ptr += 1; // len } static void encr_finish (struct tgl_secret_chat *E) { int l = packet_ptr - (encr_extra + 8); while (((packet_ptr - encr_extra) - 3) & 3) { int t; tglt_secure_random (&t, 4); out_int (t); } *encr_extra = ((packet_ptr - encr_extra) - 1) * 4 * 256 + 0xfe; encr_extra ++; *(long long *)encr_extra = E->key_fingerprint; encr_extra += 2; encr_extra[4] = l * 4; encr_ptr = encr_extra + 4; encr_end = packet_ptr; memcpy (encr_extra, encrypt_decrypted_message (E), 16); } /* }}} */ void tgl_do_send_encr_action (struct tgl_state *TLS, struct tgl_secret_chat *E, struct tl_ds_decrypted_message_action *A) { long long t; tglt_secure_random (&t, 8); int date = time (0); struct tgl_message_id id = tgl_peer_id_to_random_msg_id (E->id); tgl_peer_id_t from_id = TLS->our_id; bl_do_edit_message_encr (TLS, &id, &from_id, &E->id, &date, NULL, 0, NULL, A, NULL, TGLMF_PENDING | TGLMF_OUT | TGLMF_UNREAD | TGLMF_CREATE | TGLMF_CREATED | TGLMF_ENCRYPTED); struct tgl_message *M = tgl_message_get (TLS, &id); assert (M); tgl_do_send_msg (TLS, M, 0, 0); } void tgl_do_send_encr_chat_layer (struct tgl_state *TLS, struct tgl_secret_chat *E) { static struct tl_ds_decrypted_message_action A; A.magic = CODE_decrypted_message_action_notify_layer; int layer = TGL_ENCRYPTED_LAYER; A.layer = &layer; tgl_do_send_encr_action (TLS, E, &A); } void tgl_do_set_encr_chat_ttl (struct tgl_state *TLS, struct tgl_secret_chat *E, int ttl, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { static struct tl_ds_decrypted_message_action A; A.magic = CODE_decrypted_message_action_set_message_t_t_l; A.layer = &ttl; tgl_do_send_encr_action (TLS, E, &A); } /* {{{ Seng msg (plain text, encrypted) */ static int msg_send_encr_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_message *M = q->extra; assert (M->flags & TGLMF_ENCRYPTED); if (M->flags & TGLMF_PENDING) { bl_do_edit_message_encr (TLS, &M->permanent_id, NULL, NULL, &M->date, NULL, 0, NULL, NULL, NULL, M->flags ^ TGLMF_PENDING); bl_do_msg_update (TLS, &M->permanent_id); } if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M); } return 0; } static int msg_send_encr_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { struct tgl_message *M = q->extra; tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); if (P && P->encr_chat.state != sc_deleted && error_code == 400) { if (strncmp (error, "ENCRYPTION_DECLINED", 19) == 0) { bl_do_peer_delete (TLS, P->id); } } if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 0, M); } if (M) { bl_do_message_delete (TLS, &M->permanent_id); } return 0; } static struct query_methods msg_send_encr_methods = { .on_answer = msg_send_encr_on_answer, .on_error = msg_send_encr_on_error, .type = TYPE_TO_PARAM(messages_sent_encrypted_message), .name = "send encrypted (message)", .timeout = 0, }; /* }}} */ void tgl_do_send_encr_msg_action (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); if (!P || P->encr_chat.state != sc_ok) { vlogprintf (E_WARNING, "Unknown encrypted chat\n"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } assert (M->flags & TGLMF_ENCRYPTED); clear_packet (); out_int (CODE_messages_send_encrypted_service); out_int (CODE_input_encrypted_chat); out_int (M->permanent_id.peer_id); out_long (M->permanent_id.access_hash); out_long (M->permanent_id.id); encr_start (); out_int (CODE_decrypted_message_layer); out_random (15 + 4 * (rand () % 3)); out_int (TGL_ENCRYPTED_LAYER); out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_get_peer_id (TLS->our_id))); out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_get_peer_id (TLS->our_id)) - 2); out_int (CODE_decrypted_message_service); out_long (M->permanent_id.id); switch (M->action.type) { case tgl_message_action_notify_layer: out_int (CODE_decrypted_message_action_notify_layer); out_int (M->action.layer); break; case tgl_message_action_set_message_ttl: out_int (CODE_decrypted_message_action_set_message_t_t_l); out_int (M->action.ttl); break; case tgl_message_action_request_key: out_int (CODE_decrypted_message_action_request_key); out_long (M->action.exchange_id); out_cstring ((void *)M->action.g_a, 256); break; case tgl_message_action_accept_key: out_int (CODE_decrypted_message_action_accept_key); out_long (M->action.exchange_id); out_cstring ((void *)M->action.g_a, 256); out_long (M->action.key_fingerprint); break; case tgl_message_action_commit_key: out_int (CODE_decrypted_message_action_commit_key); out_long (M->action.exchange_id); out_long (M->action.key_fingerprint); break; case tgl_message_action_abort_key: out_int (CODE_decrypted_message_action_abort_key); out_long (M->action.exchange_id); break; case tgl_message_action_noop: out_int (CODE_decrypted_message_action_noop); break; default: assert (0); } encr_finish (&P->encr_chat); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); } void tgl_do_send_encr_msg (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (M->flags & TGLMF_SERVICE) { tgl_do_send_encr_msg_action (TLS, M, callback, callback_extra); return; } tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); if (!P || P->encr_chat.state != sc_ok) { vlogprintf (E_WARNING, "Unknown encrypted chat\n"); if (callback) { callback (TLS, callback_extra, 0, M); } return; } assert (M->flags & TGLMF_ENCRYPTED); clear_packet (); out_int (CODE_messages_send_encrypted); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (M->to_id)); out_long (P->encr_chat.access_hash); out_long (M->permanent_id.id); encr_start (); out_int (CODE_decrypted_message_layer); out_random (15 + 4 * (rand () % 3)); out_int (TGL_ENCRYPTED_LAYER); out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_get_peer_id (TLS->our_id))); out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_get_peer_id (TLS->our_id)) - 2); out_int (CODE_decrypted_message); out_long (M->permanent_id.id); out_int (P->encr_chat.ttl); out_cstring ((void *)M->message, M->message_len); switch (M->media.type) { case tgl_message_media_none: out_int (CODE_decrypted_message_media_empty); break; case tgl_message_media_geo: out_int (CODE_decrypted_message_media_geo_point); out_double (M->media.geo.latitude); out_double (M->media.geo.longitude); break; default: assert (0); } encr_finish (&P->encr_chat); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); } static int mark_read_encr_on_receive (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static int mark_read_encr_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_peer_t *P = q->extra; if (P && P->encr_chat.state != sc_deleted && error_code == 400) { if (strncmp (error, "ENCRYPTION_DECLINED", 19) == 0) { bl_do_peer_delete (TLS, P->id); } } return 0; } static struct query_methods mark_read_encr_methods = { .on_answer = mark_read_encr_on_receive, .on_error = mark_read_encr_on_error, .type = TYPE_TO_PARAM(bool), .name = "read encrypted", .timeout = 0, }; void tgl_do_messages_mark_read_encr (struct tgl_state *TLS, tgl_peer_id_t id, long long access_hash, int last_time, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra) { clear_packet (); out_int (CODE_messages_read_encrypted_history); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (id)); out_long (access_hash); out_int (last_time); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, tgl_peer_get (TLS, id), callback, callback_extra); } static int send_encr_file_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_sent_encrypted_message *DS_MSEM = D; struct tgl_message *M = q->extra; if (M->flags & TGLMF_PENDING) { bl_do_edit_message_encr (TLS, &M->permanent_id, NULL, NULL, DS_MSEM->date, NULL, 0, NULL, NULL, DS_MSEM->file, M->flags ^ TGLMF_PENDING); bl_do_msg_update (TLS, &M->permanent_id); } if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback)(TLS, q->callback_extra, 1, M); } return 0; } static struct query_methods send_encr_file_methods = { .on_answer = send_encr_file_on_answer, .on_error = msg_send_encr_on_error, .type = TYPE_TO_PARAM(messages_sent_encrypted_message), .name = "send encrypted (file)", .timeout = 0, }; static void send_file_encrypted_end (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) { out_int (CODE_messages_send_encrypted_file); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (f->to_id)); tgl_peer_t *P = tgl_peer_get (TLS, f->to_id); assert (P); out_long (P->encr_chat.access_hash); long long r; tglt_secure_random (&r, 8); out_long (r); encr_start (); out_int (CODE_decrypted_message_layer); out_random (15 + 4 * (rand () % 3)); out_int (TGL_ENCRYPTED_LAYER); out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != tgl_get_peer_id (TLS->our_id))); out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == tgl_get_peer_id (TLS->our_id))); out_int (CODE_decrypted_message); out_long (r); out_int (P->encr_chat.ttl); out_string (""); int *save_ptr = packet_ptr; if (f->flags == -1) { out_int (CODE_decrypted_message_media_photo); } else if ((f->flags & TGLDF_VIDEO)) { out_int (CODE_decrypted_message_media_video); } else if ((f->flags & TGLDF_AUDIO)) { out_int (CODE_decrypted_message_media_audio); } else { out_int (CODE_decrypted_message_media_document); } if (f->flags == -1 || !(f->flags & TGLDF_AUDIO)) { out_cstring ("", 0); out_int (90); out_int (90); } if (f->flags == -1) { out_int (f->w); out_int (f->h); } else if (f->flags & TGLDF_VIDEO) { out_int (f->duration); out_string (tg_mime_by_filename (f->file_name)); out_int (f->w); out_int (f->h); } else if (f->flags & TGLDF_AUDIO) { out_int (f->duration); out_string (tg_mime_by_filename (f->file_name)); } else { out_string (""); out_string (tg_mime_by_filename (f->file_name)); // document } out_int (f->size); out_cstring ((void *)f->key, 32); out_cstring ((void *)f->init_iv, 32); int *save_in_ptr = in_ptr; int *save_in_end = in_end; in_ptr = save_ptr; in_end = packet_ptr; assert (skip_type_any (TYPE_TO_PARAM(decrypted_message_media)) >= 0); assert (in_ptr == in_end); in_ptr = save_ptr; in_end = packet_ptr; struct tl_ds_decrypted_message_media *DS_DMM = fetch_ds_type_decrypted_message_media (TYPE_TO_PARAM (decrypted_message_media)); in_end = save_in_ptr; in_ptr = save_in_end; int date = time (NULL); encr_finish (&P->encr_chat); if (f->size < (16 << 20)) { out_int (CODE_input_encrypted_file_uploaded); } else { out_int (CODE_input_encrypted_file_big_uploaded); } out_long (f->id); out_int (f->part_num); if (f->size < (16 << 20)) { out_string (""); } unsigned char md5[16]; unsigned char str[64]; memcpy (str, f->key, 32); memcpy (str + 32, f->init_iv, 32); TGLC_md5 (str, 64, md5); out_int ((*(int *)md5) ^ (*(int *)(md5 + 4))); tfree_secure (f->iv, 32); tgl_peer_id_t from_id = TLS->our_id; struct tgl_message_id id = tgl_peer_id_to_msg_id (P->id, r); bl_do_edit_message_encr (TLS, &id, &from_id, &f->to_id, &date, NULL, 0, DS_DMM, NULL, NULL, TGLMF_OUT | TGLMF_UNREAD | TGLMF_ENCRYPTED | TGLMF_CREATE | TGLMF_CREATED); free_ds_type_decrypted_message_media (DS_DMM, TYPE_TO_PARAM (decrypted_message_media)); struct tgl_message *M = tgl_message_get (TLS, &id); assert (M); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra); tfree_str (f->file_name); tfree (f, sizeof (*f)); } void tgl_do_send_location_encr (struct tgl_state *TLS, tgl_peer_id_t peer_id, double latitude, double longitude, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { struct tl_ds_decrypted_message_media TDSM; TDSM.magic = CODE_decrypted_message_media_geo_point; TDSM.latitude = talloc (sizeof (double)); *TDSM.latitude = latitude; TDSM.longitude = talloc (sizeof (double)); *TDSM.longitude = longitude; int date = time (0); tgl_peer_id_t from_id = TLS->our_id; tgl_peer_t *P = tgl_peer_get (TLS, peer_id); struct tgl_message_id id = tgl_peer_id_to_random_msg_id (P->id);; bl_do_edit_message_encr (TLS, &id, &from_id, &peer_id, &date, NULL, 0, &TDSM, NULL, NULL, TGLMF_UNREAD | TGLMF_OUT | TGLMF_PENDING | TGLMF_CREATE | TGLMF_CREATED | TGLMF_ENCRYPTED); tfree (TDSM.latitude, sizeof (double)); tfree (TDSM.longitude, sizeof (double)); struct tgl_message *M = tgl_message_get (TLS, &id); tgl_do_send_encr_msg (TLS, M, callback, callback_extra); } /* {{{ Encr accept */ static int send_encr_accept_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (TLS, D); if (E->state == sc_ok) { tgl_do_send_encr_chat_layer (TLS, E); } if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_secret_chat *))q->callback) (TLS, q->callback_extra, E->state == sc_ok, E); } return 0; } static int send_encr_request_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (TLS, D); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_secret_chat *))q->callback) (TLS, q->callback_extra, E->state != sc_deleted, E); } return 0; } static int encr_accept_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_peer_t *P = q->extra; if (P && P->encr_chat.state != sc_deleted && error_code == 400) { if (strncmp (error, "ENCRYPTION_DECLINED", 19) == 0) { bl_do_peer_delete (TLS, P->id); } } if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_secret_chat *))q->callback) (TLS, q->callback_extra, 0, NULL); } return 0; } static struct query_methods send_encr_accept_methods = { .on_answer = send_encr_accept_on_answer, .on_error = encr_accept_on_error, .type = TYPE_TO_PARAM(encrypted_chat), .name = "send encrypted (chat accept)", .timeout = 0, }; static struct query_methods send_encr_request_methods = { .on_answer = send_encr_request_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(encrypted_chat), .name = "send encrypted (chat request)", .timeout = 0, }; //int encr_root; //unsigned char *encr_prime; //int encr_param_version; //static TGLC_bn_ctx *ctx; void tgl_do_send_accept_encr_chat (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char *random, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { int i; int ok = 0; for (i = 0; i < 64; i++) { if (E->key[i]) { ok = 1; break; } } if (ok) { if (callback) { callback (TLS, callback_extra, 1, E); } return; } // Already generated key for this chat assert (E->g_key); assert (TLS->TGLC_bn_ctx); unsigned char random_here[256]; tglt_secure_random (random_here, 256); for (i = 0; i < 256; i++) { random[i] ^= random_here[i]; } TGLC_bn *b = TGLC_bn_bin2bn (random, 256, 0); ensure_ptr (b); TGLC_bn *g_a = TGLC_bn_bin2bn (E->g_key, 256, 0); ensure_ptr (g_a); assert (tglmp_check_g_a (TLS, TLS->encr_prime_bn, g_a) >= 0); //if (!ctx) { // ctx = TGLC_bn_ctx_new (); // ensure_ptr (ctx); //} TGLC_bn *p = TLS->encr_prime_bn; TGLC_bn *r = TGLC_bn_new (); ensure_ptr (r); ensure (TGLC_bn_mod_exp (r, g_a, b, p, TLS->TGLC_bn_ctx)); static unsigned char kk[256]; memset (kk, 0, sizeof (kk)); TGLC_bn_bn2bin (r, kk + (256 - TGLC_bn_num_bytes (r))); static unsigned char sha_buffer[20]; TGLC_sha1 (kk, 256, sha_buffer); long long fingerprint = *(long long *)(sha_buffer + 12); //bl_do_encr_chat_set_key (TLS, E, kk, *(long long *)(sha_buffer + 12)); //bl_do_encr_chat_set_sha (TLS, E, sha_buffer); int state = sc_ok; bl_do_encr_chat (TLS, tgl_get_peer_id (E->id), NULL, NULL, NULL, NULL, kk, NULL, sha_buffer, &state, NULL, NULL, NULL, NULL, NULL, &fingerprint, TGL_FLAGS_UNCHANGED, NULL, 0 ); clear_packet (); out_int (CODE_messages_accept_encryption); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (E->id)); out_long (E->access_hash); ensure (TGLC_bn_set_word (g_a, TLS->encr_root)); ensure (TGLC_bn_mod_exp (r, g_a, b, p, TLS->TGLC_bn_ctx)); static unsigned char buf[256]; memset (buf, 0, sizeof (buf)); TGLC_bn_bn2bin (r, buf + (256 - TGLC_bn_num_bytes (r))); out_cstring ((void *)buf, 256); out_long (E->key_fingerprint); TGLC_bn_clear_free (b); TGLC_bn_clear_free (g_a); TGLC_bn_clear_free (r); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E, callback, callback_extra); } void tgl_do_create_keys_end (struct tgl_state *TLS, struct tgl_secret_chat *U) { assert (TLS->encr_prime); TGLC_bn *g_b = TGLC_bn_bin2bn (U->g_key, 256, 0); ensure_ptr (g_b); assert (tglmp_check_g_a (TLS, TLS->encr_prime_bn, g_b) >= 0); TGLC_bn *p = TLS->encr_prime_bn; ensure_ptr (p); TGLC_bn *r = TGLC_bn_new (); ensure_ptr (r); TGLC_bn *a = TGLC_bn_bin2bn ((void *)U->key, 256, 0); ensure_ptr (a); ensure (TGLC_bn_mod_exp (r, g_b, a, p, TLS->TGLC_bn_ctx)); unsigned char *t = talloc (256); memcpy (t, U->key, 256); memset (U->key, 0, sizeof (U->key)); TGLC_bn_bn2bin (r, (void *)(((char *)(U->key)) + (256 - TGLC_bn_num_bytes (r)))); static unsigned char sha_buffer[20]; TGLC_sha1 ((void *)U->key, 256, sha_buffer); long long k = *(long long *)(sha_buffer + 12); if (k != U->key_fingerprint) { vlogprintf (E_WARNING, "Key fingerprint mismatch (my 0x%" INT64_PRINTF_MODIFIER "x 0x%" INT64_PRINTF_MODIFIER "x)\n", (unsigned long long)k, (unsigned long long)U->key_fingerprint); U->state = sc_deleted; } memcpy (U->first_key_sha, sha_buffer, 20); tfree_secure (t, 256); TGLC_bn_clear_free (g_b); TGLC_bn_clear_free (r); TGLC_bn_clear_free (a); } void tgl_do_send_create_encr_chat (struct tgl_state *TLS, void *x, unsigned char *random, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { int user_id = (long)x; int i; unsigned char random_here[256]; tglt_secure_random (random_here, 256); for (i = 0; i < 256; i++) { random[i] ^= random_here[i]; } TGLC_bn *a = TGLC_bn_bin2bn (random, 256, 0); ensure_ptr (a); TGLC_bn *p = TGLC_bn_bin2bn (TLS->encr_prime, 256, 0); ensure_ptr (p); TGLC_bn *g = TGLC_bn_new (); ensure_ptr (g); ensure (TGLC_bn_set_word (g, TLS->encr_root)); TGLC_bn *r = TGLC_bn_new (); ensure_ptr (r); ensure (TGLC_bn_mod_exp (r, g, a, p, TLS->TGLC_bn_ctx)); TGLC_bn_clear_free (a); static char g_a[256]; memset (g_a, 0, 256); TGLC_bn_bn2bin (r, (void *)(g_a + (256 - TGLC_bn_num_bytes (r)))); int t = rand (); while (tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (t))) { t = rand (); } //bl_do_encr_chat_init (TLS, t, user_id, (void *)random, (void *)g_a); int state = sc_waiting; int our_id = tgl_get_peer_id (TLS->our_id); bl_do_encr_chat (TLS, t, NULL, NULL, &our_id, &user_id, random, NULL, NULL, &state, NULL, NULL, NULL, NULL, NULL, NULL, TGLPF_CREATE | TGLPF_CREATED, NULL, 0); tgl_peer_t *_E = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (t)); assert (_E); struct tgl_secret_chat *E = &_E->encr_chat; clear_packet (); out_int (CODE_messages_request_encryption); tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (E->user_id)); assert (U); out_int (CODE_input_user); out_int (E->user_id); out_long (U ? U->user.access_hash : 0); out_int (tgl_get_peer_id (E->id)); out_cstring (g_a, 256); //write_secret_chat_file (); TGLC_bn_clear_free (g); TGLC_bn_clear_free (p); TGLC_bn_clear_free (r); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra); } static int send_encr_discard_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_secret_chat *E = q->extra; bl_do_peer_delete (TLS, E->id); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_secret_chat *))q->callback) (TLS, q->callback_extra, 1, E); } return 0; } static struct query_methods send_encr_discard_methods = { .on_answer = send_encr_discard_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(bool), .name = "send encrypted (chat discard)", .timeout = 0, }; void tgl_do_discard_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { assert (E); assert (tgl_get_peer_id (E->id) > 0); if (E->state == sc_deleted || E->state == sc_none) { if (callback) { callback (TLS, callback_extra, 0, E); } return; } clear_packet (); out_int (CODE_messages_discard_encryption); out_int (tgl_get_peer_id (E->id)); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_discard_methods, E, callback, callback_extra); } static int get_dh_config_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_dh_config *DS_MDC = D; if (DS_MDC->magic == CODE_messages_dh_config) { assert (DS_MDC->p->len == 256); bl_do_set_dh_params (TLS, DS_LVAL (DS_MDC->g), (void *)DS_MDC->p->data, DS_LVAL (DS_MDC->version)); } else { assert (TLS->encr_param_version); } unsigned char *random = talloc (256); assert (DS_MDC->random->len == 256); memcpy (random, DS_MDC->random->data, 256); if (q->extra) { void **x = q->extra; ((void (*)(struct tgl_state *, void *, void *, void *, void *))(*x))(TLS, x[1], random, q->callback, q->callback_extra); tfree (x, 2 * sizeof (void *)); tfree_secure (random, 256); } else { tfree_secure (random, 256); } return 0; } static struct query_methods get_dh_config_methods = { .on_answer = get_dh_config_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(messages_dh_config), .name = "dh config", .timeout = 0, }; void tgl_do_accept_encr_chat_request (struct tgl_state *TLS, struct tgl_secret_chat *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { if (E->state != sc_request) { if (callback) { callback (TLS, callback_extra, 0, E); } return; } assert (E->state == sc_request); clear_packet (); out_int (CODE_messages_get_dh_config); out_int (TLS->encr_param_version); out_int (256); void **x = talloc (2 * sizeof (void *)); x[0] = tgl_do_send_accept_encr_chat; x[1] = E; tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra); } void tgl_do_create_encr_chat_request (struct tgl_state *TLS, int user_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { clear_packet (); out_int (CODE_messages_get_dh_config); out_int (TLS->encr_param_version); out_int (256); void **x = talloc (2 * sizeof (void *)); x[0] = tgl_do_send_create_encr_chat; x[1] = (void *)(long)(user_id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra); } /* }}} */ ================================================ FILE: queries.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #ifndef WIN32 #include #endif #include "mtproto-client.h" #include "queries.h" #include "tree.h" #include "mtproto-common.h" //#include "telegram.h" #include "tgl-structures.h" //#include "interface.h" //#include "net.h" #include "crypto/bn.h" #include "crypto/rand.h" #include "crypto/aes.h" #include "crypto/sha.h" #include "crypto/md5.h" #include "no-preview.h" #include "tgl-binlog.h" #include "updates.h" #include "auto.h" #include "auto/auto-types.h" #include "auto/auto-skip.h" #include "auto/auto-free-ds.h" #include "auto/auto-fetch-ds.h" #include "auto/auto-print-ds.h" #include "tgl.h" #include "tg-mime-types.h" #include "mtproto-utils.h" #include "tgl-methods-in.h" #include "tgl-queries.h" #ifndef EPROTO // BSD doesn't define EPROTO, even though it is POSIX: // https://lists.freebsd.org/pipermail/freebsd-standards/2003-June/000124.html #define EPROTO EIO #endif #ifndef PATH_MAX #define PATH_MAX 4096 #endif #ifndef O_BINARY #define O_BINARY 0 #endif static void out_peer_id (struct tgl_state *TLS, tgl_peer_id_t id); static struct query_methods send_msgs_methods; struct messages_send_extra { int multi; int count; tgl_message_id_t id; tgl_message_id_t *list; }; #define QUERY_TIMEOUT 6.0 struct send_file { int fd; long long size; long long offset; int part_num; int part_size; long long id; long long thumb_id; tgl_peer_id_t to_id; int flags; char *file_name; int encr; //int avatar; tgl_peer_id_t avatar; int reply; unsigned char *iv; unsigned char *init_iv; unsigned char *key; int w; int h; int duration; char *caption; int channel; }; #define memcmp8(a,b) memcmp ((a), (b), 8) DEFINE_TREE (query, struct query *, memcmp8, 0) ; static int mystreq1 (const char *a, const char *b, int l) { if ((int)strlen (a) != l) { return 1; } return memcmp (a, b, l); } /* {{{ COMMON */ struct query *tglq_query_get (struct tgl_state *TLS, long long id) { return tree_lookup_query (TLS->queries_tree, (void *)&id); } static int alarm_query (struct tgl_state *TLS, struct query *q) { assert (q); vlogprintf (E_DEBUG - 2, "Alarm query %" INT64_PRINTF_MODIFIER "d (type '%s')\n", q->msg_id, q->methods->name); TLS->timer_methods->insert (q->ev, q->methods->timeout ? q->methods->timeout : QUERY_TIMEOUT); if (q->session && q->session_id && q->DC && q->DC->sessions[0] == q->session && q->session->session_id == q->session_id) { clear_packet (); out_int (CODE_msg_container); out_int (1); out_long (q->msg_id); out_int (q->seq_no); out_int (4 * q->data_len); out_ints (q->data, q->data_len); tglmp_encrypt_send_message (TLS, q->session->c, packet_buffer, packet_ptr - packet_buffer, q->flags & QUERY_FORCE_SEND); } else { q->flags &= ~QUERY_ACK_RECEIVED; if (tree_lookup_query (TLS->queries_tree, q)) { TLS->queries_tree = tree_delete_query (TLS->queries_tree, q); } q->session = q->DC->sessions[0]; long long old_id = q->msg_id; q->msg_id = tglmp_encrypt_send_message (TLS, q->session->c, q->data, q->data_len, (q->flags & QUERY_FORCE_SEND) | 1); vlogprintf (E_NOTICE, "Resent query #%" INT64_PRINTF_MODIFIER "d as #%" INT64_PRINTF_MODIFIER "d of size %d to DC %d\n", old_id, q->msg_id, 4 * q->data_len, q->DC->id); TLS->queries_tree = tree_insert_query (TLS->queries_tree, q, rand ()); q->session_id = q->session->session_id; if (!(q->session->dc->flags & 4) && !(q->flags & QUERY_FORCE_SEND)) { q->session_id = 0; } } return 0; } void tglq_regen_query (struct tgl_state *TLS, long long id) { struct query *q = tglq_query_get (TLS, id); if (!q) { return; } q->flags &= ~QUERY_ACK_RECEIVED; if (!(q->session && q->session_id && q->DC && q->DC->sessions[0] == q->session && q->session->session_id == q->session_id)) { q->session_id = 0; } else { if (!(q->session->dc->flags & 4) && !(q->flags & QUERY_FORCE_SEND)) { q->session_id = 0; } } vlogprintf (E_NOTICE, "regen query %" INT64_PRINTF_MODIFIER "d\n", id); TLS->timer_methods->insert (q->ev, 0.001); } struct regen_tmp_struct { struct tgl_state *TLS; struct tgl_dc *DC; struct tgl_session *S; }; void tglq_regen_query_from_old_session (struct query *q, void *ex) { struct regen_tmp_struct *T = ex; struct tgl_state *TLS = T->TLS; if (q->DC == T->DC) { if (!q->session || q->session_id != T->S->session_id || q->session != T->S) { q->session_id = 0; vlogprintf (E_NOTICE, "regen query from old session %" INT64_PRINTF_MODIFIER "d\n", q->msg_id); TLS->timer_methods->insert (q->ev, q->methods->timeout ? 0.001 : 0.1); } } } void tglq_regen_queries_from_old_session (struct tgl_state *TLS, struct tgl_dc *DC, struct tgl_session *S) { struct regen_tmp_struct T; T.TLS = TLS; T.DC = DC; T.S = S; tree_act_ex_query (TLS->queries_tree, tglq_regen_query_from_old_session, &T); } void tglq_query_restart (struct tgl_state *TLS, long long id) { struct query *q = tglq_query_get (TLS, id); if (q) { vlogprintf (E_NOTICE, "restarting query %" INT64_PRINTF_MODIFIER "d\n", id); TLS->timer_methods->remove (q->ev); alarm_query (TLS, q); } } static void alarm_query_gateway (struct tgl_state *TLS, void *arg) { alarm_query (TLS, arg); } struct query *tglq_send_query_ex (struct tgl_state *TLS, struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra, int flags) { assert (DC); assert (DC->auth_key_id); if (!DC->sessions[0]) { tglmp_dc_create_session (TLS, DC); } vlogprintf (E_DEBUG, "Sending query of size %d to DC %d\n", 4 * ints, DC->id); struct query *q = talloc0 (sizeof (*q)); q->data_len = ints; q->data = talloc (4 * ints); memcpy (q->data, data, 4 * ints); q->msg_id = tglmp_encrypt_send_message (TLS, DC->sessions[0]->c, data, ints, 1 | (flags & QUERY_FORCE_SEND)); q->session = DC->sessions[0]; q->seq_no = q->session->seq_no - 1; q->session_id = q->session->session_id; if (!(DC->flags & 4) && !(flags & QUERY_FORCE_SEND)) { q->session_id = 0; } vlogprintf (E_DEBUG, "Msg_id is %" INT64_PRINTF_MODIFIER "d %p\n", q->msg_id, q); vlogprintf (E_NOTICE, "Sent query #%" INT64_PRINTF_MODIFIER "d of size %d to DC %d\n", q->msg_id, 4 * ints, DC->id); q->methods = methods; q->type = methods->type; q->DC = DC; q->flags = flags & QUERY_FORCE_SEND; if (TLS->queries_tree) { vlogprintf (E_DEBUG + 2, "%" INT64_PRINTF_MODIFIER "d %" INT64_PRINTF_MODIFIER "d\n", q->msg_id, TLS->queries_tree->x->msg_id); } TLS->queries_tree = tree_insert_query (TLS->queries_tree, q, rand ()); q->ev = TLS->timer_methods->alloc (TLS, alarm_query_gateway, q); TLS->timer_methods->insert (q->ev, q->methods->timeout ? q->methods->timeout : QUERY_TIMEOUT); q->extra = extra; q->callback = callback; q->callback_extra = callback_extra; TLS->active_queries ++; return q; } struct query *tglq_send_query (struct tgl_state *TLS, struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) { return tglq_send_query_ex (TLS, DC, ints, data, methods, extra, callback, callback_extra, 0); } static int fail_on_error (struct tgl_state *TLS, struct query *q, int error_code, int l, const char *error) { vlogprintf (E_ERROR, "error #%d: %.*s\n", error_code, l, error); assert (0); return 0; } void tglq_query_ack (struct tgl_state *TLS, long long id) { struct query *q = tglq_query_get (TLS, id); if (q && !(q->flags & QUERY_ACK_RECEIVED)) { assert (q->msg_id == id); q->flags |= QUERY_ACK_RECEIVED; TLS->timer_methods->remove (q->ev); } } void tglq_query_delete (struct tgl_state *TLS, long long id) { struct query *q = tglq_query_get (TLS, id); if (!q) { return; } if (!(q->flags & QUERY_ACK_RECEIVED)) { TLS->timer_methods->remove (q->ev); } TLS->queries_tree = tree_delete_query (TLS->queries_tree, q); tfree (q->data, q->data_len * 4); TLS->timer_methods->free (q->ev); TLS->active_queries --; } static void resend_query_cb (struct tgl_state *TLS, void *_q, int success); void tglq_free_query (struct query *q, void *extra) { struct tgl_state *TLS = extra; if (!(q->flags & QUERY_ACK_RECEIVED)) { TLS->timer_methods->remove (q->ev); } tfree (q->data, q->data_len * 4); TLS->timer_methods->free (q->ev); } void tglq_query_free_all (struct tgl_state *TLS) { tree_act_ex_query (TLS->queries_tree, tglq_free_query, TLS); TLS->queries_tree = tree_clear_query (TLS->queries_tree); } int tglq_query_error (struct tgl_state *TLS, long long id) { assert (fetch_int () == CODE_rpc_error); int error_code = fetch_int (); int error_len = prefetch_strlen (); char *error = fetch_str (error_len); struct query *q = tglq_query_get (TLS, id); if (!q) { vlogprintf (E_WARNING, "error for query '%s' #%" INT64_PRINTF_MODIFIER "d: #%d :%.*s\n", q->methods->name, id, error_code, error_len, error); vlogprintf (E_WARNING, "No such query\n"); } else { if (!(q->flags & QUERY_ACK_RECEIVED)) { TLS->timer_methods->remove (q->ev); } TLS->queries_tree = tree_delete_query (TLS->queries_tree, q); int res = 0; int error_handled = 0; switch (error_code) { case 303: // migrate { int offset = -1; if (error_len >= 15 && !memcmp (error, "PHONE_MIGRATE_", 14)) { offset = 14; } if (error_len >= 17 && !memcmp (error, "NETWORK_MIGRATE_", 16)) { offset = 16; } if (error_len >= 14 && !memcmp (error, "USER_MIGRATE_", 13)) { offset = 13; } if (offset >= 0) { int i = 0; while (offset < error_len && error[offset] >= '0' && error[offset] <= '9') { i = i * 10 + error[offset] - '0'; offset ++; } if (i > 0 && i < TGL_MAX_DC_NUM) { bl_do_set_working_dc (TLS, i); q->flags &= ~QUERY_ACK_RECEIVED; //q->session_id = 0; //struct tgl_dc *DC = q->DC; //if (!(DC->flags & 4) && !(q->flags & QUERY_FORCE_SEND)) { q->session_id = 0; //} q->DC = TLS->DC_working; TLS->timer_methods->insert (q->ev, 0); error_handled = 1; res = 1; } } } break; case 400: // nothing to handle // bad user input probably break; case 401: if (!mystreq1 ("SESSION_PASSWORD_NEEDED", error, error_len)) { if (!(TLS->locks & TGL_LOCK_PASSWORD)) { TLS->locks |= TGL_LOCK_PASSWORD; tgl_do_check_password (TLS, resend_query_cb, q); } res = 1; error_handled = 1; } break; case 403: // privacy violation break; case 404: // not found break; case 420: // flood case 500: // internal error default: // anything else. Treated as internal error { int wait; if (strncmp (error, "FLOOD_WAIT_", 11)) { if (error_code == 420) { vlogprintf (E_ERROR, "error = '%s'\n", error); } wait = 10; } else { wait = atoll (error + 11); } q->flags &= ~QUERY_ACK_RECEIVED; TLS->timer_methods->insert (q->ev, wait); struct tgl_dc *DC = q->DC; if (!(DC->flags & 4) && !(q->flags & QUERY_FORCE_SEND)) { q->session_id = 0; } error_handled = 1; } break; } if (error_handled) { vlogprintf (E_DEBUG - 2, "error for query #%" INT64_PRINTF_MODIFIER "d: #%d %.*s (HANDLED)\n", id, error_code, error_len, error); } else { vlogprintf (E_WARNING, "error for query '%s' #%" INT64_PRINTF_MODIFIER "d: #%d %.*s\n", q->methods->name, id, error_code, error_len, error); if (q->methods && q->methods->on_error) { res = q->methods->on_error (TLS, q, error_code, error_len, error); } } if (res <= 0) { tfree (q->data, q->data_len * 4); TLS->timer_methods->free (q->ev); } if (res == -11) { TLS->active_queries --; return -1; } } TLS->active_queries --; return 0; } #define MAX_PACKED_SIZE (1 << 24) static int packed_buffer[MAX_PACKED_SIZE / 4]; int tglq_query_result (struct tgl_state *TLS, long long id) { vlogprintf (E_DEBUG, "result for query #%" INT64_PRINTF_MODIFIER "d. Size %ld bytes\n", id, (long)4 * (in_end - in_ptr)); int op = prefetch_int (); int *end = 0; int *eend = 0; if (op == CODE_gzip_packed) { fetch_int (); int l = prefetch_strlen (); char *s = fetch_str (l); int total_out = tgl_inflate (s, l, packed_buffer, MAX_PACKED_SIZE); vlogprintf (E_DEBUG, "inflated %d bytes\n", total_out); end = in_ptr; eend = in_end; in_ptr = packed_buffer; in_end = in_ptr + total_out / 4; } struct query *q = tglq_query_get (TLS, id); if (!q) { vlogprintf (E_WARNING, "No such query\n"); in_ptr = in_end; } else { if (!(q->flags & QUERY_ACK_RECEIVED)) { TLS->timer_methods->remove (q->ev); } TLS->queries_tree = tree_delete_query (TLS->queries_tree, q); if (q->methods && q->methods->on_answer) { assert (q->type); int *save = in_ptr; vlogprintf (E_DEBUG, "in_ptr = %p, end_ptr = %p\n", in_ptr, in_end); if (skip_type_any (q->type) < 0) { vlogprintf (E_ERROR, "Skipped %ld int out of %ld (type %s) (query type %s)\n", (long)(in_ptr - save), (long)(in_end - save), q->type->type->id, q->methods->name); vlogprintf (E_ERROR, "0x%08x 0x%08x 0x%08x 0x%08x\n", *(save - 1), *(save), *(save + 1), *(save + 2)); assert (0); } assert (in_ptr == in_end); in_ptr = save; void *DS = fetch_ds_type_any (q->type); assert (DS); q->methods->on_answer (TLS, q, DS); free_ds_type_any (DS, q->type); assert (in_ptr == in_end); } tfree (q->data, 4 * q->data_len); TLS->timer_methods->free (q->ev); tfree (q, sizeof (*q)); } if (end) { in_ptr = end; in_end = eend; } TLS->active_queries --; return 0; } static void out_random (int n) { assert (n <= 32); static char buf[32]; tglt_secure_random (buf, n); out_cstring (buf, n); } int allow_send_linux_version; void tgl_do_insert_header (struct tgl_state *TLS) { out_int (CODE_invoke_with_layer); out_int (TGL_SCHEME_LAYER); out_int (CODE_init_connection); out_int (TLS->app_id); #ifndef WIN32 if (allow_send_linux_version) { struct utsname st; uname (&st); out_string (st.machine); static char buf[4096]; tsnprintf (buf, sizeof (buf) - 1, "%.999s %.999s %.999s", st.sysname, st.release, st.version); out_string (buf); tsnprintf (buf, sizeof (buf) - 1, "%s (TGL %s)", TLS->app_version, TGL_VERSION); out_string (buf); out_string ("En"); } else { out_string ("x86"); out_string ("Linux"); static char buf[4096]; tsnprintf (buf, sizeof (buf) - 1, "%s (TGL %s)", TLS->app_version, TGL_VERSION); out_string (buf); out_string ("en"); } #else out_string ("x86"); out_string ("Windows"); static char buf[4096]; tsnprintf (buf, sizeof (buf) - 1, "%s (TGL %s)", TLS->app_version, TGL_VERSION); out_string (buf); out_string ("en"); #endif } void tgl_set_query_error (struct tgl_state *TLS, int error_code, const char *format, ...) __attribute__ ((format (printf, 3, 4))); void tgl_set_query_error (struct tgl_state *TLS, int error_code, const char *format, ...) { static char s[1001]; va_list ap; va_start (ap, format); vsnprintf (s, 1000, format, ap); va_end (ap); if (TLS->error) { tfree_str (TLS->error); } TLS->error = tstrdup (s); TLS->error_code = error_code; } /* }}} */ /* {{{ Default on error */ static int q_void_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *,void *, int))(q->callback))(TLS, q->callback_extra, 0); } return 0; } static int q_ptr_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *,void *, int, void *))(q->callback))(TLS, q->callback_extra, 0, NULL); } return 0; } static int q_list_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *,void *, int, int, void *))(q->callback))(TLS, q->callback_extra, 0, 0, NULL); } return 0; } /* }}} */ #include "queries-encrypted.c" static void increase_ent (int *ent_size, int **ent, int s) { *ent = trealloc (*ent, (*ent_size) * 4, (*ent_size) * 4 + 4 * s); (*ent_size) +=s; } int utf8_len (const char *s, int len) { int i; int r = 0; for (i = 0; i < len; i++) { if ((s[i] & 0xc0) != 0x80) { r ++; } } return r; } static char *process_html_text (struct tgl_state *TLS, const char *text, int text_len, int *ent_size, int **ent) { char *new_text = talloc (2 * text_len + 1); int stpos[100]; int sttype[100]; int stp = 0; int p; int cur_p = 0; *ent = talloc (8); *ent_size = 2; (*ent)[0] = CODE_vector; (*ent)[1] = 0; int total = 0; for (p = 0; p < text_len; p++) { assert (cur_p <= 2 * text_len); if (text[p] == '<') { if (stp == 99) { tgl_set_query_error (TLS, EINVAL, "Too nested tags..."); tfree (new_text, 2 * text_len + 1); return NULL; } int old_p = *ent_size; if (text_len - p >= 3 && !memcmp (text + p, "", 3)) { increase_ent (ent_size, ent, 3); total ++; (*ent)[old_p] = CODE_message_entity_bold; (*ent)[old_p + 1] = utf8_len (new_text, cur_p); stpos[stp] = old_p + 2; sttype[stp] = 0; stp ++; p += 2; continue; } if (text_len - p >= 4 && !memcmp (text + p, "", 4)) { if (stp == 0 || sttype[stp - 1] != 0) { tgl_set_query_error (TLS, EINVAL, "Invalid tag nest"); tfree (new_text, 2 * text_len + 1); return NULL; } (*ent)[stpos[stp - 1]] = utf8_len (new_text, cur_p) - (*ent)[stpos[stp - 1] - 1]; stp --; p += 3; continue; } if (text_len - p >= 3 && !memcmp (text + p, "", 3)) { increase_ent (ent_size, ent, 3); total ++; (*ent)[old_p] = CODE_message_entity_italic; (*ent)[old_p + 1] = utf8_len (new_text, cur_p); stpos[stp] = old_p + 2; sttype[stp] = 1; stp ++; p += 2; continue; } if (text_len - p >= 4 && !memcmp (text + p, "", 4)) { if (stp == 0 || sttype[stp - 1] != 1) { tgl_set_query_error (TLS, EINVAL, "Invalid tag nest"); tfree (new_text, 2 * text_len + 1); return NULL; } (*ent)[stpos[stp - 1]] = utf8_len (new_text, cur_p) - (*ent)[stpos[stp - 1] - 1]; stp --; p += 3; continue; } if (text_len - p >= 6 && !memcmp (text + p, "", 6)) { increase_ent (ent_size, ent, 3); total ++; (*ent)[old_p] = CODE_message_entity_code; (*ent)[old_p + 1] = utf8_len (new_text, cur_p); stpos[stp] = old_p + 2; sttype[stp] = 2; stp ++; p += 5; continue; } if (text_len - p >= 7 && !memcmp (text + p, "", 7)) { if (stp == 0 || sttype[stp - 1] != 2) { tgl_set_query_error (TLS, EINVAL, "Invalid tag nest"); tfree (new_text, 2 * text_len + 1); return NULL; } (*ent)[stpos[stp - 1]] = utf8_len (new_text, cur_p) - (*ent)[stpos[stp - 1] - 1]; stp --; p += 6; continue; } if (text_len - p >= 9 && !memcmp (text + p, " tag did not close"); tfree (new_text, 2 * text_len + 1); return NULL; } int len = pp - p - 9; assert (len >= 0); if (len >= 250) { tgl_set_query_error (TLS, EINVAL, "too long link"); tfree (new_text, 2 * text_len + 1); return NULL; } increase_ent (ent_size, ent, 3 + (len + 1 + ((-len-1) & 3)) / 4); total ++; (*ent)[old_p] = CODE_message_entity_text_url; (*ent)[old_p + 1] = utf8_len (new_text, cur_p); stpos[stp] = old_p + 2; sttype[stp] = 3; stp ++; unsigned char *r = (void *)((*ent) + old_p + 3); r[0] = len; memcpy (r + 1, text + p + 9, len); memset (r + 1 + len, 0, (-len-1) & 3); p = pp + 1; continue; } if (text_len - p >= 4 && !memcmp (text + p, "", 4)) { if (stp == 0 || sttype[stp - 1] != 3) { tgl_set_query_error (TLS, EINVAL, "Invalid tag nest"); tfree (new_text, 2 * text_len + 1); return NULL; } (*ent)[stpos[stp - 1]] = utf8_len (new_text, cur_p) - (*ent)[stpos[stp - 1] - 1]; stp --; p += 3; continue; } if (text_len - p >= 4 && !memcmp (text + p, "
", 4)) { new_text[cur_p ++] = '\n'; p += 3; continue; } tgl_set_query_error (TLS, EINVAL, "Unknown tag"); tfree (new_text, 2 * text_len + 1); return NULL; } else if (text_len - p >= 4 && !memcmp (text + p, ">", 4)) { p += 3; new_text[cur_p ++] = '>'; } else if (text_len - p >= 4 && !memcmp (text + p, "<", 4)) { p += 3; new_text[cur_p ++] = '<'; } else if (text_len - p >= 5 && !memcmp (text + p, "&", 5)) { p += 4; new_text[cur_p ++] = '&'; } else if (text_len - p >= 6 && !memcmp (text + p, " ", 6)) { p += 5; new_text[cur_p ++] = 0xc2; new_text[cur_p ++] = 0xa0; } else if (text_len - p >= 3 && text[p] == '&' && text[p + 1] == '#') { p += 2; int num = 0; int ok = 0; while (p < text_len) { if (text[p] >= '0' && text[p] <= '9') { num = num * 10 + text[p] - '0'; if (num >= 127) { tgl_set_query_error (TLS, EINVAL, "Too big number in &-sequence"); tfree (new_text, text_len + 1); return NULL; } p ++; } else if (text[p] == ';') { new_text[cur_p ++] = num; ok = 1; break; } else { tgl_set_query_error (TLS, EINVAL, "Bad &-sequence"); tfree (new_text, text_len + 1); return NULL; } } if (ok) { continue; } tgl_set_query_error (TLS, EINVAL, "Unterminated &-sequence"); tfree (new_text, text_len + 1); return NULL; } else { new_text[cur_p ++] = text[p]; } } if (stp != 0) { tgl_set_query_error (TLS, EINVAL, "Invalid tag nest"); tfree (new_text, text_len + 1); return NULL; } (*ent)[1] = total; char *n = talloc (cur_p + 1); memcpy (n, new_text, cur_p); n[cur_p] = 0; tfree (new_text, 2 * text_len + 1); return n; } /* {{{ Get config */ static void fetch_dc_option (struct tgl_state *TLS, struct tl_ds_dc_option *DS_DO) { bl_do_dc_option (TLS, DS_LVAL (DS_DO->flags), DS_LVAL (DS_DO->id), NULL, 0, DS_STR (DS_DO->ip_address), DS_LVAL (DS_DO->port)); } static int help_get_config_on_answer (struct tgl_state *TLS, struct query *q, void *DS) { struct tl_ds_config *DS_C = DS; int i; for (i = 0; i < DS_LVAL (DS_C->dc_options->cnt); i++) { fetch_dc_option (TLS, DS_C->dc_options->data[i]); } int max_chat_size = DS_LVAL (DS_C->chat_size_max); int max_bcast_size = 0;//DS_LVAL (DS_C->broadcast_size_max); vlogprintf (E_DEBUG, "chat_size = %d, bcast_size = %d\n", max_chat_size, max_bcast_size); if (q->callback) { ((void (*)(struct tgl_state *,void *, int))(q->callback))(TLS, q->callback_extra, 1); } return 0; } static struct query_methods help_get_config_methods = { .on_answer = help_get_config_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(config), .name = "get config", .timeout = 1 }; void tgl_do_help_get_config (struct tgl_state *TLS, void (*callback)(struct tgl_state *,void *, int), void *callback_extra) { clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_help_get_config); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra); } void tgl_do_help_get_config_dc (struct tgl_state *TLS, struct tgl_dc *D, void (*callback)(struct tgl_state *, void *, int), void *callback_extra) { clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_help_get_config); tglq_send_query_ex (TLS, D, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra, 2); } /* }}} */ /* {{{ Send code */ static int send_code_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_auth_sent_code *DS_ASC = D; char *phone_code_hash = DS_STR_DUP (DS_ASC->phone_code_hash); int registered = DS_BVAL (DS_ASC->phone_registered);; if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, const char *))(q->callback)) (TLS, q->callback_extra, 1, registered, phone_code_hash); } tfree_str (phone_code_hash); return 0; } static struct query_methods send_code_methods = { .on_answer = send_code_on_answer, .on_error = q_list_on_error, .type = TYPE_TO_PARAM(auth_sent_code), .name = "send code" }; void tgl_do_send_code (struct tgl_state *TLS, const char *phone, int phone_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int registered, const char *hash), void *callback_extra) { vlogprintf (E_DEBUG, "sending code to dc %d\n", TLS->dc_working_num); clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_auth_send_code); out_cstring (phone, phone_len); out_int (0); out_int (TLS->app_id); out_string (TLS->app_hash); out_string ("en"); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, NULL, callback, callback_extra); } static int phone_call_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int))(q->callback))(TLS, q->callback_extra, 1); } return 0; } static struct query_methods phone_call_methods = { .on_answer = phone_call_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(bool), .name = "phone call" }; void tgl_do_phone_call (struct tgl_state *TLS, const char *phone, int phone_len, const char *hash, int hash_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { vlogprintf (E_DEBUG, "calling user\n"); clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_auth_send_call); out_cstring (phone, phone_len); out_cstring (hash, hash_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, NULL, callback, callback_extra); } /* }}} */ /* {{{ Sign in / Sign up */ static int sign_in_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_auth_authorization *DS_AA = D; //vlogprintf (E_DEBUG, "Expires in %d\n", DS_LVAL (DS_AA->expires)); struct tgl_user *U = tglf_fetch_alloc_user (TLS, DS_AA->user); bl_do_dc_signed (TLS, TLS->DC_working->id); if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U); } return 0; } static int sign_in_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 0, NULL); } return 0; } static struct query_methods sign_in_methods = { .on_answer = sign_in_on_answer, .on_error = sign_in_on_error, .type = TYPE_TO_PARAM(auth_authorization), .name = "sign in" }; int tgl_do_send_code_result (struct tgl_state *TLS, const char *phone, int phone_len, const char *hash, int hash_len, const char *code, int code_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) { clear_packet (); out_int (CODE_auth_sign_in); out_cstring (phone, phone_len); out_cstring (hash, hash_len); out_cstring (code, code_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); return 0; } int tgl_do_send_code_result_auth (struct tgl_state *TLS, const char *phone, int phone_len, const char *hash, int hash_len, const char *code, int code_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) { clear_packet (); out_int (CODE_auth_sign_up); out_cstring (phone, phone_len); out_cstring (hash, hash_len); out_cstring (code, code_len); out_cstring (first_name, first_name_len); out_cstring (last_name, last_name_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); return 0; } int tgl_do_send_bot_auth (struct tgl_state *TLS, const char *code, int code_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) { clear_packet (); out_int (CODE_auth_import_bot_authorization); out_int (0); out_int (TLS->app_id); out_string (TLS->app_hash); out_cstring (code, code_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); return 0; } /* }}} */ /* {{{ Get contacts */ static int get_contacts_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_contacts_contacts *DS_CC = D; int n = DS_CC->users ? DS_LVAL (DS_CC->users->cnt) : 0; int i; struct tgl_user **list = talloc (sizeof (void *) * n); for (i = 0; i < n; i++) { list[i] = tglf_fetch_alloc_user (TLS, DS_CC->users->data[i]); } if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, int, struct tgl_user **))q->callback) (TLS, q->callback_extra, 1, n, list); } tfree (list, sizeof (void *) * n); return 0; } static struct query_methods get_contacts_methods = { .on_answer = get_contacts_on_answer, .on_error = q_list_on_error, .type = TYPE_TO_PARAM(contacts_contacts), .name = "get contacts" }; void tgl_do_update_contact_list (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *contacts[]), void *callback_extra) { clear_packet (); out_int (CODE_contacts_get_contacts); out_string (""); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, NULL, callback, callback_extra); } /* }}} */ /* {{{ Send msg (plain text) */ static int msg_send_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_updates *DS_U = D; tgl_message_id_t id; id.peer_type = TGL_PEER_RANDOM_ID; id.id = *(long long *)q->extra; tfree (q->extra, 8); struct tgl_message *M = tgl_message_get (TLS, &id); if (M && M->permanent_id.id == id.id) { tglu_work_any_updates (TLS, 1, DS_U, M); tglu_work_any_updates (TLS, 0, DS_U, M); } else { tglu_work_any_updates (TLS, 1, DS_U, NULL); tglu_work_any_updates (TLS, 0, DS_U, NULL); } M = tgl_message_get (TLS, &id); if (q->callback) { ((void (*)(struct tgl_state *,void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M); } return 0; } static int msg_send_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); tgl_message_id_t id; id.peer_type = TGL_PEER_RANDOM_ID; id.id = *(long long *)q->extra; tfree (q->extra, 8); struct tgl_message *M = tgl_message_get (TLS, &id); if (q->callback) { ((void (*)(struct tgl_state *,void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 0, M); } if (M) { bl_do_message_delete (TLS, &M->permanent_id); } return 0; } static struct query_methods msg_send_methods = { .on_answer = msg_send_on_answer, .on_error = msg_send_on_error, .type = TYPE_TO_PARAM(updates), .name = "send message" }; void tgl_do_send_msg (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT) { tgl_do_send_encr_msg (TLS, M, callback, callback_extra); return; } clear_packet (); out_int (CODE_messages_send_message); unsigned f = ((M->flags & TGLMF_DISABLE_PREVIEW) ? 2 : 0) | (M->reply_id ? 1 : 0) | (M->reply_markup ? 4 : 0) | (M->entities_num > 0 ? 8 : 0); if (tgl_get_peer_type (M->from_id) == TGL_PEER_CHANNEL) { f |= 16; } out_int (f); out_peer_id (TLS, M->to_id); if (M->reply_id) { out_int (M->reply_id); } out_cstring (M->message, M->message_len); out_long (M->permanent_id.id); long long *x = talloc (8); *x = M->permanent_id.id; if (M->reply_markup) { if (M->reply_markup->rows) { out_int (CODE_reply_keyboard_markup); out_int (M->reply_markup->flags); out_int (CODE_vector); out_int (M->reply_markup->rows); int i; for (i = 0; i < M->reply_markup->rows; i++) { out_int (CODE_keyboard_button_row); out_int (CODE_vector); out_int (M->reply_markup->row_start[i + 1] - M->reply_markup->row_start[i]); int j; for (j = 0; j < M->reply_markup->row_start[i + 1] - M->reply_markup->row_start[i]; j++) { out_int (CODE_keyboard_button); out_string (M->reply_markup->buttons[j + M->reply_markup->row_start[i]]); } } } else { out_int (CODE_reply_keyboard_hide); } } if (M->entities_num > 0) { out_int (CODE_vector); out_int (M->entities_num); int i; for (i = 0; i < M->entities_num; i++) { struct tgl_message_entity *E = &M->entities[i]; switch (E->type) { case tgl_message_entity_bold: out_int (CODE_message_entity_bold); out_int (E->start); out_int (E->length); break; case tgl_message_entity_italic: out_int (CODE_message_entity_italic); out_int (E->start); out_int (E->length); break; case tgl_message_entity_code: out_int (CODE_message_entity_code); out_int (E->start); out_int (E->length); break; case tgl_message_entity_text_url: out_int (CODE_message_entity_text_url); out_int (E->start); out_int (E->length); out_string (E->extra); break; default: assert (0); } } } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, x, callback, callback_extra); } void tgl_do_send_message (struct tgl_state *TLS, tgl_peer_id_t peer_id, const char *text, int text_len, unsigned long long flags, struct tl_ds_reply_markup *reply_markup, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (peer_id) == TGL_PEER_ENCR_CHAT) { tgl_peer_t *P = tgl_peer_get (TLS, peer_id); if (!P) { tgl_set_query_error (TLS, EINVAL, "unknown secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (P->encr_chat.state != sc_ok) { tgl_set_query_error (TLS, EINVAL, "secret chat not in ok state"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } } int date = time (0); struct tgl_message_id id = tgl_peer_id_to_random_msg_id (peer_id); if (tgl_get_peer_type (peer_id) != TGL_PEER_ENCR_CHAT) { int reply = (flags >> 32); int disable_preview = flags & TGL_SEND_MSG_FLAG_DISABLE_PREVIEW; if (!(flags & TGL_SEND_MSG_FLAG_ENABLE_PREVIEW) && TLS->disable_link_preview) { disable_preview = 1; } if (disable_preview) { disable_preview = TGLMF_DISABLE_PREVIEW; } struct tl_ds_message_media TDSM; TDSM.magic = CODE_message_media_empty; tgl_peer_id_t from_id; if (flags & TGLMF_POST_AS_CHANNEL) { from_id = peer_id; } else { from_id = TLS->our_id; } struct tl_ds_vector *EN = NULL; char *new_text = NULL; if (flags & TGLMF_HTML) { int ent_size = 0; int *ent = NULL; text = new_text = process_html_text (TLS, text, text_len, &ent_size, &ent); if (!text) { tfree (ent, ent_size); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } text_len = strlen (new_text); int *save_ptr = in_ptr; int *save_end = in_end; in_ptr = ent; in_end = ent + ent_size; EN = fetch_ds_type_any (TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (message_entity))); assert (EN); vlogprintf (E_DEBUG, "in_ptr = %p, in_end = %p\n", in_ptr, in_end); assert (in_ptr == in_end); in_ptr = save_ptr; in_end = save_end; tfree (ent, 4 * ent_size); } bl_do_edit_message (TLS, &id, &from_id, &peer_id, NULL, NULL, &date, text, text_len, &TDSM, NULL, reply ? &reply : NULL, reply_markup, EN, TGLMF_UNREAD | TGLMF_OUT | TGLMF_PENDING | TGLMF_CREATE | TGLMF_CREATED | TGLMF_SESSION_OUTBOUND | disable_preview); if (flags & TGLMF_HTML) { tfree_str (new_text); free_ds_type_any (EN, TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (message_entity))); } } else { struct tl_ds_decrypted_message_media TDSM; TDSM.magic = CODE_decrypted_message_media_empty; tgl_peer_id_t from_id = TLS->our_id; bl_do_edit_message_encr (TLS, &id, &from_id, &peer_id, &date, text, text_len, &TDSM, NULL, NULL, TGLMF_UNREAD | TGLMF_OUT | TGLMF_PENDING | TGLMF_CREATE | TGLMF_CREATED | TGLMF_SESSION_OUTBOUND | TGLMF_ENCRYPTED); } struct tgl_message *M = tgl_message_get (TLS, &id); assert (M); tgl_do_send_msg (TLS, M, callback, callback_extra); } void tgl_do_reply_message (struct tgl_state *TLS, tgl_message_id_t *_reply_id, const char *text, int text_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t reply_id = *_reply_id; if (reply_id.peer_type == TGL_PEER_TEMP_ID) { reply_id = tgl_convert_temp_msg_id (TLS, reply_id); } if (reply_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (reply_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not reply on message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } tgl_peer_id_t peer_id = tgl_msg_id_to_peer_id (reply_id); tgl_do_send_message (TLS, peer_id, text, text_len, flags | TGL_SEND_MSG_FLAG_REPLY (reply_id.id), NULL, callback, callback_extra); } /* }}} */ /* {{{ Send text file */ void tgl_do_send_text (struct tgl_state *TLS, tgl_peer_id_t id, const char *file_name, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { int fd = open (file_name, O_RDONLY | O_BINARY); if (fd < 0) { tgl_set_query_error (TLS, EBADF, "Can not open file: %s", strerror(errno)); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } static char buf[(1 << 20) + 1]; int x = read (fd, buf, (1 << 20) + 1); if (x < 0) { tgl_set_query_error (TLS, EBADF, "Can not read from file: %s", strerror(errno)); close (fd); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } assert (x >= 0); close (fd); if (x == (1 << 20) + 1) { tgl_set_query_error (TLS, E2BIG, "text file is too big"); if (callback) { callback (TLS, callback_extra, 0, NULL); } } else { tgl_do_send_message (TLS, id, buf, x, flags, NULL, callback, callback_extra); } } void tgl_do_reply_text (struct tgl_state *TLS, tgl_message_id_t *_reply_id, const char *file_name, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t reply_id = *_reply_id; if (reply_id.peer_type == TGL_PEER_TEMP_ID) { reply_id = tgl_convert_temp_msg_id (TLS, reply_id); } if (reply_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (reply_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not reply on message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } tgl_peer_id_t peer_id = tgl_msg_id_to_peer_id (reply_id); tgl_do_send_text (TLS, peer_id, file_name, flags | TGL_SEND_MSG_FLAG_REPLY (reply_id.id), callback, callback_extra); } /* }}} */ /* {{{ Mark read */ struct mark_read_extra { tgl_peer_id_t id; int max_id; }; void tgl_do_messages_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, int max_id, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra); static int mark_read_channels_on_receive (struct tgl_state *TLS, struct query *q, void *D) { struct mark_read_extra *E = q->extra; bl_do_channel (TLS, tgl_get_peer_id (E->id), NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, &E->max_id, TGL_FLAGS_UNCHANGED); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } tfree (E, sizeof (*E)); return 0; } static int mark_read_on_receive (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_affected_messages *DS_MAM = D; int r = tgl_check_pts_diff (TLS, DS_LVAL (DS_MAM->pts), DS_LVAL (DS_MAM->pts_count)); if (r > 0) { bl_do_set_pts (TLS, DS_LVAL (DS_MAM->pts)); } struct mark_read_extra *E = q->extra; if (tgl_get_peer_type (E->id) == TGL_PEER_USER) { bl_do_user (TLS, tgl_get_peer_id (E->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, &E->max_id, NULL, NULL, TGL_FLAGS_UNCHANGED); } else { assert (tgl_get_peer_type (E->id) == TGL_PEER_CHAT); bl_do_chat (TLS, tgl_get_peer_id (E->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &E->max_id, NULL, TGL_FLAGS_UNCHANGED); } if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } tfree (E, sizeof (*E)); return 0; } static int mark_read_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct mark_read_extra *E = q->extra; tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 0); } return 0; } static struct query_methods mark_read_methods = { .on_answer = mark_read_on_receive, .on_error = mark_read_on_error, .type = TYPE_TO_PARAM(messages_affected_messages), .name = "mark read" }; static struct query_methods mark_read_channels_methods = { .on_answer = mark_read_channels_on_receive, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(bool), .name = "mark read (channels)" }; void tgl_do_messages_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, int max_id, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra) { if (TLS->is_bot) { return; } if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { tgl_do_mark_read (TLS, id, callback, callback_extra); return; } clear_packet (); if (tgl_get_peer_type (id) != TGL_PEER_CHANNEL) { out_int (CODE_messages_read_history); out_peer_id (TLS, id); out_int (max_id); //out_int (offset); struct mark_read_extra *E = talloc (sizeof (*E)); E->id = id; E->max_id = max_id; tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, E, callback, callback_extra); } else { out_int (CODE_channels_read_history); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); out_int (max_id); struct mark_read_extra *E = talloc (sizeof (*E)); E->id = id; E->max_id = max_id; tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_channels_methods, E, callback, callback_extra); } } void tgl_do_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_USER || tgl_get_peer_type (id) == TGL_PEER_CHAT || tgl_get_peer_type (id) == TGL_PEER_CHANNEL) { tgl_do_messages_mark_read (TLS, id, 0, 0, callback, callback_extra); return; } assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT); tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P) { tgl_set_query_error (TLS, EINVAL, "unknown secret chat"); if (callback) { callback (TLS, callback_extra, 0); } return; } if (P->last) { tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, P->last->date, callback, callback_extra); } else { tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, time (0) - 10, callback, callback_extra); } } /* }}} */ /* {{{ Get history */ struct get_history_extra { struct tgl_message **ML; int list_offset; int list_size; tgl_peer_id_t id; int limit; int offset; int max_id; }; static void _tgl_do_get_history (struct tgl_state *TLS, struct get_history_extra *E, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra); static int get_history_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_messages *DS_MM = D; int i; for (i = 0; i < DS_LVAL (DS_MM->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_MM->chats->data[i]); } for (i = 0; i < DS_LVAL (DS_MM->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_MM->users->data[i]); } struct get_history_extra *E = q->extra; int n = DS_LVAL (DS_MM->messages->cnt); if (E->list_size - E->list_offset < n) { int new_list_size = 2 * E->list_size; if (new_list_size - E->list_offset < n) { new_list_size = n + E->list_offset; } E->ML = trealloc (E->ML, E->list_size * sizeof (void *), new_list_size * sizeof (void *)); assert (E->ML); E->list_size = new_list_size; } for (i = 0; i < n; i++) { E->ML[i + E->list_offset] = tglf_fetch_alloc_message (TLS, DS_MM->messages->data[i], NULL); } E->list_offset += n; E->offset += n; E->limit -= n; int count = DS_LVAL (DS_MM->count); if (count >= 0 && E->limit + E->offset >= count) { E->limit = count - E->offset; if (E->limit < 0) { E->limit = 0; } } assert (E->limit >= 0); if (E->limit <= 0 || DS_MM->magic == CODE_messages_messages || DS_MM->magic == CODE_messages_channel_messages) { if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 1, E->list_offset, E->ML); } /*if (E->list_offset > 0) { tgl_do_messages_mark_read (TLS, E->id, E->ML[0]->id, 0, 0, 0); }*/ tfree (E->ML, sizeof (void *) * E->list_size); tfree (E, sizeof (*E)); } else { E->offset = 0; E->max_id = E->ML[E->list_offset - 1]->permanent_id.id; _tgl_do_get_history (TLS, E, q->callback, q->callback_extra); } return 0; } static int get_history_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct get_history_extra *E = q->extra; tfree (E->ML, sizeof (void *) * E->list_size); tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 0, 0, NULL); } return 0; } static struct query_methods get_history_methods = { .on_answer = get_history_on_answer, .on_error = get_history_on_error, .type = TYPE_TO_PARAM(messages_messages), .name = "get history" }; void tgl_do_get_local_history (struct tgl_state *TLS, tgl_peer_id_t id, int offset, int limit, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P || !P->last) { tgl_set_query_error (TLS, EINVAL, "unknown peer"); if (callback) { callback (TLS, callback_extra, 0, 0, 0); } return; } struct tgl_message *M = P->last; int count = 1; assert (!M->prev); while (count < limit + offset && M->next) { M = M->next; count ++; } if (count <= offset) { if (callback) { callback (TLS, callback_extra, 1, 0, 0); } return; } struct tgl_message **ML = talloc (sizeof (void *) * (count - offset)); M = P->last; ML[0] = M; count = 1; while (count < limit && M->next) { M = M->next; if (count >= offset) { ML[count - offset] = M; } count ++; } if (callback) { callback (TLS, callback_extra, 1, count - offset, ML); } tfree (ML, sizeof (void *) * (count) - offset); } static void _tgl_do_get_history (struct tgl_state *TLS, struct get_history_extra *E, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { clear_packet (); tgl_peer_t *C = tgl_peer_get (TLS, E->id); if (tgl_get_peer_type (E->id) != TGL_PEER_CHANNEL || (C && (C->flags & TGLCHF_MEGAGROUP))) { out_int (CODE_messages_get_history); out_peer_id (TLS, E->id); } else { out_int (CODE_channels_get_important_history); out_int (CODE_input_channel); out_int (tgl_get_peer_id (E->id)); out_long (E->id.access_hash); } out_int (E->max_id); out_int (E->offset); out_int (E->limit); out_int (0); out_int (0); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, E, callback, callback_extra); } void tgl_do_get_history (struct tgl_state *TLS, tgl_peer_id_t id, int offset, int limit, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT || offline_mode) { tgl_do_get_local_history (TLS, id, offset, limit, callback, callback_extra); //tgl_do_mark_read (TLS, id, 0, 0); return; } struct get_history_extra *E = talloc0 (sizeof (*E)); E->id = id; E->limit = limit; E->offset = offset; _tgl_do_get_history (TLS, E, callback, callback_extra); } /* }}} */ /* {{{ Get dialogs */ struct get_dialogs_extra { tgl_peer_id_t *PL; int *UC; tgl_message_id_t **LM; tgl_message_id_t *LMD; int *LRM; int list_offset; int list_size; int limit; int offset; int offset_date; int max_id; tgl_peer_id_t offset_peer; int channels; }; static void _tgl_do_get_dialog_list (struct tgl_state *TLS, struct get_dialogs_extra *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]), void *callback_extra); static int get_dialogs_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_dialogs *DS_MD = D; struct get_dialogs_extra *E = q->extra; int dl_size = DS_LVAL (DS_MD->dialogs->cnt); int i; for (i = 0; i < DS_LVAL (DS_MD->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_MD->chats->data[i]); } for (i = 0; i < DS_LVAL (DS_MD->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_MD->users->data[i]); } if (E->list_offset + dl_size > E->list_size) { int new_list_size = E->list_size * 2; if (new_list_size < E->list_offset + dl_size) { new_list_size = E->list_offset + dl_size; } E->PL = trealloc (E->PL, E->list_size * sizeof (tgl_peer_id_t), new_list_size * sizeof (tgl_peer_id_t)); assert (E->PL); E->UC = trealloc (E->UC, E->list_size * sizeof (int), new_list_size * sizeof (int)); assert (E->UC); E->LM = trealloc (E->LM, E->list_size * sizeof (void *), new_list_size * sizeof (void *)); assert (E->LM); E->LMD = trealloc (E->LMD, E->list_size * sizeof (tgl_message_id_t), new_list_size * sizeof (tgl_message_id_t)); assert (E->LMD); E->LRM = trealloc (E->LRM, E->list_size * sizeof (int), new_list_size * sizeof (int)); assert (E->LRM); E->list_size = new_list_size; int i; for (i = 0; i < E->list_offset; i++) { E->LM[i] = &E->LMD[i]; } } for (i = 0; i < dl_size; i++) { struct tl_ds_dialog *DS_D = DS_MD->dialogs->data[i]; tgl_peer_t *P = tgl_peer_get (TLS, tglf_fetch_peer_id (TLS, DS_D->peer)); assert (P); E->PL[E->list_offset + i] = P->id; E->LMD[E->list_offset + i] = tgl_peer_id_to_msg_id (E->PL[E->list_offset + i], DS_LVAL (DS_D->top_message)); E->LM[E->list_offset + i] = &E->LMD[E->list_offset + i]; E->UC[E->list_offset + i] = DS_LVAL (DS_D->unread_count); E->LRM[E->list_offset + i] = DS_LVAL (DS_D->read_inbox_max_id); } E->list_offset += dl_size; for (i = 0; i < DS_LVAL (DS_MD->messages->cnt); i++) { tglf_fetch_alloc_message (TLS, DS_MD->messages->data[i], NULL); } vlogprintf (E_DEBUG, "dl_size = %d, total = %d\n", dl_size, E->list_offset); if (dl_size && E->list_offset < E->limit && DS_MD->magic == CODE_messages_dialogs_slice && E->list_offset < DS_LVAL (DS_MD->count)) { E->offset += dl_size; if (E->list_offset > 0) { E->offset_peer = E->PL[E->list_offset - 1]; int p = E->list_offset - 1; while (p >= 0) { struct tgl_message *M = tgl_message_get (TLS, E->LM[p]); if (M) { E->offset_date = M->date; break; } p --; } } _tgl_do_get_dialog_list (TLS, E, q->callback, q->callback_extra); } else { if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, int, tgl_peer_id_t *, tgl_message_id_t **, int *))q->callback) (TLS, q->callback_extra, 1, E->list_offset, E->PL, E->LM, E->UC); } tfree (E->PL, sizeof (tgl_peer_id_t) * E->list_size); tfree (E->UC, 4 * E->list_size); tfree (E->LM, sizeof (void *) * E->list_size); tfree (E->LMD, sizeof (tgl_message_id_t) * E->list_size); tfree (E->LRM, 4 * E->list_size); tfree (E, sizeof (*E)); } return 0; } static int get_dialogs_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct get_dialogs_extra *E = q->extra; tfree (E->PL, sizeof (tgl_peer_id_t) * E->list_size); tfree (E->UC, 4 * E->list_size); tfree (E->LM, sizeof (void *) * E->list_size); tfree (E->LMD, sizeof (tgl_message_id_t) * E->list_size); tfree (E->LRM, 4 * E->list_size); tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *TLS, void *, int, int, tgl_peer_id_t *, tgl_message_id_t **, int *))q->callback) (TLS, q->callback_extra, 0, 0, NULL, NULL, NULL); } return 0; } static struct query_methods get_dialogs_methods = { .on_answer = get_dialogs_on_answer, .on_error = get_dialogs_on_error, .type = TYPE_TO_PARAM(messages_dialogs), .name = "get dialogs" }; static void _tgl_do_get_dialog_list (struct tgl_state *TLS, struct get_dialogs_extra *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]), void *callback_extra) { clear_packet (); if (E->channels) { out_int (CODE_channels_get_dialogs); out_int (E->offset); out_int (E->limit - E->list_offset); } else { out_int (CODE_messages_get_dialogs); out_int (E->offset_date); out_int (E->offset); //out_int (0); if (E->offset_peer.peer_type) { out_peer_id (TLS, E->offset_peer); } else { out_int (CODE_input_peer_empty); } out_int (E->limit - E->list_offset); } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, E, callback, callback_extra); } void tgl_do_get_dialog_list (struct tgl_state *TLS, int limit, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]), void *callback_extra) { struct get_dialogs_extra *E = talloc0 (sizeof (*E)); E->limit = limit; E->offset = offset; E->channels = 0; _tgl_do_get_dialog_list (TLS, E, callback, callback_extra); } void tgl_do_get_channels_dialog_list (struct tgl_state *TLS, int limit, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]), void *callback_extra) { struct get_dialogs_extra *E = talloc0 (sizeof (*E)); E->limit = limit; E->offset = offset; E->channels = 1; E->offset_date = 0; E->offset_peer.peer_type = 0; _tgl_do_get_dialog_list (TLS, E, callback, callback_extra); } /* }}} */ int allow_send_linux_version = 1; /* {{{ Send document file */ static void out_peer_id (struct tgl_state *TLS, tgl_peer_id_t id) { switch (tgl_get_peer_type (id)) { case TGL_PEER_CHAT: out_int (CODE_input_peer_chat); out_int (tgl_get_peer_id (id)); break; case TGL_PEER_USER: out_int (CODE_input_peer_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); break; case TGL_PEER_CHANNEL: out_int (CODE_input_peer_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); break; default: assert (0); } } static void send_part (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra); static int send_file_part_on_answer (struct tgl_state *TLS, struct query *q, void *D) { send_part (TLS, q->extra, q->callback, q->callback_extra); return 0; } static int set_photo_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static int send_file_part_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct send_file *f = q->extra; tfree_str (f->file_name); tfree_str (f->caption); if (!f->avatar.peer_type) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 0, 0); } } else { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 0); } } tfree (f, sizeof (*f)); return 0; } static struct query_methods send_file_part_methods = { .on_answer = send_file_part_on_answer, .on_error = send_file_part_on_error, .type = TYPE_TO_PARAM(bool), .name = "send file part" }; static struct query_methods set_photo_methods = { .on_answer = set_photo_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(photos_photo), .name = "set photo" }; static void send_avatar_end (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) { switch (tgl_get_peer_type (f->avatar)) { case TGL_PEER_CHAT: out_int (CODE_messages_edit_chat_photo); out_int (f->avatar.peer_id); out_int (CODE_input_chat_uploaded_photo); break; case TGL_PEER_USER: out_int (CODE_photos_upload_profile_photo); out_int (CODE_photos_upload_profile_photo); break; case TGL_PEER_CHANNEL: out_int (CODE_channels_edit_photo); out_int (CODE_input_channel); out_int (f->avatar.peer_id); out_long (f->avatar.access_hash); out_int (CODE_input_chat_uploaded_photo); break; default: assert (0); } if (f->size < (16 << 20)) { out_int (CODE_input_file); } else { out_int (CODE_input_file_big); } out_long (f->id); out_int (f->part_num); char *s = f->file_name + strlen (f->file_name); while (s >= f->file_name && *s != '/') { s --;} out_string (s + 1); if (f->size < (16 << 20)) { out_string (""); } if (f->avatar.peer_type != TGL_PEER_USER) { out_int (CODE_input_photo_crop_auto); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, NULL, callback, callback_extra); } else { out_string ("profile photo"); out_int (CODE_input_geo_point_empty); out_int (CODE_input_photo_crop_auto); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_photo_methods, 0, callback, callback_extra); } } static void send_file_unencrypted_end (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) { out_int (CODE_messages_send_media); out_int ((f->reply ? 1 : 0) | f->channel); out_peer_id (TLS, f->to_id); if (f->reply) { out_int (f->reply); } if (f->flags & TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO) { out_int (CODE_input_media_uploaded_photo); } else { if (f->thumb_id > 0) { out_int (CODE_input_media_uploaded_thumb_document); } else { out_int (CODE_input_media_uploaded_document); } } if (f->size < (16 << 20)) { out_int (CODE_input_file); } else { out_int (CODE_input_file_big); } out_long (f->id); out_int (f->part_num); char *s = f->file_name + strlen (f->file_name); while (s >= f->file_name && *s != '/') { s --;} out_string (s + 1); if (f->size < (16 << 20)) { out_string (""); } if (!(f->flags & TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO)) { out_string (tg_mime_by_filename (f->file_name)); out_int (CODE_vector); if (f->flags & TGLDF_IMAGE) { if (f->flags & TGLDF_ANIMATED) { out_int (2); out_int (CODE_document_attribute_image_size); out_int (f->w); out_int (f->h); out_int (CODE_document_attribute_animated); } else { out_int (1); out_int (CODE_document_attribute_image_size); out_int (f->w); out_int (f->h); } } else if (f->flags & TGLDF_AUDIO) { out_int (2); out_int (CODE_document_attribute_audio); out_int (f->duration); out_string (""); out_string (""); out_int (CODE_document_attribute_filename); out_string (s + 1); } else if (f->flags & TGLDF_VIDEO) { out_int (2); out_int (CODE_document_attribute_video); out_int (f->duration); out_int (f->w); out_int (f->h); out_int (CODE_document_attribute_filename); out_string (s + 1); } else if (f->flags & TGLDF_STICKER) { out_int (1); out_int (CODE_document_attribute_sticker); } else { out_int (1); out_int (CODE_document_attribute_filename); out_string (s + 1); } if (f->thumb_id > 0) { out_int (CODE_input_file); out_long (f->thumb_id); out_int (1); out_string ("thumb.jpg"); out_string (""); } out_string (f->caption ? f->caption : ""); } else { out_string (f->caption ? f->caption : ""); } struct messages_send_extra *E = talloc0 (sizeof (*E)); E->id = tgl_peer_id_to_random_msg_id (f->to_id); out_long (E->id.id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); tfree_str (f->file_name); tfree_str (f->caption); tfree (f, sizeof (*f)); } static void send_file_end (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) { TLS->cur_uploaded_bytes -= f->size; TLS->cur_uploading_bytes -= f->size; clear_packet (); if (f->avatar.peer_id) { send_avatar_end (TLS, f, callback, callback_extra); return; } if (!f->encr) { send_file_unencrypted_end (TLS, f, callback, callback_extra); return; } send_file_encrypted_end (TLS, f, callback, callback_extra); return; } static void send_part (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) { if (f->fd >= 0) { if (!f->part_num) { TLS->cur_uploading_bytes += f->size; } clear_packet (); if (f->size < (16 << 20)) { out_int (CODE_upload_save_file_part); out_long (f->id); out_int (f->part_num ++); } else { out_int (CODE_upload_save_big_file_part); out_long (f->id); out_int (f->part_num ++); out_int ((f->size + f->part_size - 1) / f->part_size); } static char buf[512 << 10]; int x = read (f->fd, buf, f->part_size); assert (x > 0); f->offset += x; TLS->cur_uploaded_bytes += x; if (f->encr) { if (x & 15) { assert (f->offset == f->size); tglt_secure_random (buf + x, (-x) & 15); x = (x + 15) & ~15; } TGLC_aes_key aes_key; TGLC_aes_set_encrypt_key (f->key, 256, &aes_key); TGLC_aes_ige_encrypt ((void *)buf, (void *)buf, x, &aes_key, f->iv, 1); memset (&aes_key, 0, sizeof (aes_key)); } out_cstring (buf, x); vlogprintf (E_DEBUG, "offset=%" INT64_PRINTF_MODIFIER "d size=%" INT64_PRINTF_MODIFIER "d\n", f->offset, f->size); if (f->offset == f->size) { close (f->fd); f->fd = -1; } else { assert (f->part_size == x); } //update_prompt (); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra); } else { send_file_end (TLS, f, callback, callback_extra); } } static void send_file_thumb (struct tgl_state *TLS, struct send_file *f, const void *thumb_data, int thumb_len, void *callback, void *callback_extra) { clear_packet (); tglt_secure_random (&f->thumb_id, 8); out_int (CODE_upload_save_file_part); out_long (f->thumb_id); out_int (0); out_cstring ((void *)thumb_data, thumb_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra); } static void _tgl_do_send_photo (struct tgl_state *TLS, tgl_peer_id_t to_id, const char *file_name, tgl_peer_id_t avatar, int w, int h, int duration, const void *thumb_data, int thumb_len, const char *caption, int caption_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { int fd = open (file_name, O_RDONLY | O_BINARY); if (fd < 0) { tgl_set_query_error (TLS, EBADF, "Can not open file: %s", strerror(errno)); if (!avatar.peer_id) { if (callback) { callback (TLS, callback_extra, 0, 0); } } else { if (callback) { ((void (*)(struct tgl_state *, void *, int))callback) (TLS, callback_extra, 0); } } return; } struct stat buf; fstat (fd, &buf); long long size = buf.st_size; if (size <= 0) { tgl_set_query_error (TLS, EBADF, "File is empty"); close (fd); if (!avatar.peer_id) { if (callback) { callback (TLS, callback_extra, 0, 0); } } else { if (callback) { ((void (*)(struct tgl_state *, void *, int))callback) (TLS, callback_extra, 0); } } return; } struct send_file *f = talloc0 (sizeof (*f)); f->fd = fd; f->size = size; f->offset = 0; f->part_num = 0; f->avatar = avatar; f->reply = flags >> 32; int tmp = ((size + 2999) / 3000); f->part_size = (1 << 14); while (f->part_size < tmp) { f->part_size *= 2; } f->flags = flags; f->channel = 0; if (flags & TGLMF_POST_AS_CHANNEL) { f->channel = 16; } if (f->part_size > (512 << 10)) { close (fd); tgl_set_query_error (TLS, E2BIG, "File is too big"); tfree (f, sizeof (*f)); if (!avatar.peer_id) { if (callback) { callback (TLS, callback_extra, 0, 0); } } else { if (callback) { ((void (*)(struct tgl_state *, void *, int))callback) (TLS, callback_extra, 0); } } return; } tglt_secure_random (&f->id, 8); f->to_id = to_id; f->flags = flags; f->file_name = tstrdup (file_name); f->w = w; f->h = h; f->duration = duration; f->caption = caption ? tstrdup (caption) : tstrdup (""); if (tgl_get_peer_type (f->to_id) == TGL_PEER_ENCR_CHAT) { f->encr = 1; f->iv = talloc (32); tglt_secure_random (f->iv, 32); f->init_iv = talloc (32); memcpy (f->init_iv, f->iv, 32); f->key = talloc (32); tglt_secure_random (f->key, 32); } if (!f->encr && f->flags != -1 && thumb_len > 0) { send_file_thumb (TLS, f, thumb_data, thumb_len, callback, callback_extra); } else { send_part (TLS, f, callback, callback_extra); } } void tgl_do_send_document (struct tgl_state *TLS, tgl_peer_id_t to_id, const char *file_name, const char *caption, int caption_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (flags & TGL_SEND_MSG_FLAG_DOCUMENT_AUTO) { char *mime_type = tg_mime_by_filename (file_name); if (strcmp (mime_type, "image/gif") == 0) { flags |= TGL_SEND_MSG_FLAG_DOCUMENT_ANIMATED; } else if (!memcmp (mime_type, "image/", 6)) { flags |= TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO; } else if (!memcmp (mime_type, "video/", 6)) { flags |= TGLDF_VIDEO; } else if (!memcmp (mime_type, "audio/", 6)) { flags |= TGLDF_AUDIO; } } tgl_peer_id_t x; x.peer_id = 0; _tgl_do_send_photo (TLS, to_id, file_name, x, 100, 100, 100, 0, 0, caption, caption_len, flags, callback, callback_extra); } void tgl_do_reply_document (struct tgl_state *TLS, tgl_message_id_t *_reply_id, const char *file_name, const char *caption, int caption_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t reply_id = *_reply_id; if (reply_id.peer_type == TGL_PEER_TEMP_ID) { reply_id = tgl_convert_temp_msg_id (TLS, reply_id); } if (reply_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (reply_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not reply on message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } tgl_peer_id_t peer_id = tgl_msg_id_to_peer_id (reply_id); tgl_do_send_document (TLS, peer_id, file_name, caption, caption_len, flags | TGL_SEND_MSG_FLAG_REPLY (reply_id.id), callback, callback_extra); } void tgl_do_set_chat_photo (struct tgl_state *TLS, tgl_peer_id_t chat_id, const char *file_name, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success), void *callback_extra) { assert (tgl_get_peer_type (chat_id) == TGL_PEER_CHAT); _tgl_do_send_photo (TLS, chat_id, file_name, chat_id, 0, 0, 0, 0, 0, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, (void *)callback, callback_extra); } void tgl_do_set_channel_photo (struct tgl_state *TLS, tgl_peer_id_t chat_id, const char *file_name, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success), void *callback_extra) { assert (tgl_get_peer_type (chat_id) == TGL_PEER_CHANNEL); _tgl_do_send_photo (TLS, chat_id, file_name, chat_id, 0, 0, 0, 0, 0, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, (void *)callback, callback_extra); } void tgl_do_set_profile_photo (struct tgl_state *TLS, const char *file_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { _tgl_do_send_photo (TLS, TLS->our_id, file_name, TLS->our_id, 0, 0, 0, 0, 0, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, (void *)callback, callback_extra); } /* }}} */ /* {{{ Profile name */ int set_profile_name_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_user *DS_U = D; struct tgl_user *U = tglf_fetch_alloc_user (TLS, DS_U); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U); } return 0; } static struct query_methods set_profile_name_methods = { .on_answer = set_profile_name_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(user), .name = "set profile name" }; void tgl_do_set_profile_name (struct tgl_state *TLS, const char *first_name, int first_name_len, const char *last_name, int last_name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) { clear_packet (); out_int (CODE_account_update_profile); out_cstring (first_name, first_name_len); out_cstring (last_name, last_name_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_profile_name_methods, 0, callback, callback_extra); } void tgl_do_set_username (struct tgl_state *TLS, const char *username, int username_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) { clear_packet (); out_int (CODE_account_update_username); out_cstring (username, username_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_profile_name_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Contacts search */ int contact_search_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_contacts_resolved_peer *DS_CRU = D; tgl_peer_id_t peer_id = tglf_fetch_peer_id (TLS, DS_CRU->peer); int i; for (i = 0; i < DS_LVAL (DS_CRU->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_CRU->users->data[i]); } for (i = 0; i < DS_LVAL (DS_CRU->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_CRU->chats->data[i]); } tgl_peer_t *P = tgl_peer_get (TLS, peer_id); if (q->callback) { ((void (*)(struct tgl_state *,void *, int, tgl_peer_t *))q->callback) (TLS, q->callback_extra, 1, P); } return 0; } static struct query_methods contact_search_methods = { .on_answer = contact_search_on_answer, .on_error = q_list_on_error, .type = TYPE_TO_PARAM(contacts_resolved_peer), .name = "contacts search" }; void tgl_do_contact_search (struct tgl_state *TLS, const char *name, int name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, tgl_peer_t *U), void *callback_extra) { clear_packet (); out_int (CODE_contacts_resolve_username); out_cstring (name, name_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &contact_search_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Forward */ static int send_msgs_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct messages_send_extra *E = q->extra; tglu_work_any_updates (TLS, 1, D, (!E || E->multi) ? NULL : tgl_message_get (TLS, &E->id)); tglu_work_any_updates (TLS, 0, D, (!E || E->multi) ? NULL : tgl_message_get (TLS, &E->id)); if (!E) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } } else if (E->multi) { struct tgl_message **ML = talloc (sizeof (void *) * E->count); int count = E->count; int i; for (i = 0; i < count; i++) { struct tgl_message_id id; id.peer_type = TGL_PEER_RANDOM_ID; id.id = E->list[i].id; ML[i] = tgl_message_get (TLS, &id); } tfree (E->list, sizeof (tgl_message_id_t) * count); tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 1, count, ML); } tfree (ML, sizeof (void *) * count); } else { struct tgl_message_id id; id.peer_type = TGL_PEER_RANDOM_ID; id.id = E->id.id; struct tgl_message *M = tgl_message_get (TLS, &id); tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M); } } return 0; } static int send_msgs_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct messages_send_extra *E = q->extra; if (!E) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 0); } } else if (E->multi) { int count = E->count; tfree (E->list, sizeof (tgl_message_id_t) * count); tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 0, 0, NULL); } } else { tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 0, NULL); } } return 0; } static struct query_methods send_msgs_methods = { .on_answer = send_msgs_on_answer, .on_error = send_msgs_on_error, .type = TYPE_TO_PARAM(updates), .name = "forward messages" }; void tgl_do_forward_messages (struct tgl_state *TLS, tgl_peer_id_t id, int n, const tgl_message_id_t *_ids[], unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int count, struct tgl_message *ML[]), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not forward messages to secret chats"); if (callback) { callback (TLS, callback_extra, 0, 0, 0); } return; } tgl_peer_id_t from_id = TGL_MK_USER (0); tgl_message_id_t *ids = talloc (sizeof (tgl_message_id_t) * n); int i; for (i = 0; i < n; i++) { tgl_message_id_t msg_id = *_ids[i]; if (msg_id.peer_type == TGL_PEER_TEMP_ID) { msg_id = tgl_convert_temp_msg_id (TLS, msg_id); } if (msg_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0, NULL); } tfree (ids, n * sizeof (tgl_message_id_t)); return; } if (msg_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not forward message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0, NULL); } tfree (ids, n * sizeof (tgl_message_id_t)); return; } ids[i] = msg_id; if (i == 0) { from_id = tgl_msg_id_to_peer_id (msg_id); } else { if (tgl_cmp_peer_id (from_id, tgl_msg_id_to_peer_id (msg_id))) { tgl_set_query_error (TLS, EINVAL, "can not forward messages from different dialogs"); if (callback) { callback (TLS, callback_extra, 0, 0, NULL); } tfree (ids, n * sizeof (tgl_message_id_t)); return; } } } clear_packet (); out_int (CODE_messages_forward_messages); unsigned f = 0; if (flags & TGLMF_POST_AS_CHANNEL) { f |= 16; } out_int (f); out_peer_id (TLS, from_id); out_int (CODE_vector); out_int (n); for (i = 0; i < n; i++) { out_int (ids[i].id); } struct messages_send_extra *E = talloc0 (sizeof (*E)); E->multi = 1; E->count = n; E->list = talloc (sizeof (tgl_message_id_t) * n); out_int (CODE_vector); out_int (n); for (i = 0; i < n; i++) { E->list[i] = tgl_peer_id_to_random_msg_id (id); assert (E->list[i].id); out_long (E->list[i].id); } out_peer_id (TLS, id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); tfree (ids, n * sizeof (tgl_message_id_t)); } void tgl_do_forward_message (struct tgl_state *TLS, tgl_peer_id_t peer_id, tgl_message_id_t *_msg_id, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t msg_id = *_msg_id; if (msg_id.peer_type == TGL_PEER_TEMP_ID) { msg_id = tgl_convert_temp_msg_id (TLS, msg_id); } if (msg_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (msg_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not forward messages from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (peer_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not forward messages to secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } clear_packet (); out_int (CODE_messages_forward_message); tgl_peer_id_t from_peer = tgl_msg_id_to_peer_id (msg_id); out_peer_id (TLS, from_peer); out_int (msg_id.id); struct messages_send_extra *E = talloc0 (sizeof (*E)); E->id = tgl_peer_id_to_random_msg_id (peer_id); out_long (E->id.id); out_peer_id (TLS, peer_id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); } void tgl_do_send_contact (struct tgl_state *TLS, tgl_peer_id_t id, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not send contact to secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } int reply_id = flags >> 32; clear_packet (); out_int (CODE_messages_send_media); out_int (reply_id ? 1 : 0); if (reply_id) { out_int (reply_id); } out_peer_id (TLS, id); out_int (CODE_input_media_contact); out_cstring (phone, phone_len); out_cstring (first_name, first_name_len); out_cstring (last_name, last_name_len); struct messages_send_extra *E = talloc0 (sizeof (*E)); tglt_secure_random (&E->id, 8); out_long (E->id.id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); } void tgl_do_reply_contact (struct tgl_state *TLS, tgl_message_id_t *_reply_id, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t reply_id = *_reply_id; if (reply_id.peer_type == TGL_PEER_TEMP_ID) { reply_id = tgl_convert_temp_msg_id (TLS, reply_id); } if (reply_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (reply_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not reply on message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } tgl_peer_id_t peer_id = tgl_msg_id_to_peer_id (reply_id); tgl_do_send_contact (TLS, peer_id, phone, phone_len, first_name, first_name_len, last_name, last_name_len, flags | TGL_SEND_MSG_FLAG_REPLY (reply_id.id), callback, callback_extra); } void tgl_do_forward_media (struct tgl_state *TLS, tgl_peer_id_t peer_id, tgl_message_id_t *_msg_id, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (peer_id) == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not forward messages to secret chats"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } tgl_message_id_t msg_id = *_msg_id; if (msg_id.peer_type == TGL_PEER_TEMP_ID) { msg_id = tgl_convert_temp_msg_id (TLS, msg_id); } if (msg_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (msg_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not forward message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (!M || !(M->flags & TGLMF_CREATED) || (M->flags & TGLMF_ENCRYPTED)) { if (!M || !(M->flags & TGLMF_CREATED)) { tgl_set_query_error (TLS, EINVAL, "unknown message"); } else { tgl_set_query_error (TLS, EINVAL, "can not forward message from secret chat"); } if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_audio && M->media.type != tgl_message_media_video) { tgl_set_query_error (TLS, EINVAL, "can only forward photo/document"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } clear_packet (); out_int (CODE_messages_send_media); int f = 0; if (flags & TGLMF_POST_AS_CHANNEL) { f |= 16; } out_int (f); out_peer_id (TLS, peer_id); switch (M->media.type) { case tgl_message_media_photo: assert (M->media.photo); out_int (CODE_input_media_photo); out_int (CODE_input_photo); out_long (M->media.photo->id); out_long (M->media.photo->access_hash); out_string (""); break; case tgl_message_media_document: case tgl_message_media_audio: case tgl_message_media_video: assert (M->media.document); out_int (CODE_input_media_document); out_int (CODE_input_document); out_long (M->media.document->id); out_long (M->media.document->access_hash); out_string (""); break; default: assert (0); } struct messages_send_extra *E = talloc0 (sizeof (*E)); E->id = tgl_peer_id_to_random_msg_id (peer_id); out_long (E->id.id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); } /* }}} */ /* {{{ Send location */ void tgl_do_send_location (struct tgl_state *TLS, tgl_peer_id_t peer_id, double latitude, double longitude, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (peer_id) == TGL_PEER_ENCR_CHAT) { tgl_do_send_location_encr (TLS, peer_id, latitude, longitude, flags, callback, callback_extra); } else { int reply_id = flags >> 32; clear_packet (); out_int (CODE_messages_send_media); unsigned f = reply_id ? 1 : 0; if (flags & TGLMF_POST_AS_CHANNEL) { f |= 16; } out_int (f); if (reply_id) { out_int (reply_id); } out_peer_id (TLS, peer_id); out_int (CODE_input_media_geo_point); out_int (CODE_input_geo_point); out_double (latitude); out_double (longitude); struct messages_send_extra *E = talloc0 (sizeof (*E)); E->id = tgl_peer_id_to_random_msg_id (peer_id); out_long (E->id.id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); } } void tgl_do_reply_location (struct tgl_state *TLS, tgl_message_id_t *_reply_id, double latitude, double longitude, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t reply_id = *_reply_id; if (reply_id.peer_type == TGL_PEER_TEMP_ID) { reply_id = tgl_convert_temp_msg_id (TLS, reply_id); } if (reply_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } if (reply_id.peer_type == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not reply on message from secret chat"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } tgl_peer_id_t peer_id = tgl_msg_id_to_peer_id (reply_id); tgl_do_send_location (TLS, peer_id, latitude, longitude, flags | TGL_SEND_MSG_FLAG_REPLY (reply_id.id), callback, callback_extra); } /* }}} */ /* {{{ Rename chat */ void tgl_do_rename_chat (struct tgl_state *TLS, tgl_peer_id_t id, const char *name, int name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_edit_chat_title); assert (tgl_get_peer_type (id) == TGL_PEER_CHAT); out_int (tgl_get_peer_id (id)); out_cstring (name, name_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Rename channel */ void tgl_do_rename_channel (struct tgl_state *TLS, tgl_peer_id_t id, const char *name, int name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_edit_title); assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); out_cstring (name, name_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Join channel */ void tgl_do_join_channel (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_join_channel); assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Leave channel */ void tgl_do_leave_channel (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_leave_channel); assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ channel change about */ static int channels_set_about_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static struct query_methods channels_set_about_methods = { .on_answer = channels_set_about_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(bool), .name = "channels set about" }; void tgl_do_channel_set_about (struct tgl_state *TLS, tgl_peer_id_t id, const char *about, int about_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_edit_about); assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); out_cstring (about, about_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &channels_set_about_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Channel set username */ void tgl_do_channel_set_username (struct tgl_state *TLS, tgl_peer_id_t id, const char *username, int username_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_update_username); assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); out_cstring (username, username_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &channels_set_about_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Channel set admin */ void tgl_do_channel_set_admin (struct tgl_state *TLS, tgl_peer_id_t channel_id, tgl_peer_id_t user_id, int type, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_edit_admin); assert (tgl_get_peer_type (channel_id) == TGL_PEER_CHANNEL); assert (tgl_get_peer_type (user_id) == TGL_PEER_USER); out_int (CODE_input_channel); out_int (tgl_get_peer_id (channel_id)); out_long (channel_id.access_hash); out_int (CODE_input_user); out_int (tgl_get_peer_id (user_id)); out_long (user_id.access_hash); switch (type) { case 1: out_int (CODE_channel_role_moderator); break; case 2: out_int (CODE_channel_role_editor); break; default: out_int (CODE_channel_role_empty); break; } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Channel members */ struct channel_get_members_extra { int size; int count; struct tgl_user **UL; int type; int offset; int limit; tgl_peer_id_t id; }; void _tgl_do_channel_get_members (struct tgl_state *TLS, struct channel_get_members_extra *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *UL[]), void *callback_extra); static int channels_get_members_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_channels_channel_participants *DS_CP = D; int count = DS_LVAL (DS_CP->participants->cnt); struct channel_get_members_extra *E = q->extra; if (E->count + count > E->size) { E->UL = trealloc (E->UL, E->size * sizeof (void *), (E->count + count) * sizeof (void *)); E->size = E->count + count; } int i; for (i = 0; i < DS_LVAL (DS_CP->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_CP->users->data[i]); } for (i = 0; i < count; i++) { E->UL[E->count ++] = (void *)tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_CP->participants->data[i]->user_id))); } E->offset += count; if (!count || E->count == E->limit) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_user **))q->callback)(TLS, q->callback_extra, 1, E->count, E->UL); tfree (E->UL, E->size * sizeof (void *)); tfree (E, sizeof (*E)); return 0; } _tgl_do_channel_get_members (TLS, E, q->callback, q->callback_extra); return 0; } static int channels_get_members_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *,void *, int, int, void *))(q->callback))(TLS, q->callback_extra, 0, 0, NULL); } struct channel_get_members_extra *E = q->extra; tfree (E->UL, E->size * sizeof (void *)); tfree (E, sizeof (*E)); return 0; } static struct query_methods channels_get_members_methods = { .on_answer = channels_get_members_on_answer, .on_error = channels_get_members_on_error, .type = TYPE_TO_PARAM(channels_channel_participants), .name = "channels get members" }; void _tgl_do_channel_get_members (struct tgl_state *TLS, struct channel_get_members_extra *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *UL[]), void *callback_extra) { clear_packet (); out_int (CODE_channels_get_participants); assert (tgl_get_peer_type (E->id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (E->id.peer_id); out_long (E->id.access_hash); switch (E->type) { case 1: case 2: out_int (CODE_channel_participants_admins); break; case 3: out_int (CODE_channel_participants_kicked); break; default: out_int (CODE_channel_participants_recent); break; } out_int (E->offset); out_int (E->limit); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &channels_get_members_methods, E, callback, callback_extra); } void tgl_do_channel_get_members (struct tgl_state *TLS, tgl_peer_id_t channel_id, int limit, int offset, int type, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *UL[]), void *callback_extra) { struct channel_get_members_extra *E = talloc0 (sizeof (*E)); E->type = type; E->id = channel_id; E->limit = limit; E->offset = offset; _tgl_do_channel_get_members (TLS, E, callback, callback_extra); } /* }}} */ /* {{{ Chat info */ static int chat_info_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_chat *C = tglf_fetch_alloc_chat_full (TLS, D); //print_chat_info (C); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_chat *))q->callback) (TLS, q->callback_extra, 1, C); } return 0; } static struct query_methods chat_info_methods = { .on_answer = chat_info_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(messages_chat_full), .name = "chat info" }; void tgl_do_get_chat_info (struct tgl_state *TLS, tgl_peer_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_chat *C), void *callback_extra) { if (offline_mode) { tgl_peer_t *C = tgl_peer_get (TLS, id); if (!C) { tgl_set_query_error (TLS, EINVAL, "unknown chat id"); if (callback) { callback (TLS, callback_extra, 0, 0); } } else { if (callback) { callback (TLS, callback_extra, 1, &C->chat); } } return; } clear_packet (); out_int (CODE_messages_get_full_chat); assert (tgl_get_peer_type (id) == TGL_PEER_CHAT); out_int (tgl_get_peer_id (id)); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Channel info */ static int channel_info_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_channel *C = tglf_fetch_alloc_channel_full (TLS, D); //print_chat_info (C); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_channel *))q->callback) (TLS, q->callback_extra, 1, C); } return 0; } static struct query_methods channel_info_methods = { .on_answer = channel_info_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(messages_chat_full), .name = "channel info" }; void tgl_do_get_channel_info (struct tgl_state *TLS, tgl_peer_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_channel *C), void *callback_extra) { if (offline_mode) { tgl_peer_t *C = tgl_peer_get (TLS, id); if (!C) { tgl_set_query_error (TLS, EINVAL, "unknown chat id"); if (callback) { callback (TLS, callback_extra, 0, 0); } } else { if (callback) { callback (TLS, callback_extra, 1, &C->channel); } } return; } clear_packet (); out_int (CODE_channels_get_full_channel); assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); out_int (CODE_input_channel); out_int (id.peer_id); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &channel_info_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ User info */ static int user_info_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_user *U = tglf_fetch_alloc_user_full (TLS, D); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U); } return 0; } static struct query_methods user_info_methods = { .on_answer = user_info_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(user_full), .name = "user info" }; void tgl_do_get_user_info (struct tgl_state *TLS, tgl_peer_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_USER) { tgl_set_query_error (TLS, EINVAL, "id should be user id"); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } if (offline_mode) { tgl_peer_t *C = tgl_peer_get (TLS, id); if (!C) { tgl_set_query_error (TLS, EINVAL, "unknown user id"); if (callback) { callback (TLS, callback_extra, 0, 0); } } else { if (callback) { callback (TLS, callback_extra, 1, &C->user); } } return; } clear_packet (); out_int (CODE_users_get_full_user); assert (tgl_get_peer_type (id) == TGL_PEER_USER); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, callback, callback_extra); } static void resend_query_cb (struct tgl_state *TLS, void *_q, int success) { assert (success); bl_do_dc_signed (TLS, TLS->DC_working->id); struct query *q = _q; clear_packet (); out_int (CODE_users_get_full_user); out_int (CODE_input_user_self); tglq_send_query (TLS, q->DC, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, q->callback, q->callback_extra); tfree (q->data, 4 * q->data_len); TLS->timer_methods->free (q->ev); tfree (q, sizeof (*q)); } /* }}} */ /* {{{ Load photo/video */ struct download { int offset; int size; long long volume; long long secret; long long access_hash; int local_id; int dc; int next; int fd; char *name; char *ext; long long id; unsigned char *iv; unsigned char *key; int type; int refcnt; }; static void end_load (struct tgl_state *TLS, struct download *D, void *callback, void *callback_extra) { TLS->cur_downloading_bytes -= D->size; TLS->cur_downloaded_bytes -= D->size; if (D->fd >= 0) { close (D->fd); } if (callback) { ((void (*)(struct tgl_state *, void *, int, char *))callback) (TLS, callback_extra, 1, D->name); } if (D->iv) { tfree_secure (D->iv, 32); } tfree_str (D->name); tfree (D, sizeof (*D)); } static void load_next_part (struct tgl_state *TLS, struct download *D, void *callback, void *callback_extra); static int download_on_answer (struct tgl_state *TLS, struct query *q, void *DD) { struct tl_ds_upload_file *DS_UF = DD; struct download *D = q->extra; if (D->fd == -1) { D->fd = open (D->name, O_CREAT | O_WRONLY | O_BINARY, 0640); if (D->fd < 0) { tgl_set_query_error (TLS, EBADF, "Can not open file for writing: %s", strerror(errno)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, char *))q->callback) (TLS, q->callback_extra, 0, NULL); } if (D->iv) { tfree_secure (D->iv, 32); } tfree_str (D->name); if (D->ext) { tfree_str (D->ext); } tfree (D, sizeof (*D)); return 0; } } int len = DS_UF->bytes->len; TLS->cur_downloaded_bytes += len; //update_prompt (); if (D->iv) { assert (!(len & 15)); void *ptr = DS_UF->bytes->data; TGLC_aes_key aes_key; TGLC_aes_set_decrypt_key (D->key, 256, &aes_key); TGLC_aes_ige_encrypt (ptr, ptr, len, &aes_key, D->iv, 0); memset (&aes_key, 0, sizeof (aes_key)); if (len > D->size - D->offset) { len = D->size - D->offset; } assert (write (D->fd, ptr, len) == len); } else { assert (write (D->fd, DS_UF->bytes->data, len) == len); } D->offset += len; D->refcnt --; if (D->offset < D->size) { load_next_part (TLS, D, q->callback, q->callback_extra); return 0; } else { if (!D->refcnt) { end_load (TLS, D, q->callback, q->callback_extra); } return 0; } } static int download_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct download *D = q->extra; if (D->fd >= 0) { close (D->fd); } if (q->callback) { ((void (*)(struct tgl_state *, void *, int, char *))q->callback) (TLS, q->callback_extra, 0, NULL); } if (D->iv) { tfree_secure (D->iv, 32); } tfree_str (D->name); if (D->ext) { tfree_str (D->ext); } tfree (D, sizeof (*D)); return 0; } static struct query_methods download_methods = { .on_answer = download_on_answer, .on_error = download_on_error, .type = TYPE_TO_PARAM(upload_file), .name = "download part" }; static void load_next_part (struct tgl_state *TLS, struct download *D, void *callback, void *callback_extra) { if (!D->offset) { static char buf[PATH_MAX]; int l; if (!D->id) { l = tsnprintf (buf, sizeof (buf), "%s/download_%" INT64_PRINTF_MODIFIER "d_%d.jpg", TLS->downloads_directory, D->volume, D->local_id); } else { if (D->ext) { l = tsnprintf (buf, sizeof (buf), "%s/download_%" INT64_PRINTF_MODIFIER "d.%s", TLS->downloads_directory, D->id, D->ext); } else { l = tsnprintf (buf, sizeof (buf), "%s/download_%" INT64_PRINTF_MODIFIER "d", TLS->downloads_directory, D->id); } } if (l >= (int) sizeof (buf)) { vlogprintf (E_ERROR, "Download filename is too long"); assert (0); } D->name = tstrdup (buf); struct stat st; if (stat (buf, &st) >= 0) { D->offset = st.st_size; if (D->offset >= D->size) { TLS->cur_downloading_bytes += D->size; TLS->cur_downloaded_bytes += D->offset; vlogprintf (E_NOTICE, "Already downloaded\n"); end_load (TLS, D, callback, callback_extra); return; } } TLS->cur_downloading_bytes += D->size; TLS->cur_downloaded_bytes += D->offset; //update_prompt (); } D->refcnt ++; clear_packet (); out_int (CODE_upload_get_file); if (!D->id) { out_int (CODE_input_file_location); out_long (D->volume); out_int (D->local_id); out_long (D->secret); } else { if (D->iv) { out_int (CODE_input_encrypted_file_location); } else { out_int (D->type); } out_long (D->id); out_long (D->access_hash); } out_int (D->offset); out_int (D->size ? (1 << 14) : (1 << 19)); tglq_send_query (TLS, TLS->DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D, callback, callback_extra); //tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D); } void tgl_do_load_photo_size (struct tgl_state *TLS, struct tgl_photo_size *P, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { if (!P->loc.dc) { vlogprintf (E_WARNING, "Bad video thumb\n"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } assert (P); struct download *D = talloc0 (sizeof (*D)); D->id = 0; D->offset = 0; D->size = P->size; D->volume = P->loc.volume; D->dc = P->loc.dc; D->local_id = P->loc.local_id; D->secret = P->loc.secret; D->name = 0; D->fd = -1; load_next_part (TLS, D, callback, callback_extra); } void tgl_do_load_file_location (struct tgl_state *TLS, struct tgl_file_location *P, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { if (!P->dc) { tgl_set_query_error (TLS, EINVAL, "Bad file location"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } assert (P); struct download *D = talloc0 (sizeof (*D)); D->id = 0; D->offset = 0; D->size = 0; D->volume = P->volume; D->dc = P->dc; D->local_id = P->local_id; D->secret = P->secret; D->name = 0; D->fd = -1; load_next_part (TLS, D, callback, callback_extra); } void tgl_do_load_photo (struct tgl_state *TLS, struct tgl_photo *photo, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { if (!photo->sizes_num) { tgl_set_query_error (TLS, EINVAL, "Bad photo (no photo sizes"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } int max = -1; int maxi = 0; int i; for (i = 0; i < photo->sizes_num; i++) { if (photo->sizes[i].w + photo->sizes[i].h > max) { max = photo->sizes[i].w + photo->sizes[i].h; maxi = i; } } tgl_do_load_photo_size (TLS, &photo->sizes[maxi], callback, callback_extra); } void tgl_do_load_document_thumb (struct tgl_state *TLS, struct tgl_document *video, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { tgl_do_load_photo_size (TLS, &video->thumb, callback, callback_extra); } static void _tgl_do_load_document (struct tgl_state *TLS, struct tgl_document *V, struct download *D, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { assert (V); D->offset = 0; D->size = V->size; D->id = V->id; D->access_hash = V->access_hash; D->dc = V->dc_id; D->name = 0; D->fd = -1; if (V->mime_type) { char *r = tg_extension_by_mime (V->mime_type); if (r) { D->ext = tstrdup (r); } } load_next_part (TLS, D, callback, callback_extra); } void tgl_do_load_document (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { struct download *D = talloc0 (sizeof (*D)); D->type = CODE_input_document_file_location; _tgl_do_load_document (TLS, V, D, callback, callback_extra); } void tgl_do_load_video (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { struct download *D = talloc0 (sizeof (*D)); D->type = CODE_input_video_file_location; _tgl_do_load_document (TLS, V, D, callback, callback_extra); } void tgl_do_load_audio (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { struct download *D = talloc0 (sizeof (*D)); D->type = CODE_input_audio_file_location; _tgl_do_load_document (TLS, V, D, callback, callback_extra); } void tgl_do_load_encr_document (struct tgl_state *TLS, struct tgl_encr_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *filename), void *callback_extra) { assert (V); struct download *D = talloc0 (sizeof (*D)); D->offset = 0; D->size = V->size; D->id = V->id; D->access_hash = V->access_hash; D->dc = V->dc_id; D->name = 0; D->fd = -1; D->key = V->key; D->iv = talloc (32); memcpy (D->iv, V->iv, 32); if (V->mime_type) { char *r = tg_extension_by_mime (V->mime_type); if (r) { D->ext = tstrdup (r); } } load_next_part (TLS, D, callback, callback_extra); unsigned char md5[16]; unsigned char str[64]; memcpy (str, V->key, 32); memcpy (str + 32, V->iv, 32); TGLC_md5 (str, 64, md5); assert (V->key_fingerprint == ((*(int *)md5) ^ (*(int *)(md5 + 4)))); } /* }}} */ /* {{{ Export auth */ static int import_auth_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_auth_authorization *DS_U = D; tglf_fetch_alloc_user (TLS, DS_U->user); bl_do_dc_signed (TLS, ((struct tgl_dc *)q->extra)->id); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } return 0; } static struct query_methods import_auth_methods = { .on_answer = import_auth_on_answer, .on_error = fail_on_error, .type = TYPE_TO_PARAM(auth_authorization), .name = "import authorization" }; static int export_auth_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_auth_exported_authorization *DS_EA = D; bl_do_set_our_id (TLS, TGL_MK_USER (DS_LVAL (DS_EA->id))); clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_auth_import_authorization); out_int (tgl_get_peer_id (TLS->our_id)); out_cstring (DS_STR (DS_EA->bytes)); tglq_send_query (TLS, q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, q->extra, q->callback, q->callback_extra); return 0; } static struct query_methods export_auth_methods = { .on_answer = export_auth_on_answer, .on_error = fail_on_error, .type = TYPE_TO_PARAM(auth_exported_authorization), .name = "export authorization" }; void tgl_do_export_auth (struct tgl_state *TLS, int num, void (*callback) (struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_auth_export_authorization); out_int (num); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, TLS->DC_list[num], callback, callback_extra); } /* }}} */ /* {{{ Add contact */ static int add_contact_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_contacts_imported_contacts *DS_CIC = D; if (DS_LVAL (DS_CIC->imported->cnt) > 0) { vlogprintf (E_DEBUG, "Added successfully"); } else { vlogprintf (E_DEBUG, "Not added"); } int n = DS_LVAL (DS_CIC->users->cnt); struct tgl_user **UL = talloc (n * sizeof (void *)); int i; for (i = 0; i < n; i++) { UL[i] = tglf_fetch_alloc_user (TLS, DS_CIC->users->data[i]); } if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_user **))q->callback) (TLS, q->callback_extra, 1, n, UL); } tfree (UL, n * sizeof (void *)); return 0; } static struct query_methods add_contact_methods = { .on_answer = add_contact_on_answer, .on_error = q_list_on_error, .type = TYPE_TO_PARAM(contacts_imported_contacts), .name = "add contact" }; void tgl_do_add_contact (struct tgl_state *TLS, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra) { clear_packet (); out_int (CODE_contacts_import_contacts); out_int (CODE_vector); out_int (1); out_int (CODE_input_phone_contact); long long r; tglt_secure_random (&r, 8); out_long (r); out_cstring (phone, phone_len); out_cstring (first_name, first_name_len); out_cstring (last_name, last_name_len); out_int (force ? CODE_bool_true : CODE_bool_false); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Del contact */ static int del_contact_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } return 0; } static struct query_methods del_contact_methods = { .on_answer = del_contact_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(contacts_link), .name = "del contact" }; void tgl_do_del_contact (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_USER) { tgl_set_query_error (TLS, EINVAL, "id should be user id"); if (callback) { callback (TLS, callback_extra, 0); } return; } clear_packet (); out_int (CODE_contacts_delete_contact); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &del_contact_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Msg search */ struct msg_search_extra { struct tgl_message **ML; int list_offset; int list_size; tgl_peer_id_t id; int limit; int offset; int from; int to; int max_id; char *query; }; static void _tgl_do_msg_search (struct tgl_state *TLS, struct msg_search_extra *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra); static int msg_search_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_messages *DS_MM = D; int i; for (i = 0; i < DS_LVAL (DS_MM->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_MM->chats->data[i]); } for (i = 0; i < DS_LVAL (DS_MM->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_MM->users->data[i]); } struct msg_search_extra *E = q->extra; int n = DS_LVAL (DS_MM->messages->cnt); if (E->list_size - E->list_offset < n) { int new_list_size = 2 * E->list_size; if (new_list_size - E->list_offset < n) { new_list_size = n + E->list_offset; } E->ML = trealloc (E->ML, E->list_size * sizeof (void *), new_list_size * sizeof (void *)); assert (E->ML); E->list_size = new_list_size; } for (i = 0; i < n; i++) { E->ML[i + E->list_offset] = tglf_fetch_alloc_message (TLS, DS_MM->messages->data[i], NULL); } E->list_offset += n; E->offset += n; E->limit -= n; if (E->limit + E->offset >= DS_LVAL (DS_MM->count)) { E->limit = DS_LVAL (DS_MM->count) - E->offset; if (E->limit < 0) { E->limit = 0; } } assert (E->limit >= 0); if (E->limit <= 0 || DS_MM->magic == CODE_messages_messages) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 1, E->list_offset, E->ML); } tfree_str (E->query); tfree (E->ML, sizeof (void *) * E->list_size); tfree (E, sizeof (*E)); } else { E->max_id = E->ML[E->list_offset - 1]->permanent_id.id; E->offset = 0; _tgl_do_msg_search (TLS, E, q->callback, q->callback_extra); } return 0; } static int msg_search_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); struct msg_search_extra *E = q->extra; tfree_str (E->query); tfree (E->ML, sizeof (void *) * E->list_size); tfree (E, sizeof (*E)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 0, 0, NULL); } return 0; } static struct query_methods msg_search_methods = { .on_answer = msg_search_on_answer, .on_error = msg_search_on_error, .type = TYPE_TO_PARAM(messages_messages), .name = "messages search" }; static void _tgl_do_msg_search (struct tgl_state *TLS, struct msg_search_extra *E, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { clear_packet (); if (tgl_get_peer_type (E->id) == TGL_PEER_UNKNOWN) { out_int (CODE_messages_search_global); out_string (E->query); out_int (0); out_int (CODE_input_peer_empty); out_int (E->offset); out_int (E->limit); } else { out_int (CODE_messages_search); out_int (0); out_peer_id (TLS, E->id); out_string (E->query); out_int (CODE_input_messages_filter_empty); out_int (E->from); out_int (E->to); out_int (E->offset); // offset out_int (E->max_id); // max_id out_int (E->limit); } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, E, callback, callback_extra); } void tgl_do_msg_search (struct tgl_state *TLS, tgl_peer_id_t id, int from, int to, int limit, int offset, const char *pattern, int pattern_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { tgl_set_query_error (TLS, EINVAL, "can not search in secret chats"); if (callback) { callback (TLS, callback_extra, 0, 0, 0); } return; } struct msg_search_extra *E = talloc0 (sizeof (*E)); E->id = id; E->from = from; E->to = to; E->limit = limit; E->offset = offset; E->query = tstrndup (pattern, pattern_len); _tgl_do_msg_search (TLS, E, callback, callback_extra); } /* }}} */ /* {{{ Get difference */ static int get_state_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_updates_state *DS_US = D; assert (TLS->locks & TGL_LOCK_DIFF); TLS->locks ^= TGL_LOCK_DIFF; bl_do_set_pts (TLS, DS_LVAL (DS_US->pts)); bl_do_set_qts (TLS, DS_LVAL (DS_US->qts)); bl_do_set_date (TLS, DS_LVAL (DS_US->date)); bl_do_set_seq (TLS, DS_LVAL (DS_US->seq)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } return 0; } static int lookup_state_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_updates_state *DS_US = D; int pts = DS_LVAL (DS_US->pts); int qts = DS_LVAL (DS_US->qts); int seq = DS_LVAL (DS_US->seq); if (pts > TLS->pts || qts > TLS->qts || seq > TLS->seq) { tgl_do_get_difference (TLS, 0, 0, 0); } return 0; } //int get_difference_active; static int get_difference_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_updates_difference *DS_UD = D; assert (TLS->locks & TGL_LOCK_DIFF); TLS->locks ^= TGL_LOCK_DIFF; if (DS_UD->magic == CODE_updates_difference_empty) { bl_do_set_date (TLS, DS_LVAL (DS_UD->date)); bl_do_set_seq (TLS, DS_LVAL (DS_UD->seq)); vlogprintf (E_DEBUG, "Empty difference. Seq = %d\n", TLS->seq); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } } else { int i; for (i = 0; i < DS_LVAL (DS_UD->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_UD->users->data[i]); } for (i = 0; i < DS_LVAL (DS_UD->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_UD->chats->data[i]); } int ml_pos = DS_LVAL (DS_UD->new_messages->cnt); struct tgl_message **ML = talloc (ml_pos * sizeof (void *)); for (i = 0; i < ml_pos; i++) { ML[i] = tglf_fetch_alloc_message (TLS, DS_UD->new_messages->data[i], NULL); } int el_pos = DS_LVAL (DS_UD->new_encrypted_messages->cnt); struct tgl_message **EL = talloc (el_pos * sizeof (void *)); for (i = 0; i < el_pos; i++) { EL[i] = tglf_fetch_alloc_encrypted_message (TLS, DS_UD->new_encrypted_messages->data[i]); } for (i = 0; i < DS_LVAL (DS_UD->other_updates->cnt); i++) { tglu_work_update (TLS, 1, DS_UD->other_updates->data[i]); } for (i = 0; i < DS_LVAL (DS_UD->other_updates->cnt); i++) { tglu_work_update (TLS, -1, DS_UD->other_updates->data[i]); } for (i = 0; i < ml_pos; i++) { bl_do_msg_update (TLS, &ML[i]->permanent_id); } for (i = 0; i < el_pos; i++) { // messages to secret chats that no longer exist are not initialized and NULL if (EL[i]) { bl_do_msg_update (TLS, &EL[i]->permanent_id); } } tfree (ML, ml_pos * sizeof (void *)); tfree (EL, el_pos * sizeof (void *)); if (DS_UD->state) { bl_do_set_pts (TLS, DS_LVAL (DS_UD->state->pts)); bl_do_set_qts (TLS, DS_LVAL (DS_UD->state->qts)); bl_do_set_date (TLS, DS_LVAL (DS_UD->state->date)); bl_do_set_seq (TLS, DS_LVAL (DS_UD->state->seq)); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } } else { bl_do_set_pts (TLS, DS_LVAL (DS_UD->intermediate_state->pts)); bl_do_set_qts (TLS, DS_LVAL (DS_UD->intermediate_state->qts)); bl_do_set_date (TLS, DS_LVAL (DS_UD->intermediate_state->date)); tgl_do_get_difference (TLS, 0, q->callback, q->callback_extra); } } return 0; } static struct query_methods lookup_state_methods = { .on_answer = lookup_state_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(updates_state), .name = "lookup state" }; static struct query_methods get_state_methods = { .on_answer = get_state_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(updates_state), .name = "get state" }; static struct query_methods get_difference_methods = { .on_answer = get_difference_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(updates_difference), .name = "get difference" }; void tgl_do_lookup_state (struct tgl_state *TLS) { if (TLS->locks & TGL_LOCK_DIFF) { return; } clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_updates_get_state); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &lookup_state_methods, 0, 0, 0); } void tgl_do_get_difference (struct tgl_state *TLS, int sync_from_start, void (*callback)(struct tgl_state *tls, void *callback_extra, int success), void *callback_extra) { //get_difference_active = 1; //difference_got = 0; if (TLS->locks & TGL_LOCK_DIFF) { if (callback) { callback (TLS, callback_extra, 0); } return; } TLS->locks |= TGL_LOCK_DIFF; clear_packet (); tgl_do_insert_header (TLS); if (TLS->pts > 0 || sync_from_start) { if (TLS->pts == 0) { TLS->pts = 1; } //if (TLS->qts == 0) { TLS->qts = 1; } if (TLS->date == 0) { TLS->date = 1; } out_int (CODE_updates_get_difference); out_int (TLS->pts); out_int (TLS->date); out_int (TLS->qts); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0, callback, callback_extra); } else { out_int (CODE_updates_get_state); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0, callback, callback_extra); } } /* }}} */ /* {{{ Get channel difference */ void tgl_do_get_channel_difference (struct tgl_state *TLS, int id, void (*callback)(struct tgl_state *tls, void *callback_extra, int success), void *callback_extra); static int get_channel_difference_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_updates_channel_difference *DS_UD = D; tgl_peer_t *E = q->extra; assert (E->flags & TGLCHF_DIFF); E->flags ^= TGLCHF_DIFF; if (DS_UD->magic == CODE_updates_channel_difference_empty) { bl_do_set_channel_pts (TLS, tgl_get_peer_id (E->id), DS_LVAL (DS_UD->channel_pts)); vlogprintf (E_DEBUG, "Empty difference. Seq = %d\n", TLS->seq); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } } else { int i; for (i = 0; i < DS_LVAL (DS_UD->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_UD->users->data[i]); } for (i = 0; i < DS_LVAL (DS_UD->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_UD->chats->data[i]); } int ml_pos = DS_LVAL (DS_UD->new_messages->cnt); struct tgl_message **ML = talloc (ml_pos * sizeof (void *)); for (i = 0; i < ml_pos; i++) { ML[i] = tglf_fetch_alloc_message (TLS, DS_UD->new_messages->data[i], NULL); } for (i = 0; i < DS_LVAL (DS_UD->other_updates->cnt); i++) { tglu_work_update (TLS, 1, DS_UD->other_updates->data[i]); } for (i = 0; i < DS_LVAL (DS_UD->other_updates->cnt); i++) { tglu_work_update (TLS, -1, DS_UD->other_updates->data[i]); } for (i = 0; i < ml_pos; i++) { bl_do_msg_update (TLS, &ML[i]->permanent_id); } tfree (ML, ml_pos * sizeof (void *)); bl_do_set_channel_pts (TLS, tgl_get_peer_id (E->id), DS_LVAL (DS_UD->channel_pts)); if (DS_UD->magic != CODE_updates_channel_difference_too_long) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } } else { tgl_do_get_channel_difference (TLS, tgl_get_peer_id (E->id), q->callback, q->callback_extra); } } return 0; } static struct query_methods get_channel_difference_methods = { .on_answer = get_channel_difference_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(updates_channel_difference), .name = "get channel difference" }; void tgl_do_get_channel_difference (struct tgl_state *TLS, int id, void (*callback)(struct tgl_state *tls, void *callback_extra, int success), void *callback_extra) { tgl_peer_t *E = tgl_peer_get (TLS, TGL_MK_CHANNEL (id)); if (!E || !(E->flags & TGLPF_CREATED) || !E->channel.pts) { if (callback) { callback (TLS, callback_extra, 0); } return; } //get_difference_active = 1; //difference_got = 0; if (E->flags & TGLCHF_DIFF) { if (callback) { callback (TLS, callback_extra, 0); } return; } E->flags |= TGLCHF_DIFF; clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_updates_get_channel_difference); out_int (CODE_input_channel); out_int (tgl_get_peer_id (E->id)); out_long (E->channel.access_hash); out_int (CODE_channel_messages_filter_empty); out_int (E->channel.pts); out_int (100); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_channel_difference_methods, E, callback, callback_extra); } /* }}} */ /* {{{ Visualize key */ int tgl_do_visualize_key (struct tgl_state *TLS, tgl_peer_id_t id, unsigned char buf[16]) { assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT); tgl_peer_t *P = tgl_peer_get (TLS, id); assert (P); if (P->encr_chat.state != sc_ok) { vlogprintf (E_WARNING, "Chat is not initialized yet\n"); return -1; } memcpy (buf, P->encr_chat.first_key_sha, 16); return 0; } /* }}} */ /* {{{ Add user to chat */ void tgl_do_add_user_to_chat (struct tgl_state *TLS, tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_add_chat_user); out_int (tgl_get_peer_id (chat_id)); assert (tgl_get_peer_type (id) == TGL_PEER_USER); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); out_int (limit); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } void tgl_do_del_user_from_chat (struct tgl_state *TLS, tgl_peer_id_t chat_id, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_delete_chat_user); out_int (tgl_get_peer_id (chat_id)); assert (tgl_get_peer_type (id) == TGL_PEER_USER); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Add user to channel */ void tgl_do_channel_invite_user (struct tgl_state *TLS, tgl_peer_id_t channel_id, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_invite_to_channel); out_int (CODE_input_channel); out_int (channel_id.peer_id); out_long (channel_id.access_hash); out_int (CODE_vector); out_int (1); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } void tgl_do_channel_kick_user (struct tgl_state *TLS, tgl_peer_id_t channel_id, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_kick_from_channel); out_int (CODE_input_channel); out_int (channel_id.peer_id); out_long (channel_id.access_hash); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); out_int (CODE_bool_true); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Create secret chat */ void tgl_do_create_secret_chat (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { assert (tgl_get_peer_type (id) == TGL_PEER_USER); tgl_peer_t *U = tgl_peer_get (TLS, id); if (!U) { tgl_set_query_error (TLS, EINVAL, "Can not create secret chat with unknown user"); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } tgl_do_create_encr_chat_request (TLS, tgl_get_peer_id (id), callback, callback_extra); } /* }}} */ /* {{{ Create group chat */ void tgl_do_create_group_chat (struct tgl_state *TLS, int users_num, tgl_peer_id_t ids[], const char *chat_topic, int chat_topic_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_create_chat); out_int (CODE_vector); out_int (users_num); // Number of users, currently we support only 1 user. int i; for (i = 0; i < users_num; i++) { tgl_peer_id_t id = ids[i]; if (tgl_get_peer_type (id) != TGL_PEER_USER) { tgl_set_query_error (TLS, EINVAL, "Can not create chat with unknown user"); if (callback) { callback (TLS, callback_extra, 0); } return; } out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); } out_cstring (chat_topic, chat_topic_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Create channel */ void tgl_do_create_channel (struct tgl_state *TLS, int users_num, tgl_peer_id_t ids[], const char *chat_topic, int chat_topic_len, const char *about, int about_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_channels_create_channel); out_int (flags); // looks like 2 is disable non-admin messages out_cstring (chat_topic, chat_topic_len); out_cstring (about, about_len); //out_int (CODE_vector); //out_int (users_num); int i; for (i = 0; i < users_num; i++) { tgl_peer_id_t id = ids[i]; if (tgl_get_peer_type (id) != TGL_PEER_USER) { tgl_set_query_error (TLS, EINVAL, "Can not create chat with unknown user"); if (callback) { callback (TLS, callback_extra, 0); } return; } out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Delete msg */ static int delete_msg_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_affected_messages *DS_MAM = D; tgl_message_id_t *id = q->extra; q->extra = NULL; struct tgl_message *M = tgl_message_get (TLS, id); if (M) { bl_do_message_delete (TLS, &M->permanent_id); } tfree (id, sizeof (*id)); int r = tgl_check_pts_diff (TLS, DS_LVAL (DS_MAM->pts), DS_LVAL (DS_MAM->pts_count)); if (r > 0) { bl_do_set_pts (TLS, DS_LVAL (DS_MAM->pts)); } if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } return 0; } static int delete_msg_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *,void *, int))(q->callback))(TLS, q->callback_extra, 0); } tfree (q->extra, sizeof (tgl_message_id_t)); return 0; } static struct query_methods delete_msg_methods = { .on_answer = delete_msg_on_answer, .on_error = delete_msg_on_error, .type = TYPE_TO_PARAM(messages_affected_messages), .name = "delete message" }; void tgl_do_delete_msg (struct tgl_state *TLS, tgl_message_id_t *_msg_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { tgl_message_id_t msg_id = *_msg_id; if (msg_id.peer_type == TGL_PEER_TEMP_ID) { msg_id = tgl_convert_temp_msg_id (TLS, msg_id); } if (msg_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0); } return; } clear_packet (); if (msg_id.peer_type == TGL_PEER_CHANNEL) { out_int (CODE_channels_delete_messages); out_int (CODE_input_channel); out_int (msg_id.peer_id); out_long (msg_id.access_hash); out_int (CODE_vector); out_int (1); out_int (msg_id.id); } else { out_int (CODE_messages_delete_messages); out_int (CODE_vector); out_int (1); out_int (msg_id.id); } tgl_message_id_t *id = talloc (sizeof (*id)); *id = msg_id; tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, id, callback, callback_extra); } /* }}} */ /* {{{ Export card */ static int export_card_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_vector *DS_V = D; int n = DS_LVAL (DS_V->f1); int *r = talloc (4 * n); int i; for (i = 0; i < n; i++) { r[i] = *(int *)DS_V->f2[i]; } if (q->callback) { ((void (*)(struct tgl_state *, void *, int, int, int *))q->callback) (TLS, q->callback_extra, 1, n, r); } tfree (r, 4 * n); return 0; } static struct query_methods export_card_methods = { .on_answer = export_card_on_answer, .on_error = q_list_on_error, .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM (bare_int)), .name = "export card" }; void tgl_do_export_card (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, int *card), void *callback_extra) { clear_packet (); out_int (CODE_contacts_export_card); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &export_card_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Import card */ static int import_card_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_user *U = tglf_fetch_alloc_user (TLS, D); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U); } return 0; } static struct query_methods import_card_methods = { .on_answer = import_card_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM (user), .name = "import card" }; void tgl_do_import_card (struct tgl_state *TLS, int size, int *card, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) { clear_packet (); out_int (CODE_contacts_import_card); out_int (CODE_vector); out_int (size); out_ints (card, size); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &import_card_methods, 0, callback, callback_extra); } /* }}} */ void tgl_do_start_bot (struct tgl_state *TLS, tgl_peer_id_t bot, tgl_peer_id_t chat, const char *str, int str_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_start_bot); out_int (CODE_input_user); out_int (tgl_get_peer_id (bot)); out_long (bot.access_hash); out_int (tgl_get_peer_id (chat)); long long m; tglt_secure_random (&m, 8); out_long (m); out_cstring (str, str_len); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* {{{ Send typing */ static int send_typing_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static struct query_methods send_typing_methods = { .on_answer = send_typing_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(bool), .name = "send typing" }; void tgl_do_send_typing (struct tgl_state *TLS, tgl_peer_id_t id, enum tgl_typing_status status, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_ENCR_CHAT) { clear_packet (); out_int (CODE_messages_set_typing); out_peer_id (TLS, id); switch (status) { case tgl_typing_none: case tgl_typing_typing: out_int (CODE_send_message_typing_action); break; case tgl_typing_cancel: out_int (CODE_send_message_cancel_action); break; case tgl_typing_record_video: out_int (CODE_send_message_record_video_action); break; case tgl_typing_upload_video: out_int (CODE_send_message_upload_video_action); break; case tgl_typing_record_audio: out_int (CODE_send_message_record_audio_action); break; case tgl_typing_upload_audio: out_int (CODE_send_message_upload_audio_action); break; case tgl_typing_upload_photo: out_int (CODE_send_message_upload_photo_action); break; case tgl_typing_upload_document: out_int (CODE_send_message_upload_document_action); break; case tgl_typing_geo: out_int (CODE_send_message_geo_location_action); break; case tgl_typing_choose_contact: out_int (CODE_send_message_choose_contact_action); break; } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_typing_methods, 0, callback, callback_extra); } else { if (callback) { callback (TLS, callback_extra, 0); } } } /* }}} */ /* {{{ Extd query */ #ifndef DISABLE_EXTF char *tglf_extf_print_ds (struct tgl_state *TLS, void *DS, struct paramed_type *T); static int ext_query_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { char *buf = tglf_extf_print_ds (TLS, D, q->type); ((void (*)(struct tgl_state *, void *, int, char *))q->callback) (TLS, q->callback_extra, 1, buf); } tgl_paramed_type_free (q->type); return 0; } static struct query_methods ext_query_methods = { .on_answer = ext_query_on_answer, .on_error = q_list_on_error, .name = "ext query" }; void tgl_do_send_extf (struct tgl_state *TLS, const char *data, int data_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *buf), void *callback_extra) { clear_packet (); ext_query_methods.type = tglf_extf_store (TLS, data, data_len); if (ext_query_methods.type) { tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &ext_query_methods, 0, callback, callback_extra); } } #else void tgl_do_send_extf (struct tgl_state *TLS, const char *data, int data_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *buf), void *callback_extra) { assert (0); } #endif /* }}} */ /* {{{ get messages */ static int get_messages_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_messages_messages *DS_MM = D; int i; for (i = 0; i < DS_LVAL (DS_MM->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_MM->users->data[i]); } for (i = 0; i < DS_LVAL (DS_MM->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_MM->chats->data[i]); } struct tgl_message **ML; if (q->extra) { ML = talloc0 (sizeof (void *) * DS_LVAL (DS_MM->messages->cnt)); } else { static struct tgl_message *M; M = NULL; ML = &M; assert (DS_LVAL (DS_MM->messages->cnt) <= 1); } for (i = 0; i < DS_LVAL (DS_MM->messages->cnt); i++) { ML[i] = tglf_fetch_alloc_message (TLS, DS_MM->messages->data[i], NULL); } if (q->callback) { if (q->extra) { ((void (*)(struct tgl_state *, void *, int, int, struct tgl_message **))q->callback)(TLS, q->callback_extra, 1, DS_LVAL (DS_MM->messages->cnt), ML); } else { if (DS_LVAL (DS_MM->messages->cnt) > 0) { ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback)(TLS, q->callback_extra, 1, *ML); } else { tgl_set_query_error (TLS, ENOENT, "no such message"); ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback)(TLS, q->callback_extra, 0, NULL); } } } if (q->extra) { tfree (ML, sizeof (void *) * DS_LVAL (DS_MM->messages->cnt)); } return 0; } static struct query_methods get_messages_methods = { .on_answer = get_messages_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM (messages_messages), .name = "get messages" }; void tgl_do_get_message (struct tgl_state *TLS, tgl_message_id_t *_msg_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_message_id_t msg_id = *_msg_id; if (msg_id.peer_type == TGL_PEER_TEMP_ID) { msg_id = tgl_convert_temp_msg_id (TLS, msg_id); } if (msg_id.peer_type == TGL_PEER_TEMP_ID) { tgl_set_query_error (TLS, EINVAL, "unknown message"); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (M) { if (callback) { callback (TLS, callback_extra, 1, M); } return; } clear_packet (); vlogprintf (E_ERROR, "id=%" INT64_PRINTF_MODIFIER "d\n", msg_id.id); out_int (CODE_messages_get_messages); out_int (CODE_vector); out_int (1); out_int (msg_id.id); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_messages_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Export/import chat link */ static int export_chat_link_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_exported_chat_invite *DS_ECI = D; char *s = DS_STR_DUP (DS_ECI->link); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, const char *))q->callback)(TLS, q->callback_extra, s ? 1 : 0, s); } tfree_str (s); return 0; } static struct query_methods export_chat_link_methods = { .on_answer = export_chat_link_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM(exported_chat_invite), .name = "export chat link" }; void tgl_do_export_chat_link (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *link), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_CHAT) { tgl_set_query_error (TLS, EINVAL, "Can only export chat link for chat"); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } clear_packet (); out_int (CODE_messages_export_chat_invite); out_int (tgl_get_peer_id (id)); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &export_chat_link_methods, 0, callback, callback_extra); } void tgl_do_import_chat_link (struct tgl_state *TLS, const char *link, int len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { const char *l = link + len - 1; while (l >= link && *l != '/') { l --; } l ++; clear_packet (); out_int (CODE_messages_import_chat_invite); out_cstring (l, len - (l - link)); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Export/import channel link */ void tgl_do_export_channel_link (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *link), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_CHANNEL) { tgl_set_query_error (TLS, EINVAL, "Can only export chat link for chat"); if (callback) { callback (TLS, callback_extra, 0, NULL); } return; } clear_packet (); out_int (CODE_channels_export_invite); out_int (CODE_input_channel); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &export_chat_link_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ set password */ static int set_password_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static int set_password_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { if (error_code == 400) { if (!strcmp (error, "PASSWORD_HASH_INVALID")) { vlogprintf (E_WARNING, "Bad old password\n"); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 0); } return 0; } if (!strcmp (error, "NEW_PASSWORD_BAD")) { vlogprintf (E_WARNING, "Bad new password (unchanged or equals hint)\n"); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 0); } return 0; } if (!strcmp (error, "NEW_SALT_INVALID")) { vlogprintf (E_WARNING, "Bad new salt\n"); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 0); } return 0; } } tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 0); } return 0; } static struct query_methods set_password_methods = { .on_answer = set_password_on_answer, .on_error = set_password_on_error, .type = TYPE_TO_PARAM(bool), .name = "set password" }; static void tgl_do_act_set_password (struct tgl_state *TLS, const char *current_password, int current_password_len, const char *new_password, int new_password_len, const char *current_salt, int current_salt_len, const char *new_salt, int new_salt_len, const char *hint, int hint_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); static char s[512]; static unsigned char shab[32]; assert (current_salt_len <= 128); assert (current_password_len <= 128); assert (new_salt_len <= 128); assert (new_password_len <= 128); out_int (CODE_account_update_password_settings); if (current_password_len && current_salt_len) { memcpy (s, current_salt, current_salt_len); memcpy (s + current_salt_len, current_password, current_password_len); memcpy (s + current_salt_len + current_password_len, current_salt, current_salt_len); TGLC_sha256 ((void *)s, 2 * current_salt_len + current_password_len, shab); out_cstring ((void *)shab, 32); } else { out_string (""); } out_int (CODE_account_password_input_settings); if (new_password_len) { out_int (1); static char d[256]; memcpy (d, new_salt, new_salt_len); int l = new_salt_len; tglt_secure_random (d + l, 16); l += 16; memcpy (s, d, l); memcpy (s + l, new_password, new_password_len); memcpy (s + l + new_password_len, d, l); TGLC_sha256 ((void *)s, 2 * l + new_password_len, shab); out_cstring (d, l); out_cstring ((void *)shab, 32); out_cstring (hint, hint_len); } else { out_int (0); } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_password_methods, 0, callback, callback_extra); } struct change_password_extra { char *current_password; char *new_password; char *current_salt; char *new_salt; char *hint; int current_password_len; int new_password_len; int current_salt_len; int new_salt_len; int hint_len; void (*callback)(struct tgl_state *, void *, int); void *callback_extra; }; void tgl_on_new_pwd (struct tgl_state *TLS, const char *pwd[], void *_T); void tgl_on_new2_pwd (struct tgl_state *TLS, const char *pwd, void *_T) { struct change_password_extra *E = _T; if (strlen (pwd) != (size_t)E->new_password_len || memcmp (E->new_password, pwd, E->new_password_len)) { tfree (E->new_password, E->new_password_len); E->new_password = NULL; E->new_password_len = 0; vlogprintf (E_ERROR, "passwords do not match\n"); TLS->callback.get_values (TLS, tgl_new_password, "new password: ", 2, tgl_on_new_pwd, E); return; } tgl_do_act_set_password (TLS, E->current_password, E->current_password_len, E->new_password, E->new_password_len, E->current_salt, E->current_salt_len, E->new_salt, E->new_salt_len, E->hint, E->hint_len, E->callback, E->callback_extra); tfree (E->current_password, E->current_password_len); tfree (E->new_password, E->new_password_len); tfree (E->current_salt, E->current_salt_len); tfree (E->new_salt, E->new_salt_len); tfree_str (E->hint); tfree (E, sizeof (*E)); } void tgl_on_new_pwd (struct tgl_state *TLS, const char *pwd[], void *_T) { struct change_password_extra *E = _T; E->new_password_len = strlen (pwd[0]); E->new_password = tmemdup (pwd[0], E->new_password_len); tgl_on_new2_pwd(TLS, pwd[1], E); } void tgl_on_old_pwd (struct tgl_state *TLS, const char *pwd[], void *_T) { struct change_password_extra *E = _T; E->current_password_len = strlen (pwd[0]); E->current_password = tmemdup (pwd[0], E->current_password_len); tgl_on_new_pwd(TLS, pwd + 1, E); } static int set_get_password_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_account_password *DS_AP = D; char *new_hint = q->extra; struct change_password_extra *E = talloc0 (sizeof (*E)); if (DS_AP->current_salt) { E->current_salt_len = DS_AP->current_salt->len; E->current_salt = tmemdup (DS_AP->current_salt->data, E->current_salt_len); } if (DS_AP->new_salt) { E->new_salt_len = DS_AP->new_salt->len; E->new_salt = tmemdup (DS_AP->new_salt->data, E->new_salt_len); } if (new_hint) { E->hint_len = strlen (new_hint); E->hint = new_hint; } E->callback = q->callback; E->callback_extra = q->callback_extra; if (DS_AP->magic == CODE_account_no_password) { TLS->callback.get_values (TLS, tgl_new_password, "new password: ", 2, tgl_on_new_pwd, E); } else { static char s[512]; snprintf (s, 511, "old password (hint %.*s): ", DS_RSTR (DS_AP->hint)); TLS->callback.get_values (TLS, tgl_cur_and_new_password, s, 3, tgl_on_old_pwd, E); } return 0; } static struct query_methods set_get_password_methods = { .on_answer = set_get_password_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(account_password), .name = "get password" }; void tgl_do_set_password (struct tgl_state *TLS, const char *hint, int hint_len, void (*callback)(struct tgl_state *TLS, void *extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_account_get_password); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_get_password_methods, hint ? tstrndup (hint, hint_len) : NULL, callback, callback_extra); } /* }}} */ /* {{{ check password */ static int check_password_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { if (error_code == 400) { vlogprintf (E_ERROR, "bad password\n"); tgl_do_check_password (TLS, q->callback, q->callback_extra); return 0; } TLS->locks ^= TGL_LOCK_PASSWORD; tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 0); } return 0; } static int check_password_on_answer (struct tgl_state *TLS, struct query *q, void *D) { TLS->locks ^= TGL_LOCK_PASSWORD; if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static struct query_methods check_password_methods = { .on_answer = check_password_on_answer, .on_error = check_password_on_error, .type = TYPE_TO_PARAM(auth_authorization), .name = "check password" }; struct check_password_extra { char *current_salt; int current_salt_len; void (*callback)(struct tgl_state *, void *, int); void *callback_extra; }; static void tgl_pwd_got (struct tgl_state *TLS, const char *pwd[], void *_T) { struct check_password_extra *E = _T; clear_packet (); static char s[512]; static unsigned char shab[32]; assert (E->current_salt_len <= 128); assert (strlen (pwd[0]) <= 128); out_int (CODE_auth_check_password); if (pwd[0] && E->current_salt_len) { int l = E->current_salt_len; memcpy (s, E->current_salt, l); int r = strlen (pwd[0]); strcpy (s + l, pwd[0]); memcpy (s + l + r, E->current_salt, l); TGLC_sha256 ((void *)s, 2 * l + r, shab); out_cstring ((void *)shab, 32); } else { out_string (""); } tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &check_password_methods, 0, E->callback, E->callback_extra); tfree (E->current_salt, E->current_salt_len); tfree (E, sizeof (*E)); } static int check_get_password_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, const char *error) { TLS->locks ^= TGL_LOCK_PASSWORD; tgl_set_query_error (TLS, EPROTO, "RPC_CALL_FAIL %d: %.*s", error_code, error_len, error); if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 0); } return 0; } static int check_get_password_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_account_password *DS_AP = D; if (DS_AP->magic == CODE_account_no_password) { TLS->locks ^= TGL_LOCK_PASSWORD; return 0; } static char s[512]; snprintf (s, 511, "type password (hint %.*s): ", DS_RSTR (DS_AP->hint)); struct check_password_extra *E = talloc0 (sizeof (*E)); if (DS_AP->current_salt) { E->current_salt_len = DS_AP->current_salt->len; E->current_salt = tmemdup (DS_AP->current_salt->data, E->current_salt_len); } E->callback = q->callback; E->callback_extra = q->callback_extra; TLS->callback.get_values (TLS, tgl_cur_password, s, 1, tgl_pwd_got, E); return 0; } static struct query_methods check_get_password_methods = { .on_answer = check_get_password_on_answer, .on_error = check_get_password_on_error, .type = TYPE_TO_PARAM(account_password), .name = "get password" }; void tgl_do_check_password (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_account_get_password); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &check_get_password_methods, NULL, callback, callback_extra); } /* }}} */ /* {{{ send broadcast */ void tgl_do_send_broadcast (struct tgl_state *TLS, int num, tgl_peer_id_t peer_id[], const char *text, int text_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *extra, int success, int num, struct tgl_message *ML[]), void *callback_extra) { assert (num <= 1000); struct messages_send_extra *E = talloc0 (sizeof (*E)); E->multi = 1; E->count = num; E->list = talloc (sizeof (tgl_message_id_t) * num); int date = time (0); struct tl_ds_message_media TDSM; TDSM.magic = CODE_message_media_empty; int i; for (i = 0; i < num; i++) { assert (tgl_get_peer_type (peer_id[i]) == TGL_PEER_USER); int disable_preview = flags & TGL_SEND_MSG_FLAG_DISABLE_PREVIEW; if (!(flags & TGL_SEND_MSG_FLAG_ENABLE_PREVIEW) && TLS->disable_link_preview) { disable_preview = 1; } if (disable_preview) { disable_preview = TGLMF_DISABLE_PREVIEW; } struct tgl_message_id id = tgl_peer_id_to_random_msg_id (peer_id[i]); E->list[i] = id; tgl_peer_id_t from_id = TLS->our_id; bl_do_edit_message (TLS, &id, &from_id, &peer_id[i], NULL, NULL, &date, text, text_len, &TDSM, NULL, NULL, NULL, NULL, TGLMF_UNREAD | TGLMF_OUT | TGLMF_PENDING | TGLMF_CREATE | TGLMF_CREATED | disable_preview); } clear_packet (); out_int (CODE_messages_send_broadcast); out_int (CODE_vector); out_int (num); for (i = 0; i < num; i++) { assert (tgl_get_peer_type (peer_id[i]) == TGL_PEER_USER); out_int (CODE_input_user); out_int (tgl_get_peer_id (peer_id[i])); out_long (peer_id[i].access_hash); } out_int (CODE_vector); out_int (num); for (i = 0; i < num; i++) { out_long (E->list[i].id); } out_cstring (text, text_len); out_int (CODE_message_media_empty); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, E, callback, callback_extra); } /* }}} */ /* {{{ block user */ static int block_user_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1); } return 0; } static struct query_methods block_user_methods = { .on_answer = block_user_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM (bool), .name = "block user" }; void tgl_do_block_user (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_USER) { tgl_set_query_error (TLS, EINVAL, "id should be user id"); if (callback) { callback (TLS, callback_extra, 0); } return; } clear_packet (); out_int (CODE_contacts_block); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &block_user_methods, 0, callback, callback_extra); } void tgl_do_unblock_user (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { if (tgl_get_peer_type (id) != TGL_PEER_USER) { tgl_set_query_error (TLS, EINVAL, "id should be user id"); if (callback) { callback (TLS, callback_extra, 0); } return; } clear_packet (); out_int (CODE_contacts_unblock); out_int (CODE_input_user); out_int (tgl_get_peer_id (id)); out_long (id.access_hash); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &block_user_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ get terms of service */ static int get_tos_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_help_terms_of_service *DS_T = D; int l = DS_T->text->len; char *s = talloc (l + 1); char *str = DS_T->text->data; int p = 0; int pp = 0; while (p < l) { if (*str == '\\' && p < l - 1) { str ++; p ++; switch (*str) { case 'n': s[pp ++] = '\n'; break; case 't': s[pp ++] = '\t'; break; case 'r': s[pp ++] = '\r'; break; default: s[pp ++] = *str; } str ++; p ++; } else { s[pp ++] = *str; str ++; p ++; } } s[pp] = 0; if (q->callback) { ((void (*)(struct tgl_state *, void *, int, char *))q->callback)(TLS, q->callback_extra, 1, s); } tfree (s, l + 1); return 0; } static struct query_methods get_tos_methods = { .on_answer = get_tos_on_answer, .on_error = q_ptr_on_error, .type = TYPE_TO_PARAM (help_terms_of_service), .name = "get tos" }; void tgl_do_get_terms_of_service (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *ans), void *callback_extra) { clear_packet (); out_int (CODE_help_get_terms_of_service); out_string (""); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_tos_methods, 0, callback, callback_extra); } /* }}} */ void tgl_do_upgrade_group (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_migrate_chat); out_int (tgl_get_peer_id (id)); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_msgs_methods, 0, callback, callback_extra); } static void set_flag_4 (struct tgl_state *TLS, void *_D, int success) { struct tgl_dc *D = _D; assert (success); D->flags |= 4; TLS->timer_methods->insert (D->ev, TLS->temp_key_expire_time * 0.9); } static int send_bind_temp_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tgl_dc *DC = q->extra; DC->flags |= 2; tgl_do_help_get_config_dc (TLS, DC, set_flag_4, DC); vlogprintf (E_DEBUG, "Bind successful in dc %d\n", DC->id); return 0; } static int send_bind_on_error (struct tgl_state *TLS, struct query *q, int error_code, int l, const char *error) { vlogprintf (E_WARNING, "bind: error %d: %.*s\n", error_code, l, error); if (error_code == 400) { return -11; } return 0; } static struct query_methods send_bind_temp_methods = { .on_answer = send_bind_temp_on_answer, .on_error = send_bind_on_error, .type = TYPE_TO_PARAM (bool), .name = "bind temp auth key" }; void tgl_do_send_bind_temp_key (struct tgl_state *TLS, struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id) { clear_packet (); out_int (CODE_auth_bind_temp_auth_key); out_long (D->auth_key_id); out_long (nonce); out_int (expires_at); out_cstring (data, len); struct query *q = tglq_send_query_ex (TLS, D, packet_ptr - packet_buffer, packet_buffer, &send_bind_temp_methods, D, 0, 0, 2); assert (q->msg_id == msg_id); } static int update_status_on_answer (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1); } return 0; } static struct query_methods update_status_methods = { .on_answer = update_status_on_answer, .on_error = q_void_on_error, .type = TYPE_TO_PARAM(bool), .name = "update status" }; void tgl_do_update_status (struct tgl_state *TLS, int online, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_account_update_status); out_int (online ? CODE_bool_false : CODE_bool_true); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0, callback, callback_extra); } void tgl_do_request_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E) { assert (0); exit (2); } void tgl_do_accept_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, long long exchange_id, unsigned char ga[]) { assert (0); exit (2); } void tgl_do_confirm_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, int sen_nop) { assert (0); exit (2); } void tgl_do_commit_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char gb[]) { assert (0); exit (2); } void tgl_do_abort_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E) { assert (0); exit (2); } void tgl_started_cb (struct tgl_state *TLS, void *arg, int success) { if (!success) { vlogprintf (E_ERROR, "login problem: error #%d (%s)\n", TLS->error_code, TLS->error); if (TLS->callback.on_failed_login) { TLS->callback.on_failed_login (TLS); } else { assert (success); } return; } TLS->started = 1; if (TLS->callback.started) { TLS->callback.started (TLS); } } void tgl_export_auth_callback (struct tgl_state *TLS, void *arg, int success) { if (!success) { vlogprintf (E_ERROR, "login problem: error #%d (%s)\n", TLS->error_code, TLS->error); if (TLS->callback.on_failed_login) { TLS->callback.on_failed_login (TLS); } else { assert (success); } return; } int i; for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i])) { return; } if (TLS->callback.logged_in) { TLS->callback.logged_in (TLS); } tglm_send_all_unsent (TLS); tgl_do_get_difference (TLS, 0, tgl_started_cb, 0); } void tgl_export_all_auth (struct tgl_state *TLS) { int i; int ok = 1; for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i])) { tgl_do_export_auth (TLS, i, tgl_export_auth_callback, TLS->DC_list[i]); ok = 0; } if (ok) { if (TLS->callback.logged_in) { TLS->callback.logged_in (TLS); } tglm_send_all_unsent (TLS); tgl_do_get_difference (TLS, 0, tgl_started_cb, 0); } } struct sign_up_extra { char *phone; char *hash; char *first_name; char *last_name; int phone_len; int hash_len; int first_name_len; int last_name_len; }; void tgl_sign_in_code (struct tgl_state *TLS, const char *code[], void *_T); void tgl_sign_in_result (struct tgl_state *TLS, void *_T, int success, struct tgl_user *U) { struct sign_up_extra *E = _T; if (success) { tfree (E->phone, E->phone_len); tfree (E->hash, E->hash_len); tfree (E, sizeof (*E)); } else { vlogprintf (E_ERROR, "incorrect code\n"); TLS->callback.get_values (TLS, tgl_code, "code ('call' for phone call):", 1, tgl_sign_in_code, E); return; } tgl_export_all_auth (TLS); } void tgl_sign_in_code (struct tgl_state *TLS, const char *code[], void *_T) { struct sign_up_extra *E = _T; if (!strcmp (code[0], "call")) { tgl_do_phone_call (TLS, E->phone, E->phone_len, E->hash, E->hash_len, 0, 0); TLS->callback.get_values (TLS, tgl_code, "code ('call' for phone call):", 1, tgl_sign_in_code, E); return; } tgl_do_send_code_result (TLS, E->phone, E->phone_len, E->hash, E->hash_len, code[0], strlen (code[0]), tgl_sign_in_result, E); } void tgl_sign_up_code (struct tgl_state *TLS, const char *code[], void *_T); void tgl_sign_up_result (struct tgl_state *TLS, void *_T, int success, struct tgl_user *U) { struct sign_up_extra *E = _T; if (success) { tfree (E->phone, E->phone_len); tfree (E->hash, E->hash_len); tfree (E->first_name, E->first_name_len); tfree (E->last_name, E->last_name_len); tfree (E, sizeof (*E)); } else { vlogprintf (E_ERROR, "incorrect code\n"); TLS->callback.get_values (TLS, tgl_code, "code ('call' for phone call):", 1, tgl_sign_up_code, E); return; } tgl_export_all_auth (TLS); } void tgl_sign_up_code (struct tgl_state *TLS, const char *code[], void *_T) { struct sign_up_extra *E = _T; if (!strcmp (code[0], "call")) { tgl_do_phone_call (TLS, E->phone, E->phone_len, E->hash, E->hash_len, 0, 0); TLS->callback.get_values (TLS, tgl_code, "code ('call' for phone call):", 1, tgl_sign_up_code, E); return; } tgl_do_send_code_result_auth (TLS, E->phone, E->phone_len, E->hash, E->hash_len, code[0], strlen (code[0]), E->first_name, E->first_name_len, E->last_name, E->last_name_len, tgl_sign_up_result, E); } void tgl_set_last_name (struct tgl_state *TLS, const char *last_name, struct sign_up_extra *E) { E->last_name_len = strlen (last_name); E->last_name = tmemdup (last_name, E->last_name_len); } int tgl_set_first_name (struct tgl_state *TLS, const char *first_name, struct sign_up_extra *E) { if (strlen (first_name) < 1) { return -1; } E->first_name_len = strlen (first_name); E->first_name = tmemdup (first_name, E->first_name_len); return 0; } void tgl_register_cb (struct tgl_state *TLS, const char *rinfo[], void *_T) { struct sign_up_extra *E = _T; const char *yn = rinfo[0]; if (strlen (yn) > 1) { TLS->callback.get_values (TLS, tgl_register_info, "registration info:", 3, tgl_register_cb, E); } else if (strlen (yn) == 0 || *yn == 'y' || *yn == 'Y') { if (!tgl_set_first_name(TLS, rinfo[1], E)) { tgl_set_last_name(TLS, rinfo[2], E); TLS->callback.get_values (TLS, tgl_code, "code ('call' for phone call):", 1, tgl_sign_up_code, E); } else { TLS->callback.get_values (TLS, tgl_register_info, "registration info:", 3, tgl_register_cb, E); } } else if (*yn == 'n' || *yn == 'N') { vlogprintf (E_ERROR, "stopping registration"); tfree (E->phone, E->phone_len); tfree (E->hash, E->hash_len); tfree (E, sizeof (*E)); tgl_login (TLS); } else { TLS->callback.get_values (TLS, tgl_register_info, "registration info:", 3, tgl_register_cb, E); } } void tgl_sign_in_phone (struct tgl_state *TLS, const char *phone[], void *arg); void tgl_sign_in_phone_cb (struct tgl_state *TLS, void *extra, int success, int registered, const char *mhash) { struct sign_up_extra *E = extra; if (!success) { vlogprintf (E_ERROR, "Incorrect phone number\n"); tfree (E->phone, E->phone_len); tfree (E, sizeof (*E)); TLS->callback.get_values (TLS, tgl_phone_number, "phone number:", 1, tgl_sign_in_phone, NULL); return; } E->hash_len = strlen (mhash); E->hash = tmemdup (mhash, E->hash_len); if (registered) { TLS->callback.get_values (TLS, tgl_code, "code ('call' for phone call):", 1, tgl_sign_in_code, E); } else { TLS->callback.get_values (TLS, tgl_register_info, "registration info:", 3, tgl_register_cb, E); } } void tgl_sign_in_phone (struct tgl_state *TLS, const char *phone[], void *arg) { struct sign_up_extra *E = talloc0 (sizeof (*E)); E->phone_len = strlen (phone[0]); E->phone = tmemdup (phone[0], E->phone_len); tgl_do_send_code (TLS, E->phone, E->phone_len, tgl_sign_in_phone_cb, E); } void tgl_bot_hash_cb (struct tgl_state *TLS, const char *code[], void *arg); void tgl_sign_in_bot_cb (struct tgl_state *TLS, void *_T, int success, struct tgl_user *U) { if (!success) { vlogprintf (E_ERROR, "incorrect bot hash\n"); TLS->callback.get_values (TLS, tgl_bot_hash, "bot hash:", 1, tgl_bot_hash_cb, NULL); return; } tgl_export_all_auth (TLS); } void tgl_bot_hash_cb (struct tgl_state *TLS, const char *code[], void *arg) { tgl_do_send_bot_auth (TLS, code[0], strlen (code[0]), tgl_sign_in_bot_cb, NULL); } void tgl_sign_in (struct tgl_state *TLS) { if (!tgl_signed_dc (TLS, TLS->DC_working)) { if (TLS->is_bot) { TLS->callback.get_values (TLS, tgl_bot_hash, "bot hash:", 1, tgl_bot_hash_cb, NULL); } else { TLS->callback.get_values (TLS, tgl_phone_number, "phone number:", 1, tgl_sign_in_phone, NULL); } } else { tgl_export_all_auth (TLS); } } static void check_authorized (struct tgl_state *TLS, void *arg) { int i; int ok = 1; for (i = 0; i <= TLS->max_dc_num; i++) { if (TLS->DC_list[i]) { tgl_dc_authorize (TLS, TLS->DC_list[i]); } } for (i = 0; i <= TLS->max_dc_num; i++) { if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i]) && !tgl_authorized_dc (TLS, TLS->DC_list[i])) { ok = 0; break; } } if (ok) { TLS->timer_methods->free (TLS->ev_login); TLS->ev_login = NULL; tgl_sign_in (TLS); } else { TLS->timer_methods->insert (TLS->ev_login, 0.1); } } void tgl_login (struct tgl_state *TLS) { int i; int ok = 1; for (i = 0; i <= TLS->max_dc_num; i++) { if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i]) && !tgl_authorized_dc (TLS, TLS->DC_list[i])) { ok = 0; break; } } if (!ok) { TLS->ev_login = TLS->timer_methods->alloc (TLS, check_authorized, NULL); TLS->timer_methods->insert (TLS->ev_login, 0.1); } else { tgl_sign_in (TLS); } } static int callback (struct tgl_state *TLS, struct query *q, void *D) { if (q->callback) { ((void (*)(struct tgl_state *, void *))(q->callback)) (TLS, q->callback_extra); } return 0; } static int send_change_code_on_answer (struct tgl_state *TLS, struct query *q, void *D) { struct tl_ds_account_sent_change_phone_code *DS_ASCPC= D; char *phone_code_hash = DS_STR_DUP (DS_ASCPC->phone_code_hash); if (q->callback) { ((void (*)(struct tgl_state *, void *, int, const char *))(q->callback)) (TLS, q->callback_extra, 1, phone_code_hash); } tfree_str (phone_code_hash); return 0; } struct change_phone_extra { char *phone; char *hash; char *first_name; char *last_name; int phone_len; int hash_len; int first_name_len; int last_name_len; void (*callback)(struct tgl_state *TLS, void *extra, int success); void *callback_extra; }; static struct query_methods set_phone_methods = { .on_answer = callback, .on_error = sign_in_on_error, .type = TYPE_TO_PARAM(user), .name = "set phone" }; static struct query_methods send_change_code_methods = { .on_answer = send_change_code_on_answer, .on_error = q_list_on_error, .type = TYPE_TO_PARAM(account_sent_change_phone_code), .name = "send change phone code" }; void tgl_set_number_code (struct tgl_state *TLS, const char *code[], void *_T); void tgl_set_number_result (struct tgl_state *TLS, void *_T, int success, struct tgl_user *U) { struct change_phone_extra *E = _T; if (success) { if (E->callback) { E->callback (TLS, E->callback_extra, 1); } tfree (E->phone, E->phone_len); tfree (E->hash, E->hash_len); tfree (E, sizeof (*E)); } else { vlogprintf (E_ERROR, "incorrect code\n"); TLS->callback.get_values (TLS, tgl_code, "code:", 1, tgl_set_number_code, E); } } void tgl_set_number_code (struct tgl_state *TLS, const char *code[], void *_T) { struct change_phone_extra *E = _T; clear_packet (); out_int (CODE_account_change_phone); out_cstring (E->phone, E->phone_len); out_cstring (E->hash, E->hash_len); out_cstring (code[0], strlen (code[0])); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_phone_methods, 0, tgl_set_number_result, E); } void tgl_set_phone_number_cb (struct tgl_state *TLS, void *extra, int success, const char *mhash) { struct change_phone_extra *E = extra; if (!success) { vlogprintf (E_ERROR, "Incorrect phone number\n"); if (E->callback) { E->callback (TLS, E->callback_extra, 0); } tfree (E->phone, E->phone_len); tfree (E, sizeof (*E)); return; } E->hash_len = strlen (mhash); E->hash = tmemdup (mhash, E->hash_len); TLS->callback.get_values (TLS, tgl_code, "code:", 1, tgl_set_number_code, E); } void tgl_do_set_phone_number (struct tgl_state *TLS, const char *phonenumber, int phonenumber_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) { struct change_phone_extra *E = talloc0 (sizeof (*E)); E->phone_len = phonenumber_len; E->phone = tmemdup (phonenumber, E->phone_len); clear_packet (); tgl_do_insert_header (TLS); out_int (CODE_account_send_change_phone_code); out_cstring (E->phone, E->phone_len); E->callback = callback; E->callback_extra = callback_extra; tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_change_code_methods, NULL, tgl_set_phone_number_cb, E); } ================================================ FILE: queries.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ //#include "net.h" #ifndef __QUERIES_H__ #define __QUERIES_H__ #include "tgl-structures.h" #include "auto.h" #include "tgl-layout.h" #define QUERY_ACK_RECEIVED 1 #define QUERY_FORCE_SEND 2 struct query; struct query_methods { int (*on_answer)(struct tgl_state *TLS, struct query *q, void *DS); int (*on_error)(struct tgl_state *TLS, struct query *q, int error_code, int len, const char *error); int (*on_timeout)(struct tgl_state *TLS, struct query *q); struct paramed_type *type; char *name; double timeout; }; struct query { long long msg_id; int data_len; int flags; int seq_no; long long session_id; void *data; struct query_methods *methods; struct tgl_timer *ev; struct tgl_dc *DC; struct tgl_session *session; struct paramed_type *type; void *extra; void *callback; void *callback_extra; }; struct query *tglq_send_query (struct tgl_state *TLS, struct tgl_dc *DC, int len, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra); void tglq_query_ack (struct tgl_state *TLS, long long id); int tglq_query_error (struct tgl_state *TLS, long long id); int tglq_query_result (struct tgl_state *TLS, long long id); void tglq_query_restart (struct tgl_state *TLS, long long id); //double next_timer_in (void); //void work_timers (void); //extern struct query_methods help_get_config_methods; double get_double_time (void); void tgl_do_send_bind_temp_key (struct tgl_state *TLS, struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id); void tgl_do_request_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E); void tgl_do_confirm_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, int sen_nop); void tgl_do_accept_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, long long exchange_id, unsigned char g_a[]); void tgl_do_commit_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char g_a[]); void tgl_do_abort_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E); void tglq_regen_query (struct tgl_state *TLS, long long id); void tglq_query_delete (struct tgl_state *TLS, long long id); void tglq_query_free_all (struct tgl_state *TLS); void tglq_regen_queries_from_old_session (struct tgl_state *TLS, struct tgl_dc *DC, struct tgl_session *S); // For binlog //int get_dh_config_on_answer (struct query *q); //void fetch_dc_option (void); #endif ================================================ FILE: scheme.tl ================================================ int ?= Int; long ?= Long; double ?= Double; string ?= String; bytes string = Bytes; int128 long long = Int128; int256 long long long long = Int256; boolFalse#bc799737 = Bool; boolTrue#997275b5 = Bool; true#3fedd339 = True; vector#1cb5c415 {t:Type} # [ t ] = Vector t; error#c4b9f9bb code:int text:string = Error; null#56730bcc = Null; inputPeerEmpty#7f3b18ea = InputPeer; inputPeerSelf#7da07ec9 = InputPeer; inputPeerChat#179be863 chat_id:int = InputPeer; inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer; inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer; inputUserEmpty#b98886cf = InputUser; inputUserSelf#f7c1b13f = InputUser; inputUser#d8292816 user_id:int access_hash:long = InputUser; inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact; inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile; inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile; inputMediaEmpty#9664f57f = InputMedia; inputMediaUploadedPhoto#f7aff1c0 file:InputFile caption:string = InputMedia; inputMediaPhoto#e9bfb4f3 id:InputPhoto caption:string = InputMedia; inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia; inputMediaContact#a6e45987 phone_number:string first_name:string last_name:string = InputMedia; inputMediaUploadedVideo#82713fdf file:InputFile duration:int w:int h:int mime_type:string caption:string = InputMedia; inputMediaUploadedThumbVideo#7780ddf9 file:InputFile thumb:InputFile duration:int w:int h:int mime_type:string caption:string = InputMedia; inputMediaVideo#936a4ebd video:InputVideo caption:string = InputMedia; inputMediaUploadedAudio#4e498cab file:InputFile duration:int mime_type:string = InputMedia; inputMediaAudio#89938781 audio:InputAudio = InputMedia; inputMediaUploadedDocument#1d89306d file:InputFile mime_type:string attributes:Vector caption:string = InputMedia; inputMediaUploadedThumbDocument#ad613491 file:InputFile thumb:InputFile mime_type:string attributes:Vector caption:string = InputMedia; inputMediaDocument#1a77f29c document_id:InputDocument caption:string = InputMedia; inputMediaVenue#2827a81a geo_point:InputGeoPoint title:string address:string provider:string venue_id:string = InputMedia; inputMediaGifExternal#4843b0fd url:string q:string = InputMedia; inputChatPhotoEmpty#1ca48f57 = InputChatPhoto; inputChatUploadedPhoto#94254732 file:InputFile crop:InputPhotoCrop = InputChatPhoto; inputChatPhoto#b2e1bf08 id:InputPhoto crop:InputPhotoCrop = InputChatPhoto; inputGeoPointEmpty#e4c123d6 = InputGeoPoint; inputGeoPoint#f3b7acc9 latitude:double longitude:double = InputGeoPoint; inputPhotoEmpty#1cd7bf0d = InputPhoto; inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto; inputVideoEmpty#5508ec75 = InputVideo; inputVideo#ee579652 id:long access_hash:long = InputVideo; inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation; inputVideoFileLocation#3d0364ec id:long access_hash:long = InputFileLocation; inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation; inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation; inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation; inputPhotoCropAuto#ade6b004 = InputPhotoCrop; inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop; inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent; peerUser#9db1bc6d user_id:int = Peer; peerChat#bad0e5bb chat_id:int = Peer; peerChannel#bddde532 channel_id:int = Peer; storage.fileUnknown#aa963b05 = storage.FileType; storage.fileJpeg#7efe0e = storage.FileType; storage.fileGif#cae1aadf = storage.FileType; storage.filePng#a4f63c0 = storage.FileType; storage.filePdf#ae1e508d = storage.FileType; storage.fileMp3#528a0677 = storage.FileType; storage.fileMov#4b09ebbc = storage.FileType; storage.filePartial#40bc6f52 = storage.FileType; storage.fileMp4#b3cea0e4 = storage.FileType; storage.fileWebp#1081464c = storage.FileType; fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation; fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation; userEmpty#200250ba id:int = User; user#d10d979a flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string = User; userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto; userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto; userStatusEmpty#9d05049 = UserStatus; userStatusOnline#edb93949 expires:int = UserStatus; userStatusOffline#8c703f was_online:int = UserStatus; userStatusRecently#e26f42f1 = UserStatus; userStatusLastWeek#7bf09fc = UserStatus; userStatusLastMonth#77ebc742 = UserStatus; chatEmpty#9ba2d800 id:int = Chat; chat#d91cdd54 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true admins_enabled:flags.3?true admin:flags.4?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel = Chat; chatForbidden#7328bdb id:int title:string = Chat; channel#4b1b7506 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true editor:flags.3?true moderator:flags.4?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true id:int access_hash:long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string = Chat; channelForbidden#2d85832c id:int access_hash:long title:string = Chat; chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector = ChatFull; channelFull#9e341ddf flags:# can_view_participants:flags.3?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int read_inbox_max_id:int unread_count:int unread_important_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int = ChatFull; chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant; chatParticipantCreator#da13538a user_id:int = ChatParticipant; chatParticipantAdmin#e2d6e436 user_id:int inviter_id:int date:int = ChatParticipant; chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0?ChatParticipant = ChatParticipants; chatParticipants#3f460fed chat_id:int participants:Vector version:int = ChatParticipants; chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto; messageEmpty#83e5de54 id:int = Message; message#c992e15c flags:# unread:flags.0?true out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true id:int from_id:flags.8?int to_id:Peer fwd_from_id:flags.2?Peer fwd_date:flags.2?int via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int = Message; messageService#c06b9607 flags:# unread:flags.0?true out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true id:int from_id:flags.8?int to_id:Peer date:int action:MessageAction = Message; messageMediaEmpty#3ded6320 = MessageMedia; messageMediaPhoto#3d8ce53d photo:Photo caption:string = MessageMedia; messageMediaVideo#5bcf1675 video:Video caption:string = MessageMedia; messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia; messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia; messageMediaUnsupported#9f84f49e = MessageMedia; messageMediaDocument#f3e02ea8 document:Document caption:string = MessageMedia; messageMediaAudio#c6b68300 audio:Audio = MessageMedia; messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia; messageMediaVenue#7912b71f geo:GeoPoint title:string address:string provider:string venue_id:string = MessageMedia; messageActionEmpty#b6aef7b0 = MessageAction; messageActionChatCreate#a6638b9a title:string users:Vector = MessageAction; messageActionChatEditTitle#b5a1ce5a title:string = MessageAction; messageActionChatEditPhoto#7fcb13a8 photo:Photo = MessageAction; messageActionChatDeletePhoto#95e3fbef = MessageAction; messageActionChatAddUser#488a7337 users:Vector = MessageAction; messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction; messageActionChatJoinedByLink#f89cf5e8 inviter_id:int = MessageAction; messageActionChannelCreate#95d2ac92 title:string = MessageAction; messageActionChatMigrateTo#51bdb021 channel_id:int = MessageAction; messageActionChannelMigrateFrom#b055eaee title:string chat_id:int = MessageAction; dialog#c1dd804a peer:Peer top_message:int read_inbox_max_id:int unread_count:int notify_settings:PeerNotifySettings = Dialog; dialogChannel#5b8496b2 peer:Peer top_message:int top_important_message:int read_inbox_max_id:int unread_count:int unread_important_count:int notify_settings:PeerNotifySettings pts:int = Dialog; photoEmpty#2331b22d id:long = Photo; photo#cded42fe id:long access_hash:long date:int sizes:Vector = Photo; photoSizeEmpty#e17e23c type:string = PhotoSize; photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize; photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize; videoEmpty#c10658a8 id:long = Video; video#f72887d3 id:long access_hash:long date:int duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video; geoPointEmpty#1117dd5f = GeoPoint; geoPoint#2049d70c longitude:double latitude:double = GeoPoint; auth.checkedPhone#811ea28e phone_registered:Bool = auth.CheckedPhone; auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode; auth.sentAppCode#e325edcf phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode; auth.authorization#ff036af1 user:User = auth.Authorization; auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorization; inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer; inputNotifyUsers#193b4417 = InputNotifyPeer; inputNotifyChats#4a95e84e = InputNotifyPeer; inputNotifyAll#a429b886 = InputNotifyPeer; inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents; inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents; inputPeerNotifySettings#46a2ce98 mute_until:int sound:string show_previews:Bool events_mask:int = InputPeerNotifySettings; peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents; peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents; peerNotifySettingsEmpty#70a68512 = PeerNotifySettings; peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool events_mask:int = PeerNotifySettings; wallPaper#ccb03657 id:int title:string sizes:Vector color:int = WallPaper; wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper; inputReportReasonSpam#58dbcab8 = ReportReason; inputReportReasonViolence#1e22c78d = ReportReason; inputReportReasonPornography#2e59d922 = ReportReason; inputReportReasonOther#e1746d0a text:string = ReportReason; userFull#5a89ac5b user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool bot_info:BotInfo = UserFull; contact#f911c994 user_id:int mutual:Bool = Contact; importedContact#d0028438 user_id:int client_id:long = ImportedContact; contactBlocked#561bc879 user_id:int date:int = ContactBlocked; contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested; contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus; contacts.link#3ace484c my_link:ContactLink foreign_link:ContactLink user:User = contacts.Link; contacts.contactsNotModified#b74ba9d2 = contacts.Contacts; contacts.contacts#6f8b8cb2 contacts:Vector users:Vector = contacts.Contacts; contacts.importedContacts#ad524315 imported:Vector retry_contacts:Vector users:Vector = contacts.ImportedContacts; contacts.blocked#1c138d15 blocked:Vector users:Vector = contacts.Blocked; contacts.blockedSlice#900802a1 count:int blocked:Vector users:Vector = contacts.Blocked; contacts.suggested#5649dcc5 results:Vector users:Vector = contacts.Suggested; messages.dialogs#15ba6c40 dialogs:Vector messages:Vector chats:Vector users:Vector = messages.Dialogs; messages.dialogsSlice#71e094f3 count:int dialogs:Vector messages:Vector chats:Vector users:Vector = messages.Dialogs; messages.messages#8c718e87 messages:Vector chats:Vector users:Vector = messages.Messages; messages.messagesSlice#b446ae3 count:int messages:Vector chats:Vector users:Vector = messages.Messages; messages.channelMessages#bc0f17bc flags:# pts:int count:int messages:Vector collapsed:flags.0?Vector chats:Vector users:Vector = messages.Messages; messages.chats#64ff9fd5 chats:Vector = messages.Chats; messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector users:Vector = messages.ChatFull; messages.affectedHistory#b45c69d1 pts:int pts_count:int offset:int = messages.AffectedHistory; inputMessagesFilterEmpty#57e2f66c = MessagesFilter; inputMessagesFilterPhotos#9609a51c = MessagesFilter; inputMessagesFilterVideo#9fc00e65 = MessagesFilter; inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter; inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter; inputMessagesFilterDocument#9eddf188 = MessagesFilter; inputMessagesFilterAudio#cfc87522 = MessagesFilter; inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter; inputMessagesFilterUrl#7ef0dd87 = MessagesFilter; inputMessagesFilterGif#ffc86587 = MessagesFilter; updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update; updateMessageID#4e90bfd6 id:int random_id:long = Update; updateDeleteMessages#a20db0e5 messages:Vector pts:int pts_count:int = Update; updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update; updateChatUserTyping#9a65ea1f chat_id:int user_id:int action:SendMessageAction = Update; updateChatParticipants#7761198 participants:ChatParticipants = Update; updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update; updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update; updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update; updateContactRegistered#2575bbb9 user_id:int date:int = Update; updateContactLink#9d2e67c5 user_id:int my_link:ContactLink foreign_link:ContactLink = Update; updateNewAuthorization#8f06529a auth_key_id:long date:int device:string location:string = Update; updateNewEncryptedMessage#12bcbd9a encr_message:EncryptedMessage qts:int = Update; updateEncryptedChatTyping#1710f156 chat_id:int = Update; updateEncryption#b4a2e88d encr_chat:EncryptedChat date:int = Update; updateEncryptedMessagesRead#38fe25b7 chat_id:int max_date:int date:int = Update; updateChatParticipantAdd#ea4b0e5c chat_id:int user_id:int inviter_id:int date:int version:int = Update; updateChatParticipantDelete#6e5f8c22 chat_id:int user_id:int version:int = Update; updateDcOptions#8e5e9873 dc_options:Vector = Update; updateUserBlocked#80ece81a user_id:int blocked:Bool = Update; updateNotifySettings#bec268ef notify_peer:NotifyPeer notify_settings:PeerNotifySettings = Update; updateServiceNotification#382dd3e4 type:string message_text:string media:MessageMedia popup:Bool = Update; updatePrivacy#ee3b272a key:PrivacyKey rules:Vector = Update; updateUserPhone#12b9417b user_id:int phone:string = Update; updateReadHistoryInbox#9961fd5c peer:Peer max_id:int pts:int pts_count:int = Update; updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update; updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update; updateReadMessagesContents#68c13933 messages:Vector pts:int pts_count:int = Update; updateChannelTooLong#60946422 channel_id:int = Update; updateChannel#b6d45656 channel_id:int = Update; updateChannelGroup#c36c1e3c channel_id:int group:MessageGroup = Update; updateNewChannelMessage#62ba04d9 message:Message channel_pts:int channel_pts_count:int = Update; updateReadChannelInbox#4214f37f channel_id:int max_id:int = Update; updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector channel_pts:int channel_pts_count:int = Update; updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update; updateChatAdmins#6e947941 chat_id:int enabled:Bool version:int = Update; updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update; updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update; updateStickerSetsOrder#f0dfb451 order:Vector = Update; updateStickerSets#43ae3dec = Update; updateSavedGifs#9375341e = Update; updateBotInlineQuery#c01eea08 query_id:long user_id:int query:string offset:string = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference; updates.difference#f49ca0 new_messages:Vector new_encrypted_messages:Vector other_updates:Vector chats:Vector users:Vector state:updates.State = updates.Difference; updates.differenceSlice#a8fb1981 new_messages:Vector new_encrypted_messages:Vector other_updates:Vector chats:Vector users:Vector intermediate_state:updates.State = updates.Difference; updatesTooLong#e317af7e = Updates; updateShortMessage#13e4deaa flags:# unread:flags.0?true out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true id:int user_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?Peer fwd_date:flags.2?int via_bot_id:flags.11?int reply_to_msg_id:flags.3?int entities:flags.7?Vector = Updates; updateShortChatMessage#248afa62 flags:# unread:flags.0?true out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true id:int from_id:int chat_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?Peer fwd_date:flags.2?int via_bot_id:flags.11?int reply_to_msg_id:flags.3?int entities:flags.7?Vector = Updates; updateShort#78d4dec1 update:Update date:int = Updates; updatesCombined#725b04c3 updates:Vector users:Vector chats:Vector date:int seq_start:int seq:int = Updates; updates#74ae4240 updates:Vector users:Vector chats:Vector date:int seq:int = Updates; updateShortSentMessage#11f1331c flags:# unread:flags.0?true out:flags.1?true id:int pts:int pts_count:int date:int media:flags.9?MessageMedia entities:flags.7?Vector = Updates; photos.photos#8dca6aa5 photos:Vector users:Vector = photos.Photos; photos.photosSlice#15051f54 count:int photos:Vector users:Vector = photos.Photos; photos.photo#20212ca8 photo:Photo users:Vector = photos.Photo; upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File; dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true id:int ip_address:string port:int = DcOption; config#6bbc5f8 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int disabled_features:Vector = Config; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; help.appUpdate#8987f311 id:int critical:Bool url:string text:string = help.AppUpdate; help.noAppUpdate#c45a6536 = help.AppUpdate; help.inviteText#18cb9f78 message:string = help.InviteText; encryptedChatEmpty#ab7ec0a0 id:int = EncryptedChat; encryptedChatWaiting#3bf703dc id:int access_hash:long date:int admin_id:int participant_id:int = EncryptedChat; encryptedChatRequested#c878527e id:int access_hash:long date:int admin_id:int participant_id:int g_a:bytes = EncryptedChat; encryptedChat#fa56ce36 id:int access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long = EncryptedChat; encryptedChatDiscarded#13d6dd27 id:int = EncryptedChat; inputEncryptedChat#f141b5e1 chat_id:int access_hash:long = InputEncryptedChat; encryptedFileEmpty#c21f497e = EncryptedFile; encryptedFile#4a70994c id:long access_hash:long size:int dc_id:int key_fingerprint:int = EncryptedFile; inputEncryptedFileEmpty#1837c364 = InputEncryptedFile; inputEncryptedFileUploaded#64bd0306 id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile; inputEncryptedFile#5a17b5e5 id:long access_hash:long = InputEncryptedFile; inputEncryptedFileBigUploaded#2dc173c8 id:long parts:int key_fingerprint:int = InputEncryptedFile; encryptedMessage#ed18c118 random_id:long chat_id:int date:int bytes:bytes file:EncryptedFile = EncryptedMessage; encryptedMessageService#23734b06 random_id:long chat_id:int date:int bytes:bytes = EncryptedMessage; messages.dhConfigNotModified#c0e24635 random:bytes = messages.DhConfig; messages.dhConfig#2c221edd g:int p:bytes version:int random:bytes = messages.DhConfig; messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage; messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage; inputAudioEmpty#d95adc84 = InputAudio; inputAudio#77d440ff id:long access_hash:long = InputAudio; inputDocumentEmpty#72f0eaae = InputDocument; inputDocument#18798952 id:long access_hash:long = InputDocument; audioEmpty#586988d8 id:long = Audio; audio#f9e35055 id:long access_hash:long date:int duration:int mime_type:string size:int dc_id:int = Audio; documentEmpty#36f8c871 id:long = Document; document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector = Document; help.support#17c6b5f6 phone_number:string user:User = help.Support; notifyPeer#9fd40bd8 peer:Peer = NotifyPeer; notifyUsers#b4c83b4c = NotifyPeer; notifyChats#c007cec3 = NotifyPeer; notifyAll#74d07c60 = NotifyPeer; sendMessageTypingAction#16bf744e = SendMessageAction; sendMessageCancelAction#fd5ec8f5 = SendMessageAction; sendMessageRecordVideoAction#a187d66f = SendMessageAction; sendMessageUploadVideoAction#e9763aec progress:int = SendMessageAction; sendMessageRecordAudioAction#d52f73f7 = SendMessageAction; sendMessageUploadAudioAction#f351d7ab progress:int = SendMessageAction; sendMessageUploadPhotoAction#d1d34a26 progress:int = SendMessageAction; sendMessageUploadDocumentAction#aa0cd9e4 progress:int = SendMessageAction; sendMessageGeoLocationAction#176f8ba1 = SendMessageAction; sendMessageChooseContactAction#628cbc6f = SendMessageAction; contacts.found#1aa1f784 results:Vector chats:Vector users:Vector = contacts.Found; inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey; privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey; inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule; inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule; inputPrivacyValueAllowUsers#131cc67f users:Vector = InputPrivacyRule; inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule; inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule; inputPrivacyValueDisallowUsers#90110467 users:Vector = InputPrivacyRule; privacyValueAllowContacts#fffe1bac = PrivacyRule; privacyValueAllowAll#65427b82 = PrivacyRule; privacyValueAllowUsers#4d5bbe0c users:Vector = PrivacyRule; privacyValueDisallowContacts#f888fa1a = PrivacyRule; privacyValueDisallowAll#8b73e763 = PrivacyRule; privacyValueDisallowUsers#c7f49b7 users:Vector = PrivacyRule; account.privacyRules#554abb6f rules:Vector users:Vector = account.PrivacyRules; accountDaysTTL#b8d0afdf days:int = AccountDaysTTL; account.sentChangePhoneCode#a4f58c4c phone_code_hash:string send_call_timeout:int = account.SentChangePhoneCode; documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute; documentAttributeAnimated#11b58939 = DocumentAttribute; documentAttributeSticker#3a556302 alt:string stickerset:InputStickerSet = DocumentAttribute; documentAttributeVideo#5910cccb duration:int w:int h:int = DocumentAttribute; documentAttributeAudio#ded218e0 duration:int title:string performer:string = DocumentAttribute; documentAttributeFilename#15590068 file_name:string = DocumentAttribute; messages.stickersNotModified#f1749a22 = messages.Stickers; messages.stickers#8a8ecd32 hash:string stickers:Vector = messages.Stickers; stickerPack#12b299d4 emoticon:string documents:Vector = StickerPack; messages.allStickersNotModified#e86602c3 = messages.AllStickers; messages.allStickers#edfd405f hash:int sets:Vector = messages.AllStickers; disabledFeature#ae636f24 feature:string description:string = DisabledFeature; messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages; contactLinkUnknown#5f4f9247 = ContactLink; contactLinkNone#feedd3ad = ContactLink; contactLinkHasPhone#268f3f59 = ContactLink; contactLinkContact#d502c2d0 = ContactLink; webPageEmpty#eb1477e8 id:long = WebPage; webPagePending#c586da1c id:long date:int = WebPage; webPage#ca820ed7 flags:# id:long url:string display_url:string type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document = WebPage; authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization; account.authorizations#1250abde authorizations:Vector = account.Authorizations; account.noPassword#96dabc18 new_salt:bytes email_unconfirmed_pattern:string = account.Password; account.password#7c18141c current_salt:bytes new_salt:bytes hint:string has_recovery:Bool email_unconfirmed_pattern:string = account.Password; account.passwordSettings#b7b72ab3 email:string = account.PasswordSettings; account.passwordInputSettings#bcfc532c flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string = account.PasswordInputSettings; auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery; receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage; chatInviteEmpty#69df3769 = ExportedChatInvite; chatInviteExported#fc2e05bc link:string = ExportedChatInvite; chatInviteAlready#5a686d7c chat:Chat = ChatInvite; chatInvite#93e99b60 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string = ChatInvite; inputStickerSetEmpty#ffb62b95 = InputStickerSet; inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet; inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet; stickerSet#cd303b41 flags:# installed:flags.0?true disabled:flags.1?true official:flags.2?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet; messages.stickerSet#b60a24a6 set:StickerSet packs:Vector documents:Vector = messages.StickerSet; botCommand#c27ac8c7 command:string description:string = BotCommand; botInfoEmpty#bb2e37ce = BotInfo; botInfo#9cf585d user_id:int version:int share_text:string description:string commands:Vector = BotInfo; keyboardButton#a2fa4880 text:string = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup; replyKeyboardForceReply#f4108aa0 flags:# single_use:flags.1?true selective:flags.2?true = ReplyMarkup; replyKeyboardMarkup#3502758c flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector = ReplyMarkup; help.appChangelogEmpty#af7e0394 = help.AppChangelog; help.appChangelog#4668e6bd text:string = help.AppChangelog; messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity; messageEntityMention#fa04579d offset:int length:int = MessageEntity; messageEntityHashtag#6f635b0d offset:int length:int = MessageEntity; messageEntityBotCommand#6cef8ac7 offset:int length:int = MessageEntity; messageEntityUrl#6ed02538 offset:int length:int = MessageEntity; messageEntityEmail#64e475c2 offset:int length:int = MessageEntity; messageEntityBold#bd610bc9 offset:int length:int = MessageEntity; messageEntityItalic#826f8b60 offset:int length:int = MessageEntity; messageEntityCode#28a20571 offset:int length:int = MessageEntity; messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity; messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity; inputChannelEmpty#ee8c1e86 = InputChannel; inputChannel#afeb712e channel_id:int access_hash:long = InputChannel; contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector users:Vector = contacts.ResolvedPeer; messageRange#ae30253 min_id:int max_id:int = MessageRange; messageGroup#e8346f53 min_id:int max_id:int count:int date:int = MessageGroup; updates.channelDifferenceEmpty#3e11affb flags:# final:flags.0?true channel_pts:int timeout:flags.1?int = updates.ChannelDifference; updates.channelDifferenceTooLong#5e167646 flags:# final:flags.0?true channel_pts:int timeout:flags.1?int top_message:int top_important_message:int read_inbox_max_id:int unread_count:int unread_important_count:int messages:Vector chats:Vector users:Vector = updates.ChannelDifference; updates.channelDifference#2064674e flags:# final:flags.0?true channel_pts:int timeout:flags.1?int new_messages:Vector other_updates:Vector chats:Vector users:Vector = updates.ChannelDifference; channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter; channelMessagesFilter#cd77d957 flags:# important_only:flags.0?true exclude_new_messages:flags.1?true ranges:Vector = ChannelMessagesFilter; channelMessagesFilterCollapsed#fa01232e = ChannelMessagesFilter; channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant; channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant; channelParticipantModerator#91057fef user_id:int inviter_id:int date:int = ChannelParticipant; channelParticipantEditor#98192d61 user_id:int inviter_id:int date:int = ChannelParticipant; channelParticipantKicked#8cc5e69a user_id:int kicked_by:int date:int = ChannelParticipant; channelParticipantCreator#e3e2e1f9 user_id:int = ChannelParticipant; channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter; channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter; channelParticipantsKicked#3c37bb7a = ChannelParticipantsFilter; channelParticipantsBots#b0d1865b = ChannelParticipantsFilter; channelRoleEmpty#b285a0c6 = ChannelParticipantRole; channelRoleModerator#9618d975 = ChannelParticipantRole; channelRoleEditor#820bfe8c = ChannelParticipantRole; channels.channelParticipants#f56ee2a8 count:int participants:Vector users:Vector = channels.ChannelParticipants; channels.channelParticipant#d0d9b163 participant:ChannelParticipant users:Vector = channels.ChannelParticipant; help.termsOfService#f1ee3e90 text:string = help.TermsOfService; foundGif#162ecc1f url:string thumb_url:string content_url:string content_type:string w:int h:int = FoundGif; foundGifCached#9c750409 url:string photo:Photo document:Document = FoundGif; messages.foundGifs#450a1c0a next_offset:int results:Vector = messages.FoundGifs; messages.savedGifsNotModified#e8025ca2 = messages.SavedGifs; messages.savedGifs#2e0709a5 hash:int gifs:Vector = messages.SavedGifs; inputBotInlineMessageMediaAuto#2e43e587 caption:string = InputBotInlineMessage; inputBotInlineMessageText#adf0df71 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector = InputBotInlineMessage; inputBotInlineResult#2cbbe15a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:InputBotInlineMessage = InputBotInlineResult; botInlineMessageMediaAuto#fc56e87d caption:string = BotInlineMessage; botInlineMessageText#a56197a9 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector = BotInlineMessage; botInlineMediaResultDocument#f897d33e id:string type:string document:Document send_message:BotInlineMessage = BotInlineResult; botInlineMediaResultPhoto#c5528587 id:string type:string photo:Photo send_message:BotInlineMessage = BotInlineResult; botInlineResult#9bebaeb9 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:BotInlineMessage = BotInlineResult; messages.botResults#1170b0a3 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string results:Vector = messages.BotResults; ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector query:!X = X; initConnection#69796de9 {X:Type} api_id:int device_model:string system_version:string app_version:string lang_code:string query:!X = X; invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X; invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X; auth.checkPhone#6fe51dfb phone_number:string = auth.CheckedPhone; auth.sendCode#768d5f4d phone_number:string sms_type:int api_id:int api_hash:string lang_code:string = auth.SentCode; auth.sendCall#3c51564 phone_number:string phone_code_hash:string = Bool; auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization; auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization; auth.logOut#5717da40 = Bool; auth.resetAuthorizations#9fab0d1a = Bool; auth.sendInvites#771c1d97 phone_numbers:Vector message:string = Bool; auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization; auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization; auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool; auth.sendSms#da9f3e8 phone_number:string phone_code_hash:string = Bool; auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization; auth.checkPassword#a63011e password_hash:bytes = auth.Authorization; auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery; auth.recoverPassword#4ea56e92 code:string = auth.Authorization; account.registerDevice#446c712c token_type:int token:string device_model:string system_version:string app_version:string app_sandbox:Bool lang_code:string = Bool; account.unregisterDevice#65c55b40 token_type:int token:string = Bool; account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool; account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings; account.resetNotifySettings#db7e1747 = Bool; account.updateProfile#f0888d68 first_name:string last_name:string = User; account.updateStatus#6628562c offline:Bool = Bool; account.getWallPapers#c04cfac2 = Vector; account.reportPeer#ae189d5f peer:InputPeer reason:ReportReason = Bool; account.checkUsername#2714d86c username:string = Bool; account.updateUsername#3e0bdd7c username:string = User; account.getPrivacy#dadbc950 key:InputPrivacyKey = account.PrivacyRules; account.setPrivacy#c9f81ce8 key:InputPrivacyKey rules:Vector = account.PrivacyRules; account.deleteAccount#418d4e0b reason:string = Bool; account.getAccountTTL#8fc711d = AccountDaysTTL; account.setAccountTTL#2442485e ttl:AccountDaysTTL = Bool; account.sendChangePhoneCode#a407a8f4 phone_number:string = account.SentChangePhoneCode; account.changePhone#70c32edb phone_number:string phone_code_hash:string phone_code:string = User; account.updateDeviceLocked#38df3532 period:int = Bool; account.getAuthorizations#e320c158 = account.Authorizations; account.resetAuthorization#df77f3bc hash:long = Bool; account.getPassword#548a30f5 = account.Password; account.getPasswordSettings#bc8d11bb current_password_hash:bytes = account.PasswordSettings; account.updatePasswordSettings#fa7c4b86 current_password_hash:bytes new_settings:account.PasswordInputSettings = Bool; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#ca30a5b1 id:InputUser = UserFull; contacts.getStatuses#c4a353ee = Vector; contacts.getContacts#22c6aa08 hash:string = contacts.Contacts; contacts.importContacts#da30b32d contacts:Vector replace:Bool = contacts.ImportedContacts; contacts.getSuggested#cd773428 limit:int = contacts.Suggested; contacts.deleteContact#8e953744 id:InputUser = contacts.Link; contacts.deleteContacts#59ab389e id:Vector = Bool; contacts.block#332b49fc id:InputUser = Bool; contacts.unblock#e54100bd id:InputUser = Bool; contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked; contacts.exportCard#84e53737 = Vector; contacts.importCard#4fe196fe export_card:Vector = User; contacts.search#11f812d8 q:string limit:int = contacts.Found; contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer; messages.getMessages#4222fa74 id:Vector = messages.Messages; messages.getDialogs#6b47f94d offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs; messages.getHistory#8a8ec2da peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; messages.search#d4569248 flags:# important_only:flags.0?true peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages; messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages; messages.deleteHistory#b7c13bd9 peer:InputPeer max_id:int = messages.AffectedHistory; messages.deleteMessages#a5f18925 id:Vector = messages.AffectedMessages; messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool; messages.sendMessage#fa88427a flags:# no_webpage:flags.1?true broadcast:flags.4?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = Updates; messages.sendMedia#c8f16791 flags:# broadcast:flags.4?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates; messages.forwardMessages#708e0195 flags:# broadcast:flags.4?true from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer = Updates; messages.reportSpam#cf1592db peer:InputPeer = Bool; messages.getChats#3c6aa187 id:Vector = messages.Chats; messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull; messages.editChatTitle#dc452855 chat_id:int title:string = Updates; messages.editChatPhoto#ca4c79d8 chat_id:int photo:InputChatPhoto = Updates; messages.addChatUser#f9a0aa09 chat_id:int user_id:InputUser fwd_limit:int = Updates; messages.deleteChatUser#e0611f16 chat_id:int user_id:InputUser = Updates; messages.createChat#9cb126e users:Vector title:string = Updates; messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates; messages.sendBroadcast#bf73f4da contacts:Vector random_id:Vector message:string media:InputMedia = Updates; messages.getDhConfig#26cf8950 version:int random_length:int = messages.DhConfig; messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat; messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat; messages.discardEncryption#edd923c5 chat_id:int = Bool; messages.setEncryptedTyping#791451ed peer:InputEncryptedChat typing:Bool = Bool; messages.readEncryptedHistory#7f4b690a peer:InputEncryptedChat max_date:int = Bool; messages.sendEncrypted#a9776773 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage; messages.sendEncryptedFile#9a901b66 peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage; messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage; messages.receivedQueue#55a5bb66 max_qts:int = Vector; messages.readMessageContents#36a73f77 id:Vector = messages.AffectedMessages; messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers; messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers; messages.getWebPagePreview#25223e24 message:string = MessageMedia; messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite; messages.checkChatInvite#3eadb1bb hash:string = ChatInvite; messages.importChatInvite#6c50051c hash:string = Updates; messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet; messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool; messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool; messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates; messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector increment:Bool = Vector; messages.toggleChatAdmins#ec8bd9e1 chat_id:int enabled:Bool = Updates; messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool; messages.migrateChat#15a3b8e3 chat_id:int = Updates; messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; messages.reorderStickerSets#9fcfbc30 order:Vector = Bool; messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document; messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs; messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs; messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool; messages.getInlineBotResults#9324600d bot:InputUser query:string offset:string = messages.BotResults; messages.setInlineBotResults#3f23ec12 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector cache_time:int next_offset:flags.2?string = Bool; messages.sendInlineBotResult#b16e06fe flags:# broadcast:flags.4?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates; updates.getState#edd4882a = updates.State; updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference; updates.getChannelDifference#bb32d7c0 channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference; photos.updateProfilePhoto#eef579a0 id:InputPhoto crop:InputPhotoCrop = UserProfilePhoto; photos.uploadProfilePhoto#d50f9c88 file:InputFile caption:string geo_point:InputGeoPoint crop:InputPhotoCrop = photos.Photo; photos.deletePhotos#87cf7f2f id:Vector = Vector; photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos; upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool; upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload.File; upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool; help.getConfig#c4f9186b = Config; help.getNearestDc#1fb33026 = NearestDc; help.getAppUpdate#c812ac7e device_model:string system_version:string app_version:string lang_code:string = help.AppUpdate; help.saveAppLog#6f02f748 events:Vector = Bool; help.getInviteText#a4a95186 lang_code:string = help.InviteText; help.getSupport#9cdf08cd = help.Support; help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog; help.getTermsOfService#37d78f83 lang_code:string = help.TermsOfService; channels.getDialogs#a9d3d249 offset:int limit:int = messages.Dialogs; channels.getImportantHistory#ddb929cb channel:InputChannel offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool; channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector = messages.AffectedMessages; channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = messages.AffectedHistory; channels.reportSpam#fe087810 channel:InputChannel user_id:InputUser id:Vector = Bool; channels.getMessages#93d7b347 channel:InputChannel id:Vector = messages.Messages; channels.getParticipants#24d98f92 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int = channels.ChannelParticipants; channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant; channels.getChannels#a7f6bbb id:Vector = messages.Chats; channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull; channels.createChannel#f4893d7f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string = Updates; channels.editAbout#13e27f1e channel:InputChannel about:string = Bool; channels.editAdmin#eb7611d0 channel:InputChannel user_id:InputUser role:ChannelParticipantRole = Updates; channels.editTitle#566decd0 channel:InputChannel title:string = Updates; channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates; channels.toggleComments#aaa29e88 channel:InputChannel enabled:Bool = Updates; channels.checkUsername#10e6bd2c channel:InputChannel username:string = Bool; channels.updateUsername#3514b3de channel:InputChannel username:string = Bool; channels.joinChannel#24b524c5 channel:InputChannel = Updates; channels.leaveChannel#f836aa95 channel:InputChannel = Updates; channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector = Updates; channels.kickFromChannel#a672de14 channel:InputChannel user_id:InputUser kicked:Bool = Updates; channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite; channels.deleteChannel#c0111fe3 channel:InputChannel = Updates; ================================================ FILE: structures.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "tgl-structures.h" #include "mtproto-common.h" //#include "telegram.h" #include "tree.h" #include "crypto/aes.h" #include "crypto/bn.h" #include "crypto/sha.h" #include "queries.h" #include "tgl-binlog.h" #include "tgl-methods-in.h" #include "updates.h" #include "mtproto-client.h" #include "tgl.h" #include "auto.h" #include "auto/auto-types.h" #include "auto/auto-skip.h" #include "auto/auto-fetch-ds.h" #include "auto/auto-free-ds.h" static int id_cmp (struct tgl_message *M1, struct tgl_message *M2); #define peer_cmp(a,b) (tgl_cmp_peer_id (a->id, b->id)) #define peer_cmp_name(a,b) (strcmp (a->print_name, b->print_name)) static int random_id_cmp (struct tgl_message *L, struct tgl_message *R) { if (L->random_id < R->random_id) { return -1; } if (L->random_id > R->random_id) { return 1; } return 0; } static int temp_id_cmp (struct tgl_message *L, struct tgl_message *R) { if (L->temp_id < R->temp_id) { return -1; } if (L->temp_id > R->temp_id) { return 1; } return 0; } static int photo_id_cmp (struct tgl_photo *L, struct tgl_photo *R) { if (L->id < R->id) { return -1; } if (L->id > R->id) { return 1; } return 0; } static int document_id_cmp (struct tgl_document *L, struct tgl_document *R) { if (L->id < R->id) { return -1; } if (L->id > R->id) { return 1; } return 0; } static int webpage_id_cmp (struct tgl_webpage *L, struct tgl_webpage *R) { if (L->id < R->id) { return -1; } if (L->id > R->id) { return 1; } return 0; } DEFINE_TREE(peer,tgl_peer_t *,peer_cmp,0) DEFINE_TREE(peer_by_name,tgl_peer_t *,peer_cmp_name,0) DEFINE_TREE(message,struct tgl_message *,id_cmp,0) DEFINE_TREE(random_id,struct tgl_message *, random_id_cmp,0) DEFINE_TREE(temp_id,struct tgl_message *, temp_id_cmp,0) DEFINE_TREE(photo,struct tgl_photo *,photo_id_cmp,0) DEFINE_TREE(document,struct tgl_document *,document_id_cmp,0) DEFINE_TREE(webpage,struct tgl_webpage *,webpage_id_cmp,0) static void increase_peer_size (struct tgl_state *TLS); char *tgls_default_create_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4) { const char *d[4]; d[0] = a1; d[1] = a2; d[2] = a3; d[3] = a4; static char buf[10000]; buf[0] = 0; int i; int p = 0; for (i = 0; i < 4; i++) { if (d[i] && strlen (d[i])) { p += tsnprintf (buf + p, 9999 - p, "%s%s", p ? "_" : "", d[i]); assert (p < 9990); } } char *s = buf; while (*s) { if (((unsigned char)*s) <= ' ') { *s = '_'; } if (*s == '#') { *s = '_'; } if (*s == '$') { *s = '_'; } if (*s == '@') { *s = '_'; } s++; } s = buf; int fl = strlen (s); int cc = 0; while (1) { tgl_peer_t *P = tgl_peer_get_by_name (TLS, s); if (!P || !tgl_cmp_peer_id (P->id, id)) { break; } cc ++; assert (cc <= 9999); tsnprintf (s + fl, 9999 - fl, "#%d", cc); } return tstrdup (s); } enum tgl_typing_status tglf_fetch_typing (struct tl_ds_send_message_action *DS_SMA) { if (!DS_SMA) { return 0; } switch (DS_SMA->magic) { case CODE_send_message_typing_action: return tgl_typing_typing; case CODE_send_message_cancel_action: return tgl_typing_cancel; case CODE_send_message_record_video_action: return tgl_typing_record_video; case CODE_send_message_upload_video_action: return tgl_typing_upload_video; case CODE_send_message_record_audio_action: return tgl_typing_record_audio; case CODE_send_message_upload_audio_action: return tgl_typing_upload_audio; case CODE_send_message_upload_photo_action: return tgl_typing_upload_photo; case CODE_send_message_upload_document_action: return tgl_typing_upload_document; case CODE_send_message_geo_location_action: return tgl_typing_geo; case CODE_send_message_choose_contact_action: return tgl_typing_choose_contact; default: assert (0); return tgl_typing_none; } } /*enum tgl_typing_status tglf_fetch_typing (void) { struct tl_ds_send_message_action *DS_SMA = fetch_ds_type_send_message_action (TYPE_TO_PARAM (send_message_action)); enum tgl_typing_status res = tglf_fetch_typing (DS_SMA); free_ds_type_send_message_action (DS_SMA, TYPE_TO_PARAM (send_message_action)); return res; }*/ /* {{{ Fetch */ tgl_peer_id_t tglf_fetch_peer_id (struct tgl_state *TLS, struct tl_ds_peer *DS_P) { switch (DS_P->magic) { case CODE_peer_user: return TGL_MK_USER (DS_LVAL (DS_P->user_id)); case CODE_peer_chat: return TGL_MK_CHAT (DS_LVAL (DS_P->chat_id)); case CODE_peer_channel: return TGL_MK_CHANNEL (DS_LVAL (DS_P->channel_id)); default: assert (0); exit (2); } } int tglf_fetch_file_location (struct tgl_state *TLS, struct tgl_file_location *loc, struct tl_ds_file_location *DS_FL) { if (!DS_FL) { return 0; } loc->dc = DS_LVAL (DS_FL->dc_id); loc->volume = DS_LVAL (DS_FL->volume_id); loc->local_id = DS_LVAL (DS_FL->local_id); loc->secret = DS_LVAL (DS_FL->secret); return 0; } int tglf_fetch_user_status (struct tgl_state *TLS, struct tgl_user_status *S, struct tgl_user *U, struct tl_ds_user_status *DS_US) { if (!DS_US) { return 0; } switch (DS_US->magic) { case CODE_user_status_empty: if (S->online) { tgl_insert_status_update (TLS, U); if (S->online == 1) { tgl_remove_status_expire (TLS, U); } } S->online = 0; S->when = 0; break; case CODE_user_status_online: { if (S->online != 1) { S->when = DS_LVAL (DS_US->expires); if (S->online) { tgl_insert_status_update (TLS, U); } tgl_insert_status_expire (TLS, U); S->online = 1; } else { if (DS_LVAL (DS_US->expires) != S->when) { S->when = DS_LVAL (DS_US->expires); tgl_remove_status_expire (TLS, U); tgl_insert_status_expire (TLS, U); } } } break; case CODE_user_status_offline: if (S->online != -1) { if (S->online) { tgl_insert_status_update (TLS, U); } if (S->online == 1) { tgl_remove_status_expire (TLS, U); } } S->online = -1; S->when = DS_LVAL (DS_US->was_online); break; case CODE_user_status_recently: if (S->online != -2) { if (S->online) { tgl_insert_status_update (TLS, U); } if (S->online == 1) { tgl_remove_status_expire (TLS, U); } } S->online = -2; break; case CODE_user_status_last_week: if (S->online != -3) { if (S->online) { tgl_insert_status_update (TLS, U); } if (S->online == 1) { tgl_remove_status_expire (TLS, U); } } S->online = -3; break; case CODE_user_status_last_month: if (S->online != -4) { if (S->online) { tgl_insert_status_update (TLS, U); } if (S->online == 1) { tgl_remove_status_expire (TLS, U); } } S->online = -4; break; default: assert (0); } return 0; } struct tgl_user *tglf_fetch_alloc_user (struct tgl_state *TLS, struct tl_ds_user *DS_U) { if (!DS_U) { return 0; } if (DS_U->magic == CODE_user_empty) { return 0; } tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->id)); user_id.access_hash = DS_LVAL (DS_U->access_hash); struct tgl_user *U = (struct tgl_user *)tgl_peer_get (TLS, user_id); if (!U) { TLS->users_allocated ++; U = talloc0 (sizeof (tgl_peer_t)); U->id = user_id; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, (tgl_peer_t *)U, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = (tgl_peer_t *)U; } int flags = U->flags; if (DS_LVAL (DS_U->flags) & (1 << 10)) { bl_do_set_our_id (TLS, U->id); flags |= TGLUF_SELF; } else { flags &= ~TGLUF_SELF; } if (DS_LVAL (DS_U->flags) & (1 << 11)) { flags |= TGLUF_CONTACT; } else { flags &= ~TGLUF_CONTACT; } if (DS_LVAL (DS_U->flags) & (1 << 12)) { flags |= TGLUF_MUTUAL_CONTACT; } else { flags &= ~TGLUF_MUTUAL_CONTACT; } if (DS_LVAL (DS_U->flags) & (1 << 14)) { flags |= TGLUF_BOT; } else { flags &= ~TGLUF_BOT; } /* if (DS_LVAL (DS_U->flags) & (1 << 15)) { flags |= TGLUF_BOT_FULL_ACCESS; } if (DS_LVAL (DS_U->flags) & (1 << 16)) { flags |= TGLUF_BOT_NO_GROUPS; }*/ if (DS_LVAL (DS_U->flags) & (1 << 17)) { flags |= TGLUF_OFFICIAL; } else { flags &= ~TGLUF_OFFICIAL; } if (!(flags & TGLUF_CREATED)) { flags |= TGLUF_CREATE | TGLUF_CREATED; } bl_do_user (TLS, tgl_get_peer_id (U->id), DS_U->access_hash, DS_STR (DS_U->first_name), DS_STR (DS_U->last_name), DS_STR (DS_U->phone), DS_STR (DS_U->username), NULL, DS_U->photo, NULL, NULL, NULL, flags ); if (DS_U->status) { assert (tglf_fetch_user_status (TLS, &U->status, U, DS_U->status) >= 0); } if (DS_LVAL (DS_U->flags) & (1 << 13)) { if (!(U->flags & TGLUF_DELETED)) { bl_do_peer_delete (TLS, U->id); } } return U; } struct tgl_user *tglf_fetch_alloc_user_full (struct tgl_state *TLS, struct tl_ds_user_full *DS_UF) { if (!DS_UF) { return NULL; } struct tgl_user *U = tglf_fetch_alloc_user (TLS, DS_UF->user); if (!U) { return NULL; } int flags = U->flags; if (DS_BVAL (DS_UF->blocked)) { flags |= TGLUF_BLOCKED; } else { flags &= ~TGLUF_BLOCKED; } bl_do_user (TLS, tgl_get_peer_id (U->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, DS_UF->profile_photo, NULL, NULL, NULL, DS_UF->bot_info, flags ); return U; } void str_to_256 (unsigned char *dst, char *src, int src_len) { if (src_len >= 256) { memcpy (dst, src + src_len - 256, 256); } else { memset(dst, 0, 256 - src_len); memcpy (dst + 256 - src_len, src, src_len); } } void str_to_32 (unsigned char *dst, char *src, int src_len) { if (src_len >= 32) { memcpy (dst, src + src_len - 32, 32); } else { memset(dst, 0, 32 - src_len); memcpy (dst + 32 - src_len, src, src_len); } } struct tgl_secret_chat *tglf_fetch_alloc_encrypted_chat (struct tgl_state *TLS, struct tl_ds_encrypted_chat *DS_EC) { if (!DS_EC) { return NULL; } if (DS_EC->magic == CODE_encrypted_chat_empty) { return NULL; } tgl_peer_id_t chat_id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_EC->id)); chat_id.access_hash = DS_LVAL (DS_EC->access_hash); struct tgl_secret_chat *U = (void *)tgl_peer_get (TLS, chat_id); if (!U) { TLS->encr_chats_allocated ++; U = talloc0 (sizeof (tgl_peer_t)); U->id = chat_id; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, (tgl_peer_t *)U, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = (tgl_peer_t *)U; } int new = !(U->flags & TGLPF_CREATED); if (DS_EC->magic == CODE_encrypted_chat_discarded) { if (new) { vlogprintf (E_WARNING, "Unknown chat in deleted state. May be we forgot something...\n"); return U; } bl_do_peer_delete (TLS, U->id); //write_secret_chat_file (); return U; } static unsigned char g_key[256]; if (new) { if (DS_EC->magic != CODE_encrypted_chat_requested) { vlogprintf (E_WARNING, "Unknown chat. May be we forgot something...\n"); return U; } str_to_256 (g_key, DS_STR (DS_EC->g_a)); int user_id = DS_LVAL (DS_EC->participant_id) + DS_LVAL (DS_EC->admin_id) - tgl_get_peer_id (TLS->our_id); int r = sc_request; bl_do_encr_chat (TLS, tgl_get_peer_id (U->id), DS_EC->access_hash, DS_EC->date, DS_EC->admin_id, &user_id, NULL, (void *)g_key, NULL, &r, NULL, NULL, NULL, NULL, NULL, NULL, TGLECF_CREATE | TGLECF_CREATED, NULL, 0 ); } else { if (DS_EC->magic == CODE_encrypted_chat_waiting) { int r = sc_waiting; bl_do_encr_chat (TLS, tgl_get_peer_id (U->id), DS_EC->access_hash, DS_EC->date, NULL, NULL, NULL, NULL, NULL, &r, NULL, NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED, NULL, 0 ); return U; // We needed only access hash from here } str_to_256 (g_key, DS_STR (DS_EC->g_a_or_b)); //write_secret_chat_file (); int r = sc_ok; bl_do_encr_chat (TLS, tgl_get_peer_id (U->id), DS_EC->access_hash, DS_EC->date, NULL, NULL, NULL, g_key, NULL, &r, NULL, NULL, NULL, NULL, NULL, DS_EC->key_fingerprint, TGL_FLAGS_UNCHANGED, NULL, 0 ); } return U; } struct tgl_chat *tglf_fetch_alloc_chat (struct tgl_state *TLS, struct tl_ds_chat *DS_C) { if (!DS_C) { return NULL; } if (DS_C->magic == CODE_chat_empty) { return NULL; } if (DS_C->magic == CODE_channel || DS_C->magic == CODE_channel_forbidden) { return (void *)tglf_fetch_alloc_channel (TLS, DS_C); } tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_C->id)); chat_id.access_hash = 0; // chats don't have access hash struct tgl_chat *C = (void *)tgl_peer_get (TLS, chat_id); if (!C) { TLS->chats_allocated ++; C = talloc0 (sizeof (tgl_peer_t)); C->id = chat_id; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, (tgl_peer_t *)C, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = (tgl_peer_t *)C; } C->id = chat_id; int flags = C->flags; if (!(flags & TGLCF_CREATED)) { flags |= TGLCF_CREATE | TGLCF_CREATED; } if (DS_LVAL (DS_C->flags) & 1) { flags |= TGLCF_CREATOR; } else { flags &= ~TGLCF_CREATOR; } if (DS_LVAL (DS_C->flags) & 2) { flags |= TGLCF_KICKED; } else { flags &= ~TGLCF_KICKED; } if (DS_LVAL (DS_C->flags) & 4) { flags |= TGLCF_LEFT; } else { flags &= ~TGLCF_LEFT; } if (DS_LVAL (DS_C->flags) & 8) { flags |= TGLCF_ADMINS_ENABLED; } else { flags &= ~TGLCF_ADMINS_ENABLED; } if (DS_LVAL (DS_C->flags) & 16) { flags |= TGLCF_ADMIN; } else { flags &= ~TGLCF_ADMIN; } if (DS_LVAL (DS_C->flags) & 32) { flags |= TGLCF_DEACTIVATED; } else { flags &= ~TGLCF_DEACTIVATED; } bl_do_chat (TLS, tgl_get_peer_id (C->id), DS_STR (DS_C->title), DS_C->participants_count, DS_C->date, NULL, NULL, DS_C->photo, NULL, NULL, NULL, NULL, flags ); return C; } struct tgl_chat *tglf_fetch_alloc_chat_full (struct tgl_state *TLS, struct tl_ds_messages_chat_full *DS_MCF) { if (!DS_MCF) { return NULL; } if (DS_MCF->full_chat->magic == CODE_channel_full) { return (void *)tglf_fetch_alloc_channel_full (TLS, DS_MCF); } if (DS_MCF->users) { int i; for (i = 0; i < DS_LVAL (DS_MCF->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_MCF->users->data[i]); } } if (DS_MCF->chats) { int i; for (i = 0; i < DS_LVAL (DS_MCF->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_MCF->chats->data[i]); } } struct tl_ds_chat_full *DS_CF = DS_MCF->full_chat; if (DS_CF->bot_info) { int n = DS_LVAL (DS_CF->bot_info->cnt); int i; for (i = 0; i < n; i++) { struct tl_ds_bot_info *DS_BI = DS_CF->bot_info->data[i]; tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_BI->user_id))); if (P && (P->flags & TGLCF_CREATED)) { bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, DS_BI, TGL_FLAGS_UNCHANGED ); } } } tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_CF->id)); struct tgl_chat *C = (void *)tgl_peer_get (TLS, chat_id); assert (C); bl_do_chat (TLS, tgl_get_peer_id (C->id), NULL, 0, NULL, NULL, DS_CF->participants->version, (struct tl_ds_vector *)DS_CF->participants->participants, NULL, DS_CF->chat_photo, NULL, //DS_CF->participants->admin_id, NULL, NULL, C->flags & 0xffff ); return C; } struct tgl_channel *tglf_fetch_alloc_channel (struct tgl_state *TLS, struct tl_ds_chat *DS_C) { if (!DS_C) { return NULL; } tgl_peer_id_t chat_id = TGL_MK_CHANNEL (DS_LVAL (DS_C->id)); chat_id.access_hash = DS_LVAL (DS_C->access_hash); struct tgl_channel *C = (void *)tgl_peer_get (TLS, chat_id); if (!C) { TLS->channels_allocated ++; C = talloc0 (sizeof (tgl_peer_t)); C->id = chat_id; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, (tgl_peer_t *)C, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = (tgl_peer_t *)C; } C->id = chat_id; int flags = C->flags; if (!(flags & TGLCHF_CREATED)) { flags |= TGLCHF_CREATE | TGLCHF_CREATED; } if (DS_LVAL (DS_C->flags) & 1) { flags |= TGLCHF_CREATOR; } else { flags &= ~TGLCHF_CREATOR; } if (DS_LVAL (DS_C->flags) & 2) { flags |= TGLCHF_KICKED; } else { flags &= ~TGLCHF_KICKED; } if (DS_LVAL (DS_C->flags) & 4) { flags |= TGLCHF_LEFT; } else { flags &= ~TGLCHF_LEFT; } if (DS_LVAL (DS_C->flags) & 8) { flags |= TGLCHF_EDITOR; } else { flags &= ~TGLCHF_EDITOR; } if (DS_LVAL (DS_C->flags) & 16) { flags |= TGLCHF_MODERATOR; } else { flags &= ~TGLCHF_MODERATOR; } if (DS_LVAL (DS_C->flags) & 32) { flags |= TGLCHF_BROADCAST; } else { flags &= ~TGLCHF_BROADCAST; } if (DS_LVAL (DS_C->flags) & 128) { flags |= TGLCHF_OFFICIAL; } else { flags &= ~TGLCHF_OFFICIAL; } if (DS_LVAL (DS_C->flags) & 256) { flags |= TGLCHF_MEGAGROUP; } else { flags &= ~TGLCHF_MEGAGROUP; } bl_do_channel (TLS, tgl_get_peer_id (C->id), DS_C->access_hash, DS_C->date, DS_STR (DS_C->title), DS_STR (DS_C->username), DS_C->photo, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, flags ); return C; } struct tgl_channel *tglf_fetch_alloc_channel_full (struct tgl_state *TLS, struct tl_ds_messages_chat_full *DS_MCF) { if (!DS_MCF) { return NULL; } if (DS_MCF->users) { int i; for (i = 0; i < DS_LVAL (DS_MCF->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_MCF->users->data[i]); } } if (DS_MCF->chats) { int i; for (i = 0; i < DS_LVAL (DS_MCF->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_MCF->chats->data[i]); } } struct tl_ds_chat_full *DS_CF = DS_MCF->full_chat; tgl_peer_id_t chat_id = TGL_MK_CHANNEL (DS_LVAL (DS_CF->id)); struct tgl_channel *C = (void *)tgl_peer_get (TLS, chat_id); assert (C); bl_do_channel (TLS, tgl_get_peer_id (C->id), NULL, NULL, NULL, 0, NULL, 0, NULL, DS_CF->chat_photo, NULL, DS_STR (DS_CF->about), DS_CF->participants_count, DS_CF->admins_count, DS_CF->kicked_count, DS_CF->read_inbox_max_id, TGL_FLAGS_UNCHANGED ); return C; } void tglf_fetch_photo_size (struct tgl_state *TLS, struct tgl_photo_size *S, struct tl_ds_photo_size *DS_PS) { memset (S, 0, sizeof (*S)); S->type = DS_STR_DUP (DS_PS->type); S->w = DS_LVAL (DS_PS->w); S->h = DS_LVAL (DS_PS->h); S->size = DS_LVAL (DS_PS->size); if (DS_PS->bytes) { S->size = DS_PS->bytes->len; } tglf_fetch_file_location (TLS, &S->loc, DS_PS->location); } void tglf_fetch_geo (struct tgl_state *TLS, struct tgl_geo *G, struct tl_ds_geo_point *DS_GP) { G->longitude = DS_LVAL (DS_GP->longitude); G->latitude = DS_LVAL (DS_GP->latitude); } struct tgl_photo *tglf_fetch_alloc_photo (struct tgl_state *TLS, struct tl_ds_photo *DS_P) { if (!DS_P) { return NULL; } if (DS_P->magic == CODE_photo_empty) { return NULL; } struct tgl_photo *P = tgl_photo_get (TLS, DS_LVAL (DS_P->id)); if (P) { P->refcnt ++; return P; } P = talloc0 (sizeof (*P)); P->id = DS_LVAL (DS_P->id); P->refcnt = 1; tgl_photo_insert (TLS, P); P->access_hash = DS_LVAL (DS_P->access_hash); //P->user_id = DS_LVAL (DS_P->user_id); P->date = DS_LVAL (DS_P->date); P->caption = NULL;//DS_STR_DUP (DS_P->caption); /*if (DS_P->geo) { tglf_fetch_geo (TLS, &P->geo, DS_P->geo); }*/ P->sizes_num = DS_LVAL (DS_P->sizes->cnt); P->sizes = talloc (sizeof (struct tgl_photo_size) * P->sizes_num); int i; for (i = 0; i < P->sizes_num; i++) { tglf_fetch_photo_size (TLS, &P->sizes[i], DS_P->sizes->data[i]); } return P; } struct tgl_document *tglf_fetch_alloc_video (struct tgl_state *TLS, struct tl_ds_video *DS_V) { if (!DS_V) { return NULL; } if (DS_V->magic == CODE_video_empty) { return NULL; } struct tgl_document *D = tgl_document_get (TLS, DS_LVAL (DS_V->id)); if (D) { D->refcnt ++; return D; } D = talloc0 (sizeof (*D)); D->id = DS_LVAL (DS_V->id); D->refcnt = 1; tgl_document_insert (TLS, D); D->flags = TGLDF_VIDEO; D->access_hash = DS_LVAL (DS_V->access_hash); //D->user_id = DS_LVAL (DS_V->user_id); D->date = DS_LVAL (DS_V->date); D->caption = NULL;//DS_STR_DUP (DS_V->caption); D->duration = DS_LVAL (DS_V->duration); D->mime_type = tstrdup ("video/");//DS_STR_DUP (DS_V->mime_type); D->size = DS_LVAL (DS_V->size); tglf_fetch_photo_size (TLS, &D->thumb, DS_V->thumb); D->dc_id = DS_LVAL (DS_V->dc_id); D->w = DS_LVAL (DS_V->w); D->h = DS_LVAL (DS_V->h); return D; } struct tgl_document *tglf_fetch_alloc_audio (struct tgl_state *TLS, struct tl_ds_audio *DS_A) { if (!DS_A) { return NULL; } if (DS_A->magic == CODE_audio_empty) { return NULL; } struct tgl_document *D = tgl_document_get (TLS, DS_LVAL (DS_A->id)); if (D) { D->refcnt ++; return D; } D = talloc0 (sizeof (*D)); D->id = DS_LVAL (DS_A->id); D->refcnt = 1; tgl_document_insert (TLS, D); D->flags = TGLDF_AUDIO; D->access_hash = DS_LVAL (DS_A->access_hash); //D->user_id = DS_LVAL (DS_A->user_id); D->date = DS_LVAL (DS_A->date); D->duration = DS_LVAL (DS_A->duration); D->mime_type = DS_STR_DUP (DS_A->mime_type); D->size = DS_LVAL (DS_A->size); D->dc_id = DS_LVAL (DS_A->dc_id); return D; } void tglf_fetch_document_attribute (struct tgl_state *TLS, struct tgl_document *D, struct tl_ds_document_attribute *DS_DA) { switch (DS_DA->magic) { case CODE_document_attribute_image_size: D->flags |= TGLDF_IMAGE; D->w = DS_LVAL (DS_DA->w); D->h = DS_LVAL (DS_DA->h); return; case CODE_document_attribute_animated: D->flags |= TGLDF_ANIMATED; return; case CODE_document_attribute_sticker: D->flags |= TGLDF_STICKER; return; case CODE_document_attribute_video: D->flags |= TGLDF_VIDEO; D->duration = DS_LVAL (DS_DA->duration); D->w = DS_LVAL (DS_DA->w); D->h = DS_LVAL (DS_DA->h); return; case CODE_document_attribute_audio: D->flags |= TGLDF_AUDIO; D->duration = DS_LVAL (DS_DA->duration); return; case CODE_document_attribute_filename: D->caption = DS_STR_DUP (DS_DA->file_name); return; default: assert (0); } } struct tgl_document *tglf_fetch_alloc_document (struct tgl_state *TLS, struct tl_ds_document *DS_D) { if (!DS_D) { return NULL; } if (DS_D->magic == CODE_document_empty) { return NULL; } struct tgl_document *D = tgl_document_get (TLS, DS_LVAL (DS_D->id)); if (D) { D->refcnt ++; return D; } D = talloc0 (sizeof (*D)); D->id = DS_LVAL (DS_D->id); D->refcnt = 1; tgl_document_insert (TLS, D); D->access_hash = DS_LVAL (DS_D->access_hash); //D->user_id = DS_LVAL (DS_D->user_id); D->date = DS_LVAL (DS_D->date); //D->caption = DS_STR_DUP (DS_D->file_name); D->mime_type = DS_STR_DUP (DS_D->mime_type); D->size = DS_LVAL (DS_D->size); D->dc_id = DS_LVAL (DS_D->dc_id); tglf_fetch_photo_size (TLS, &D->thumb, DS_D->thumb); if (DS_D->attributes) { int i; for (i = 0; i < DS_LVAL (DS_D->attributes->cnt); i++) { tglf_fetch_document_attribute (TLS, D, DS_D->attributes->data[i]); } } return D; } struct tgl_webpage *tglf_fetch_alloc_webpage (struct tgl_state *TLS, struct tl_ds_web_page *DS_W) { if (!DS_W) { return NULL; } struct tgl_webpage *W = tgl_webpage_get (TLS, DS_LVAL (DS_W->id)); if (W) { W->refcnt ++; } else { W = talloc0 (sizeof (*W)); W->id = DS_LVAL (DS_W->id); W->refcnt = 1; tgl_webpage_insert (TLS, W); } if (!W->url) { W->url = DS_STR_DUP (DS_W->url); } if (!W->display_url) { W->display_url = DS_STR_DUP (DS_W->display_url); } if (!W->type) { W->type = DS_STR_DUP (DS_W->type); } if (!W->site_name) { W->site_name = DS_STR_DUP (DS_W->site_name); } if (!W->title) { W->title = DS_STR_DUP (DS_W->title); } if (!W->photo) { W->photo = tglf_fetch_alloc_photo (TLS, DS_W->photo); } if (!W->description) { W->description = DS_STR_DUP (DS_W->description); } if (!W->embed_url) { W->embed_url = DS_STR_DUP (DS_W->embed_url); } if (!W->embed_type) { W->embed_type = DS_STR_DUP (DS_W->embed_type); } W->embed_width = DS_LVAL (DS_W->embed_width); W->embed_height = DS_LVAL (DS_W->embed_height); W->duration = DS_LVAL (DS_W->duration); if (!W->author) { W->author = DS_STR_DUP (DS_W->author); } return W; } void tglf_fetch_message_action (struct tgl_state *TLS, struct tgl_message_action *M, struct tl_ds_message_action *DS_MA) { if (!DS_MA) { return; } memset (M, 0, sizeof (*M)); switch (DS_MA->magic) { case CODE_message_action_empty: M->type = tgl_message_action_none; break; /*case CODE_message_action_geo_chat_create: { M->type = tgl_message_action_geo_chat_create; assert (0); } break;*/ /*case CODE_message_action_geo_chat_checkin: M->type = tgl_message_action_geo_chat_checkin; break;*/ case CODE_message_action_chat_create: { M->type = tgl_message_action_chat_create; M->title = DS_STR_DUP (DS_MA->title); M->user_num = DS_LVAL (DS_MA->users->cnt); M->users = talloc (M->user_num * 4); int i; for (i = 0; i < M->user_num; i++) { M->users[i] = DS_LVAL (DS_MA->users->data[i]); } } break; case CODE_message_action_chat_edit_title: M->type = tgl_message_action_chat_edit_title; M->new_title = DS_STR_DUP (DS_MA->title); break; case CODE_message_action_chat_edit_photo: M->type = tgl_message_action_chat_edit_photo; M->photo = tglf_fetch_alloc_photo (TLS, DS_MA->photo); break; case CODE_message_action_chat_delete_photo: M->type = tgl_message_action_chat_delete_photo; break; case CODE_message_action_chat_add_user: M->type = tgl_message_action_chat_add_users; M->user_num = DS_LVAL (DS_MA->users->cnt); M->users = talloc (4 * M->user_num); { int i; for (i = 0; i < M->user_num; i++) { M->users[i] = DS_LVAL (DS_MA->users->data[i]); } } break; case CODE_message_action_chat_delete_user: M->type = tgl_message_action_chat_delete_user; M->user = DS_LVAL (DS_MA->user_id); break; case CODE_message_action_chat_joined_by_link: M->type = tgl_message_action_chat_add_user_by_link; M->user = DS_LVAL (DS_MA->inviter_id); break; case CODE_message_action_channel_create: M->type = tgl_message_action_channel_create; M->title = DS_STR_DUP (DS_MA->title); break; case CODE_message_action_chat_migrate_to: M->type = tgl_message_action_migrated_to; break; case CODE_message_action_channel_migrate_from: M->type = tgl_message_action_migrated_from; M->title = DS_STR_DUP (DS_MA->title); break; default: assert (0); } } struct tgl_message *tglf_fetch_alloc_message_short (struct tgl_state *TLS, struct tl_ds_updates *DS_U) { tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user_id))); if (!P || !(P->flags & TGLPF_CREATED)) { tgl_do_get_difference (TLS, 0, 0, 0); return NULL; } tgl_message_id_t msg_id = tgl_peer_id_to_msg_id (P->id, DS_LVAL (DS_U->id)); struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (!M) { M = talloc0 (sizeof (*M)); M->permanent_id = msg_id; tglm_message_insert_tree (TLS, M); TLS->messages_allocated ++; assert (tgl_message_get (TLS, &msg_id) == M); } int flags = M->flags & 0xffff; if (M->flags & TGLMF_PENDING) { M->flags ^= TGLMF_PENDING; } if (!(flags & TGLMF_CREATED)) { flags |= TGLMF_CREATE | TGLMF_CREATED; } int f = DS_LVAL (DS_U->flags); if (f & 1) { flags |= TGLMF_UNREAD; } if (f & 2) { flags |= TGLMF_OUT; } if (f & 16) { flags |= TGLMF_MENTION; } struct tl_ds_message_media A; A.magic = CODE_message_media_empty; tgl_peer_id_t our_id = TLS->our_id; tgl_peer_id_t peer_id = P->id; tgl_peer_id_t fwd_from_id; if (DS_U->fwd_from_id) { fwd_from_id = tglf_fetch_peer_id (TLS, DS_U->fwd_from_id); } else { fwd_from_id = TGL_MK_USER (0); } bl_do_edit_message (TLS, &msg_id, (f & 2) ? &our_id : &peer_id, (f & 2) ? &peer_id : &our_id, DS_U->fwd_from_id ? &fwd_from_id : NULL, DS_U->fwd_date, DS_U->date, DS_STR (DS_U->message), &A, NULL, DS_U->reply_to_msg_id, NULL, (void *)DS_U->entities, flags ); return M; } struct tgl_message *tglf_fetch_alloc_message_short_chat (struct tgl_state *TLS, struct tl_ds_updates *DS_U) { tgl_peer_t *F = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->from_id))); if (!F || !(F->flags & TGLPF_CREATED)) { tgl_do_get_difference (TLS, 0, 0, 0); return NULL; } tgl_peer_t *T = tgl_peer_get (TLS, TGL_MK_CHAT (DS_LVAL (DS_U->chat_id))); if (!T || !(T->flags & TGLPF_CREATED)) { tgl_do_get_difference (TLS, 0, 0, 0); return NULL; } tgl_message_id_t msg_id = tgl_peer_id_to_msg_id (T->id, DS_LVAL (DS_U->id)); struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (!M) { M = talloc0 (sizeof (*M)); M->permanent_id = msg_id; tglm_message_insert_tree (TLS, M); TLS->messages_allocated ++; } int flags = M->flags & 0xffff; if (M->flags & TGLMF_PENDING) { M->flags ^= TGLMF_PENDING; } if (!(flags & TGLMF_CREATED)) { flags |= TGLMF_CREATE | TGLMF_CREATED; } int f = DS_LVAL (DS_U->flags); if (f & 1) { flags |= TGLMF_UNREAD; } if (f & 2) { flags |= TGLMF_OUT; } if (f & 16) { flags |= TGLMF_MENTION; } struct tl_ds_message_media A; A.magic = CODE_message_media_empty; tgl_peer_id_t from_id = F->id; tgl_peer_id_t to_id = T->id; tgl_peer_id_t fwd_from_id; if (DS_U->fwd_from_id) { fwd_from_id = tglf_fetch_peer_id (TLS, DS_U->fwd_from_id); } else { fwd_from_id = TGL_MK_USER (0); } bl_do_edit_message (TLS, &msg_id, &from_id, &to_id, DS_U->fwd_from_id ? &fwd_from_id : NULL, DS_U->fwd_date, DS_U->date, DS_STR (DS_U->message), &A, NULL, DS_U->reply_to_msg_id, NULL, NULL, flags ); return M; } void tglf_fetch_message_media (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_message_media *DS_MM) { if (!DS_MM) { return; } memset (M, 0, sizeof (*M)); switch (DS_MM->magic) { case CODE_message_media_empty: M->type = tgl_message_media_none; break; case CODE_message_media_photo: case CODE_message_media_photo_l27: M->type = tgl_message_media_photo; M->photo = tglf_fetch_alloc_photo (TLS, DS_MM->photo); M->caption = DS_STR_DUP (DS_MM->caption); break; case CODE_message_media_video: case CODE_message_media_video_l27: M->type = tgl_message_media_video; M->document = tglf_fetch_alloc_video (TLS, DS_MM->video); M->caption = DS_STR_DUP (DS_MM->caption); break; case CODE_message_media_audio: M->type = tgl_message_media_audio; M->document = tglf_fetch_alloc_audio (TLS, DS_MM->audio); M->caption = DS_STR_DUP (DS_MM->caption); break; case CODE_message_media_document: M->type = tgl_message_media_document; M->document = tglf_fetch_alloc_document (TLS, DS_MM->document); M->caption = DS_STR_DUP (DS_MM->caption); break; case CODE_message_media_geo: M->type = tgl_message_media_geo; tglf_fetch_geo (TLS, &M->geo, DS_MM->geo); break; case CODE_message_media_contact: M->type = tgl_message_media_contact; M->phone = DS_STR_DUP (DS_MM->phone_number); M->first_name = DS_STR_DUP (DS_MM->first_name); M->last_name = DS_STR_DUP (DS_MM->last_name); M->user_id = DS_LVAL (DS_MM->user_id); break; case CODE_message_media_web_page: M->type = tgl_message_media_webpage; M->webpage = tglf_fetch_alloc_webpage (TLS, DS_MM->webpage); break; case CODE_message_media_venue: M->type = tgl_message_media_venue; tglf_fetch_geo (TLS, &M->venue.geo, DS_MM->geo); M->venue.title = DS_STR_DUP (DS_MM->title); M->venue.address = DS_STR_DUP (DS_MM->address); M->venue.provider = DS_STR_DUP (DS_MM->provider); M->venue.venue_id = DS_STR_DUP (DS_MM->venue_id); break; case CODE_message_media_unsupported: M->type = tgl_message_media_unsupported; break; default: assert (0); } } void tglf_fetch_message_media_encrypted (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_decrypted_message_media *DS_DMM) { if (!DS_DMM) { return; } memset (M, 0, sizeof (*M)); switch (DS_DMM->magic) { case CODE_decrypted_message_media_empty: M->type = tgl_message_media_none; //M->type = CODE_message_media_empty; break; case CODE_decrypted_message_media_photo: case CODE_decrypted_message_media_video: case CODE_decrypted_message_media_video_l12: case CODE_decrypted_message_media_document: case CODE_decrypted_message_media_audio: //M->type = CODE_decrypted_message_media_video; M->type = tgl_message_media_document_encr; M->encr_document = talloc0 (sizeof (*M->encr_document)); switch (DS_DMM->magic) { case CODE_decrypted_message_media_photo: M->encr_document->flags = TGLDF_IMAGE; break; case CODE_decrypted_message_media_video: case CODE_decrypted_message_media_video_l12: M->encr_document->flags = TGLDF_VIDEO; break; case CODE_decrypted_message_media_document: //M->encr_document->flags = TGLDF_DOCUMENT; break; case CODE_decrypted_message_media_audio: M->encr_document->flags = TGLDF_AUDIO; break; } M->encr_document->w = DS_LVAL (DS_DMM->w); M->encr_document->h = DS_LVAL (DS_DMM->h); M->encr_document->size = DS_LVAL (DS_DMM->size); M->encr_document->duration = DS_LVAL (DS_DMM->duration); M->encr_document->mime_type = DS_STR_DUP (DS_DMM->mime_type); M->encr_document->key = talloc (32); str_to_32 (M->encr_document->key, DS_STR (DS_DMM->key)); M->encr_document->iv = talloc (32); str_to_32 (M->encr_document->iv, DS_STR (DS_DMM->iv)); break; case CODE_decrypted_message_media_geo_point: M->type = tgl_message_media_geo; M->geo.latitude = DS_LVAL (DS_DMM->latitude); M->geo.longitude = DS_LVAL (DS_DMM->longitude); break; case CODE_decrypted_message_media_contact: M->type = tgl_message_media_contact; M->phone = DS_STR_DUP (DS_DMM->phone_number); M->first_name = DS_STR_DUP (DS_DMM->first_name); M->last_name = DS_STR_DUP (DS_DMM->last_name); M->user_id = DS_LVAL (DS_DMM->user_id); break; default: assert (0); } } void tglf_fetch_message_action_encrypted (struct tgl_state *TLS, struct tgl_message_action *M, struct tl_ds_decrypted_message_action *DS_DMA) { if (!DS_DMA) { return; } switch (DS_DMA->magic) { case CODE_decrypted_message_action_set_message_t_t_l: M->type = tgl_message_action_set_message_ttl; M->ttl = DS_LVAL (DS_DMA->ttl_seconds); break; case CODE_decrypted_message_action_read_messages: M->type = tgl_message_action_read_messages; { M->read_cnt = DS_LVAL (DS_DMA->random_ids->cnt); int i; for (i = 0; i < M->read_cnt; i++) { tgl_message_id_t id; id.peer_type = TGL_PEER_RANDOM_ID; id.id = DS_LVAL (DS_DMA->random_ids->data[i]); struct tgl_message *N = tgl_message_get (TLS, &id); if (N) { N->flags &= ~TGLMF_UNREAD; } } } break; case CODE_decrypted_message_action_delete_messages: M->type = tgl_message_action_delete_messages; break; case CODE_decrypted_message_action_screenshot_messages: M->type = tgl_message_action_screenshot_messages; { M->screenshot_cnt = DS_LVAL (DS_DMA->random_ids->cnt); } break; case CODE_decrypted_message_action_notify_layer: M->type = tgl_message_action_notify_layer; M->layer = DS_LVAL (DS_DMA->layer); break; case CODE_decrypted_message_action_flush_history: M->type = tgl_message_action_flush_history; break; case CODE_decrypted_message_action_typing: M->type = tgl_message_action_typing; M->typing = tglf_fetch_typing (DS_DMA->action); break; case CODE_decrypted_message_action_resend: M->type = tgl_message_action_resend; M->start_seq_no = DS_LVAL (DS_DMA->start_seq_no); M->end_seq_no = DS_LVAL (DS_DMA->end_seq_no); break; case CODE_decrypted_message_action_noop: M->type = tgl_message_action_noop; break; case CODE_decrypted_message_action_request_key: M->type = tgl_message_action_request_key; M->exchange_id = DS_LVAL (DS_DMA->exchange_id); M->g_a = talloc (256); str_to_256 (M->g_a, DS_STR (DS_DMA->g_a)); break; case CODE_decrypted_message_action_accept_key: M->type = tgl_message_action_accept_key; M->exchange_id = DS_LVAL (DS_DMA->exchange_id); M->g_a = talloc (256); str_to_256 (M->g_a, DS_STR (DS_DMA->g_b)); M->key_fingerprint = DS_LVAL (DS_DMA->key_fingerprint); break; case CODE_decrypted_message_action_commit_key: M->type = tgl_message_action_commit_key; M->exchange_id = DS_LVAL (DS_DMA->exchange_id); M->key_fingerprint = DS_LVAL (DS_DMA->key_fingerprint); break; case CODE_decrypted_message_action_abort_key: M->type = tgl_message_action_abort_key; M->exchange_id = DS_LVAL (DS_DMA->exchange_id); break; default: assert (0); } } void tglf_fetch_message_entity (struct tgl_state *TLS, struct tgl_message_entity *E, struct tl_ds_message_entity *DS_ME) { E->start = DS_LVAL (DS_ME->offset); E->length = DS_LVAL (DS_ME->length); switch (DS_ME->magic) { case CODE_message_entity_unknown: E->type = tgl_message_entity_unknown; break; case CODE_message_entity_mention: E->type = tgl_message_entity_mention; break; case CODE_message_entity_hashtag: E->type = tgl_message_entity_hashtag; break; case CODE_message_entity_bot_command: E->type = tgl_message_entity_bot_command; break; case CODE_message_entity_url: E->type = tgl_message_entity_url; break; case CODE_message_entity_email: E->type = tgl_message_entity_email; break; case CODE_message_entity_bold: E->type = tgl_message_entity_bold; break; case CODE_message_entity_italic: E->type = tgl_message_entity_italic; break; case CODE_message_entity_code: E->type = tgl_message_entity_code; break; case CODE_message_entity_pre: E->type = tgl_message_entity_pre; break; case CODE_message_entity_text_url: E->type = tgl_message_entity_text_url; E->extra = DS_STR_DUP (DS_ME->url); break; default: assert (0); } } void tglf_fetch_message_entities (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_vector *DS) { M->entities_num = DS_LVAL (DS->f1); M->entities = talloc0 (M->entities_num * sizeof (struct tgl_message_entity)); int i; for (i = 0; i < M->entities_num; i++) { struct tl_ds_message_entity *D = DS->f2[i]; tglf_fetch_message_entity (TLS, &M->entities[i], D); } } struct tgl_message *tglf_fetch_alloc_message (struct tgl_state *TLS, struct tl_ds_message *DS_M, int *new_msg) { if (new_msg) { *new_msg = 0; } //assert (0); if (!DS_M || DS_M->magic == CODE_message_empty) { vlogprintf (E_NOTICE, "empty message\n"); return NULL; } tgl_peer_id_t to_id = tglf_fetch_peer_id (TLS, DS_M->to_id); tgl_peer_t *T = tgl_peer_get (TLS, to_id); if (!T || !(T->flags & TGLPF_CREATED)) { tgl_do_get_difference (TLS, 0, 0, 0); vlogprintf (E_NOTICE, "unknown to_id\n"); return NULL; } tgl_peer_t *P = T; tgl_peer_t *F = NULL; if (DS_M->from_id) { F = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_M->from_id))); if (!F || !(F->flags & TGLPF_CREATED)) { tgl_do_get_difference (TLS, 0, 0, 0); vlogprintf (E_NOTICE, "unknown from_id %d\n", DS_LVAL (DS_M->from_id)); return NULL; } if (!tgl_cmp_peer_id (to_id, TLS->our_id)) { P = F; } } tgl_peer_t *FF = NULL; if (DS_M->fwd_from_id) { tgl_peer_id_t FF_id = tglf_fetch_peer_id (TLS, DS_M->fwd_from_id); FF = tgl_peer_get (TLS, FF_id); if (!FF) { tgl_do_get_difference (TLS, 0, 0, 0); vlogprintf (E_NOTICE, "unknown fwd_id\n"); return NULL; } } tgl_message_id_t msg_id = tgl_peer_id_to_msg_id (P->id, DS_LVAL (DS_M->id)); struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (!M) { M = talloc0 (sizeof (*M)); M->permanent_id = msg_id; tglm_message_insert_tree (TLS, M); TLS->messages_allocated ++; assert (tgl_message_get (TLS, &msg_id) == M); } int new = !(M->flags & TGLMF_CREATED); if (new_msg) { *new_msg = new; } if (new) { int flags = 0; if (DS_LVAL (DS_M->flags) & 1) { flags |= TGLMF_UNREAD; } if (DS_LVAL (DS_M->flags) & 2) { flags |= TGLMF_OUT; } if (DS_LVAL (DS_M->flags) & 16) { flags |= TGLMF_MENTION; } tgl_peer_id_t from_id; if (DS_M->from_id) { from_id = F->id; } else { from_id = TGL_MK_USER (0); } tgl_peer_id_t to_id = T->id; tgl_peer_id_t fwd_from_id; if (DS_M->fwd_from_id) { fwd_from_id = FF->id; } else { fwd_from_id = TGL_MK_USER (0); } bl_do_edit_message (TLS, &msg_id, DS_M->from_id ? &from_id : NULL, &to_id, DS_M->fwd_from_id ? &fwd_from_id : NULL, DS_M->fwd_date, DS_M->date, DS_STR (DS_M->message), DS_M->media, DS_M->action, DS_M->reply_to_msg_id, DS_M->reply_markup, (void *)DS_M->entities, flags | TGLMF_CREATE | TGLMF_CREATED ); } return M; } static int *decr_ptr; static int *decr_end; static int decrypt_encrypted_message (struct tgl_secret_chat *E) { int *msg_key = decr_ptr; decr_ptr += 4; assert (decr_ptr < decr_end); static unsigned char sha1a_buffer[20]; static unsigned char sha1b_buffer[20]; static unsigned char sha1c_buffer[20]; static unsigned char sha1d_buffer[20]; static unsigned char buf[64]; int *e_key = E->exchange_state != tgl_sce_committed ? E->key : E->exchange_key; memcpy (buf, msg_key, 16); memcpy (buf + 16, e_key, 32); TGLC_sha1 (buf, 48, sha1a_buffer); memcpy (buf, e_key + 8, 16); memcpy (buf + 16, msg_key, 16); memcpy (buf + 32, e_key + 12, 16); TGLC_sha1 (buf, 48, sha1b_buffer); memcpy (buf, e_key + 16, 32); memcpy (buf + 32, msg_key, 16); TGLC_sha1 (buf, 48, sha1c_buffer); memcpy (buf, msg_key, 16); memcpy (buf + 16, e_key + 24, 32); TGLC_sha1 (buf, 48, sha1d_buffer); static unsigned char key[32]; memcpy (key, sha1a_buffer + 0, 8); memcpy (key + 8, sha1b_buffer + 8, 12); memcpy (key + 20, sha1c_buffer + 4, 12); static unsigned char iv[32]; memcpy (iv, sha1a_buffer + 8, 12); memcpy (iv + 12, sha1b_buffer + 0, 8); memcpy (iv + 20, sha1c_buffer + 16, 4); memcpy (iv + 24, sha1d_buffer + 0, 8); TGLC_aes_key aes_key; TGLC_aes_set_decrypt_key (key, 256, &aes_key); TGLC_aes_ige_encrypt ((void *)decr_ptr, (void *)decr_ptr, 4 * (decr_end - decr_ptr), &aes_key, iv, 0); memset (&aes_key, 0, sizeof (aes_key)); int x = *(decr_ptr); if (x < 0 || (x & 3)) { return -1; } assert (x >= 0 && !(x & 3)); TGLC_sha1 ((void *)decr_ptr, 4 + x, sha1a_buffer); if (memcmp (sha1a_buffer + 4, msg_key, 16)) { return -1; } return 0; } struct tgl_message *tglf_fetch_encrypted_message (struct tgl_state *TLS, struct tl_ds_encrypted_message *DS_EM) { if (!DS_EM) { return NULL; } tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (DS_LVAL (DS_EM->chat_id))); if (!P || P->encr_chat.state != sc_ok) { vlogprintf (E_WARNING, "Encrypted message to unknown chat. Dropping\n"); return NULL; } tgl_message_id_t msg_id = tgl_peer_id_to_msg_id (P->id, DS_LVAL (DS_EM->random_id)); struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (!M) { M = talloc0 (sizeof (*M)); M->permanent_id = msg_id; tglm_message_insert_tree (TLS, M); TLS->messages_allocated ++; assert (tgl_message_get (TLS, &msg_id) == M); } int new = !(M->flags & TGLMF_CREATED); if (!new) { return M; } decr_ptr = (void *)DS_EM->bytes->data; decr_end = decr_ptr + (DS_EM->bytes->len / 4); if (P->encr_chat.exchange_state == tgl_sce_committed && P->encr_chat.key_fingerprint == *(long long *)decr_ptr) { tgl_do_confirm_exchange (TLS, (void *)P, 0); assert (P->encr_chat.exchange_state == tgl_sce_none); } long long key_fingerprint = P->encr_chat.exchange_state != tgl_sce_committed ? P->encr_chat.key_fingerprint : P->encr_chat.exchange_key_fingerprint; if (*(long long *)decr_ptr != key_fingerprint) { vlogprintf (E_WARNING, "Encrypted message with bad fingerprint to chat %s\n", P->print_name); return M; } decr_ptr += 2; if (decrypt_encrypted_message (&P->encr_chat) < 0) { vlogprintf (E_WARNING, "can not decrypt message\n"); return M; } int *save_in_ptr = in_ptr; int *save_in_end = in_end; in_ptr = decr_ptr; int ll = *in_ptr; in_end = in_ptr + ll / 4 + 1; assert (fetch_int () == ll); if (skip_type_decrypted_message_layer (TYPE_TO_PARAM (decrypted_message_layer)) < 0 || in_ptr != in_end) { vlogprintf (E_WARNING, "can not fetch message\n"); in_ptr = save_in_ptr; in_end = save_in_end; return M; } in_ptr = decr_ptr; assert (fetch_int () == ll); struct tl_ds_decrypted_message_layer *DS_DML = fetch_ds_type_decrypted_message_layer (TYPE_TO_PARAM (decrypted_message_layer)); assert (DS_DML); in_ptr = save_in_ptr; in_end = save_in_end; //bl_do_encr_chat_set_layer (TLS, (void *)P, DS_LVAL (DS_DML->layer)); bl_do_encr_chat (TLS, tgl_get_peer_id (P->id), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, DS_DML->layer, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED, NULL, 0 ); int in_seq_no = DS_LVAL (DS_DML->out_seq_no); int out_seq_no = DS_LVAL (DS_DML->in_seq_no); if (in_seq_no / 2 != P->encr_chat.in_seq_no) { vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no); free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer)); return M; } if ((in_seq_no & 1) != 1 - (P->encr_chat.admin_id == tgl_get_peer_id (TLS->our_id)) || (out_seq_no & 1) != (P->encr_chat.admin_id == tgl_get_peer_id (TLS->our_id))) { vlogprintf (E_WARNING, "Bad msg admin\n"); free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer)); return M; } if (out_seq_no / 2 > P->encr_chat.out_seq_no) { vlogprintf (E_WARNING, "In seq no is bigger than our's out seq no (out_seq_no = %d, our_out_seq_no = %d). Drop\n", out_seq_no / 2, P->encr_chat.out_seq_no); free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer)); return M; } if (out_seq_no / 2 < P->encr_chat.last_in_seq_no) { vlogprintf (E_WARNING, "Clients in_seq_no decreased (out_seq_no = %d, last_out_seq_no = %d). Drop\n", out_seq_no / 2, P->encr_chat.last_in_seq_no); free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer)); return M; } struct tl_ds_decrypted_message *DS_DM = DS_DML->message; if (M->permanent_id.id != DS_LVAL (DS_DM->random_id)) { vlogprintf (E_ERROR, "Incorrect message: id = %" INT64_PRINTF_MODIFIER "d, new_id = %" INT64_PRINTF_MODIFIER "d\n", M->permanent_id.id, DS_LVAL (DS_DM->random_id)); free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer)); return M; } tgl_peer_id_t from_id = TGL_MK_USER (P->encr_chat.user_id); bl_do_edit_message_encr (TLS, &M->permanent_id, &from_id, &P->id, DS_EM->date, DS_STR (DS_DM->message), DS_DM->media, DS_DM->action, DS_EM->file, TGLMF_CREATE | TGLMF_CREATED | TGLMF_ENCRYPTED); if (in_seq_no >= 0 && out_seq_no >= 0) { //bl_do_encr_chat_update_seq (TLS, (void *)P, in_seq_no / 2 + 1, out_seq_no / 2); in_seq_no = in_seq_no / 2 + 1; out_seq_no = out_seq_no / 2; bl_do_encr_chat (TLS, tgl_get_peer_id (P->id), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &in_seq_no, &out_seq_no, NULL, NULL, TGL_FLAGS_UNCHANGED, NULL, 0 ); assert (P->encr_chat.in_seq_no == in_seq_no); } free_ds_type_decrypted_message_layer (DS_DML, TYPE_TO_PARAM(decrypted_message_layer)); return M; } void tglf_fetch_encrypted_message_file (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_encrypted_file *DS_EF) { if (DS_EF->magic == CODE_encrypted_file_empty) { assert (M->type != tgl_message_media_document_encr); } else { assert (M->type == tgl_message_media_document_encr); assert (M->encr_document); M->encr_document->id = DS_LVAL (DS_EF->id); M->encr_document->access_hash = DS_LVAL (DS_EF->access_hash); if (!M->encr_document->size) { M->encr_document->size = DS_LVAL (DS_EF->size); } M->encr_document->dc_id = DS_LVAL (DS_EF->dc_id); M->encr_document->key_fingerprint = DS_LVAL (DS_EF->key_fingerprint); } } static int id_cmp (struct tgl_message *M1, struct tgl_message *M2) { if (M1->permanent_id.peer_type < M2->permanent_id.peer_type) { return -1; } if (M1->permanent_id.peer_type > M2->permanent_id.peer_type) { return 1; } if (M1->permanent_id.peer_id < M2->permanent_id.peer_id) { return -1; } if (M1->permanent_id.peer_id > M2->permanent_id.peer_id) { return 1; } if (M1->permanent_id.id < M2->permanent_id.id) { return -1; } if (M1->permanent_id.id > M2->permanent_id.id) { return 1; } else { return 0; } } static void increase_peer_size (struct tgl_state *TLS) { if (TLS->peer_num == TLS->peer_size) { int new_size = TLS->peer_size ? 2 * TLS->peer_size : 10; int old_size = TLS->peer_size; if (old_size) { TLS->Peers = trealloc (TLS->Peers, old_size * sizeof (void *), new_size * sizeof (void *)); } else { TLS->Peers = talloc (new_size * sizeof (void *)); } TLS->peer_size = new_size; } } struct tgl_message *tglf_fetch_alloc_encrypted_message (struct tgl_state *TLS, struct tl_ds_encrypted_message *DS_EM) { struct tgl_message *M = tglf_fetch_encrypted_message (TLS, DS_EM); if (!M) { return M; } if (M->flags & TGLMF_CREATED) { tgl_peer_t *_E = tgl_peer_get (TLS, M->to_id); assert (_E); struct tgl_secret_chat *E = &_E->encr_chat; if (M->action.type == tgl_message_action_request_key) { if (E->exchange_state == tgl_sce_none || (E->exchange_state == tgl_sce_requested && E->exchange_id > M->action.exchange_id )) { tgl_do_accept_exchange (TLS, E, M->action.exchange_id, M->action.g_a); } else { vlogprintf (E_WARNING, "Exchange: Incorrect state (received request, state = %d)\n", E->exchange_state); } } if (M->action.type == tgl_message_action_accept_key) { if (E->exchange_state == tgl_sce_requested && E->exchange_id == M->action.exchange_id) { tgl_do_commit_exchange (TLS, E, M->action.g_a); } else { vlogprintf (E_WARNING, "Exchange: Incorrect state (received accept, state = %d)\n", E->exchange_state); } } if (M->action.type == tgl_message_action_commit_key) { if (E->exchange_state == tgl_sce_accepted && E->exchange_id == M->action.exchange_id) { tgl_do_confirm_exchange (TLS, E, 1); } else { vlogprintf (E_WARNING, "Exchange: Incorrect state (received commit, state = %d)\n", E->exchange_state); } } if (M->action.type == tgl_message_action_abort_key) { if (E->exchange_state != tgl_sce_none && E->exchange_id == M->action.exchange_id) { tgl_do_abort_exchange (TLS, E); } else { vlogprintf (E_WARNING, "Exchange: Incorrect state (received abort, state = %d)\n", E->exchange_state); } } if (M->action.type == tgl_message_action_notify_layer) { bl_do_encr_chat (TLS, tgl_get_peer_id (E->id), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &M->action.layer, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED, NULL, 0 ); } if (M->action.type == tgl_message_action_set_message_ttl) { //bl_do_encr_chat_set_ttl (TLS, E, M->action.ttl); bl_do_encr_chat (TLS, tgl_get_peer_id (E->id), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &M->action.ttl, NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED, NULL, 0 ); } } return M; } struct tgl_bot_info *tglf_fetch_alloc_bot_info (struct tgl_state *TLS, struct tl_ds_bot_info *DS_BI) { if (!DS_BI || DS_BI->magic == CODE_bot_info_empty) { return NULL; } struct tgl_bot_info *B = talloc (sizeof (*B)); B->version = DS_LVAL (DS_BI->version); B->share_text = DS_STR_DUP (DS_BI->share_text); B->description = DS_STR_DUP (DS_BI->description); B->commands_num = DS_LVAL (DS_BI->commands->cnt); B->commands = talloc (sizeof (struct tgl_bot_command) * B->commands_num); int i; for (i = 0; i < B->commands_num; i++) { struct tl_ds_bot_command *BC = DS_BI->commands->data[i]; B->commands[i].command = DS_STR_DUP (BC->command); B->commands[i].description = DS_STR_DUP (BC->description); } return B; } struct tgl_message_reply_markup *tglf_fetch_alloc_reply_markup (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_reply_markup *DS_RM) { if (!DS_RM) { return NULL; } struct tgl_message_reply_markup *R = talloc0 (sizeof (*R)); R->flags = DS_LVAL (DS_RM->flags); R->refcnt = 1; R->rows = DS_RM->rows ? DS_LVAL (DS_RM->rows->cnt) : 0; int total = 0; R->row_start = talloc ((R->rows + 1) * 4); R->row_start[0] = 0; int i; for (i = 0; i < R->rows; i++) { struct tl_ds_keyboard_button_row *DS_K = DS_RM->rows->data[i]; total += DS_LVAL (DS_K->buttons->cnt); R->row_start[i + 1] = total; } R->buttons = talloc (sizeof (void *) * total); int r = 0; for (i = 0; i < R->rows; i++) { struct tl_ds_keyboard_button_row *DS_K = DS_RM->rows->data[i]; int j; for (j = 0; j < DS_LVAL (DS_K->buttons->cnt); j++) { struct tl_ds_keyboard_button *DS_KB = DS_K->buttons->data[j]; R->buttons[r ++] = DS_STR_DUP (DS_KB->text); } } assert (r == total); return R; } /* }}} */ void tglp_insert_encrypted_chat (struct tgl_state *TLS, tgl_peer_t *P) { TLS->encr_chats_allocated ++; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = P; } void tglp_insert_user (struct tgl_state *TLS, tgl_peer_t *P) { TLS->users_allocated ++; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = P; } void tglp_insert_chat (struct tgl_state *TLS, tgl_peer_t *P) { TLS->chats_allocated ++; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = P; } void tglp_insert_channel (struct tgl_state *TLS, tgl_peer_t *P) { TLS->channels_allocated ++; TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = P; } void tgl_insert_empty_user (struct tgl_state *TLS, int uid) { tgl_peer_id_t id = TGL_MK_USER (uid); if (tgl_peer_get (TLS, id)) { return; } tgl_peer_t *P = talloc0 (sizeof (*P)); P->id = id; tglp_insert_user (TLS, P); } void tgl_insert_empty_chat (struct tgl_state *TLS, int cid) { tgl_peer_id_t id = TGL_MK_CHAT (cid); if (tgl_peer_get (TLS, id)) { return; } tgl_peer_t *P = talloc0 (sizeof (*P)); P->id = id; tglp_insert_chat (TLS, P); } /* {{{ Free */ void tgls_free_photo_size (struct tgl_state *TLS, struct tgl_photo_size *S) { tfree_str (S->type); if (S->data) { tfree (S->data, S->size); } } void tgls_free_photo (struct tgl_state *TLS, struct tgl_photo *P) { if (--P->refcnt) { assert (P->refcnt > 0); return; } if (P->caption) { tfree_str (P->caption); } if (P->sizes) { int i; for (i = 0; i < P->sizes_num; i++) { tgls_free_photo_size (TLS, &P->sizes[i]); } tfree (P->sizes, sizeof (struct tgl_photo_size) * P->sizes_num); } TLS->photo_tree = tree_delete_photo (TLS->photo_tree, P); tfree (P, sizeof (*P)); } void tgls_free_document (struct tgl_state *TLS, struct tgl_document *D) { if (--D->refcnt) { assert (D->refcnt); return; } if (D->mime_type) { tfree_str (D->mime_type);} if (D->caption) {tfree_str (D->caption);} tgls_free_photo_size (TLS, &D->thumb); TLS->document_tree = tree_delete_document (TLS->document_tree, D); tfree (D, sizeof (*D)); } void tgls_free_webpage (struct tgl_state *TLS, struct tgl_webpage *W) { if (--W->refcnt) { assert (W->refcnt); return; } if (W->url) { tfree_str (W->url); } if (W->display_url) { tfree_str (W->display_url); } if (W->title) { tfree_str (W->title); } if (W->site_name) { tfree_str (W->site_name); } if (W->type) { tfree_str (W->type); } if (W->description) { tfree_str (W->description); } if (W->photo) { tgls_free_photo (TLS, W->photo); } if (W->embed_url) { tfree_str (W->embed_url); } if (W->embed_type) { tfree_str (W->embed_type); } if (W->author) { tfree_str (W->author); } TLS->webpage_tree = tree_delete_webpage (TLS->webpage_tree, W); tfree (W, sizeof (*W)); } void tgls_free_message_media (struct tgl_state *TLS, struct tgl_message_media *M) { switch (M->type) { case tgl_message_media_none: case tgl_message_media_geo: return; case tgl_message_media_photo: tgls_free_photo (TLS, M->photo); if (M->caption) { tfree_str (M->caption); } M->photo = NULL; return; case tgl_message_media_contact: tfree_str (M->phone); tfree_str (M->first_name); tfree_str (M->last_name); return; case tgl_message_media_document: case tgl_message_media_video: case tgl_message_media_audio: tgls_free_document (TLS, M->document); if (M->caption) { tfree_str (M->caption); } return; case tgl_message_media_unsupported: return; case tgl_message_media_document_encr: tfree_secure (M->encr_document->key, 32); tfree_secure (M->encr_document->iv, 32); tfree (M->encr_document, sizeof (*M->encr_document)); return; case tgl_message_media_webpage: tgls_free_webpage (TLS, M->webpage); return; case tgl_message_media_venue: if (M->venue.title) { tfree_str (M->venue.title); } if (M->venue.address) { tfree_str (M->venue.address); } if (M->venue.provider) { tfree_str (M->venue.provider); } if (M->venue.venue_id) { tfree_str (M->venue.venue_id); } return; default: vlogprintf (E_ERROR, "type = 0x%08x\n", M->type); assert (0); } } void tgls_free_message_action (struct tgl_state *TLS, struct tgl_message_action *M) { switch (M->type) { case tgl_message_action_none: return; case tgl_message_action_chat_create: tfree_str (M->title); tfree (M->users, M->user_num * 4); return; case tgl_message_action_chat_edit_title: tfree_str (M->new_title); return; case tgl_message_action_chat_edit_photo: tgls_free_photo (TLS, M->photo); M->photo = NULL; return; case tgl_message_action_chat_add_users: tfree (M->users, M->user_num * 4); return; case tgl_message_action_chat_delete_photo: case tgl_message_action_chat_add_user_by_link: case tgl_message_action_chat_delete_user: case tgl_message_action_geo_chat_create: case tgl_message_action_geo_chat_checkin: case tgl_message_action_set_message_ttl: case tgl_message_action_read_messages: case tgl_message_action_delete_messages: case tgl_message_action_screenshot_messages: case tgl_message_action_flush_history: case tgl_message_action_typing: case tgl_message_action_resend: case tgl_message_action_notify_layer: case tgl_message_action_commit_key: case tgl_message_action_abort_key: case tgl_message_action_noop: case tgl_message_action_migrated_to: return; case tgl_message_action_request_key: case tgl_message_action_accept_key: tfree (M->g_a, 256); return; case tgl_message_action_channel_create: case tgl_message_action_migrated_from: tfree_str (M->title); return; /* default: vlogprintf (E_ERROR, "type = 0x%08x\n", M->type); assert (0);*/ } vlogprintf (E_ERROR, "type = 0x%08x\n", M->type); assert (0); } void tgls_free_message_entity (struct tgl_state *TLS, struct tgl_message_entity *E) { if (E->extra) { tfree_str (E->extra); } } void tgls_clear_message (struct tgl_state *TLS, struct tgl_message *M) { if (!(M->flags & TGLMF_SERVICE)) { if (M->message) { tfree (M->message, M->message_len + 1); } tgls_free_message_media (TLS, &M->media); } else { tgls_free_message_action (TLS, &M->action); } int i; for (i = 0; i < M->entities_num; i++) { tgls_free_message_entity (TLS, &M->entities[i]); } tfree (M->entities, M->entities_num * sizeof (struct tgl_message_entity)); } void tgls_free_reply_markup (struct tgl_state *TLS, struct tgl_message_reply_markup *R) { if (!--R->refcnt) { int i; for (i = 0; i < R->row_start[R->rows]; i++) { tfree_str (R->buttons[i]); } tfree (R->buttons, R->row_start[R->rows] * sizeof (void *)); tfree (R->row_start, 4 * (R->rows + 1)); tfree (R, sizeof (*R)); } else { assert (R->refcnt > 0); } } void tgls_free_message (struct tgl_state *TLS, struct tgl_message *M) { tgls_clear_message (TLS, M); if (M->reply_markup) { tgls_free_reply_markup (TLS, M->reply_markup); } tfree (M, sizeof (*M)); } void tgls_free_chat (struct tgl_state *TLS, struct tgl_chat *U) { if (U->title) { tfree_str (U->title); } if (U->print_title) { tfree_str (U->print_title); } if (U->user_list) { tfree (U->user_list, U->user_list_size * 12); } if (U->photo) { tgls_free_photo (TLS, U->photo); } tfree (U, sizeof (tgl_peer_t)); } void tgls_free_user (struct tgl_state *TLS, struct tgl_user *U) { if (U->first_name) { tfree_str (U->first_name); } if (U->last_name) { tfree_str (U->last_name); } if (U->print_name) { tfree_str (U->print_name); } if (U->phone) { tfree_str (U->phone); } if (U->username) { tfree_str (U->username); } if (U->real_first_name) { tfree_str (U->real_first_name); } if (U->real_last_name) { tfree_str (U->real_last_name); } if (U->status.ev) { tgl_remove_status_expire (TLS, U); } if (U->photo) { tgls_free_photo (TLS, U->photo); } if (U->bot_info) { tgls_free_bot_info (TLS, U->bot_info); } tfree (U, sizeof (tgl_peer_t)); } void tgls_free_encr_chat (struct tgl_state *TLS, struct tgl_secret_chat *U) { if (U->print_name) { tfree_str (U->print_name); } if (U->g_key) { tfree (U->g_key, 256); } tfree (U, sizeof (tgl_peer_t)); } void tgls_free_channel (struct tgl_state *TLS, struct tgl_channel *U) { if (U->print_title) { tfree_str (U->print_title); } if (U->username) { tfree_str (U->username); } if (U->title) { tfree_str (U->title); } if (U->about) { tfree_str (U->about); } if (U->photo) { tgls_free_photo (TLS, U->photo); } tfree (U, sizeof (tgl_peer_t)); } void tgls_free_peer (struct tgl_state *TLS, tgl_peer_t *P) { if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { tgls_free_user (TLS, (void *)P); } else if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT) { tgls_free_chat (TLS, (void *)P); } else if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT) { tgls_free_encr_chat (TLS, (void *)P); } else if (tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL) { tgls_free_channel (TLS, (void *)P); } else { assert (0); } } void tgls_free_bot_info (struct tgl_state *TLS, struct tgl_bot_info *B) { if (!B) { return; } int i; for (i = 0; i < B->commands_num; i++) { tfree_str (B->commands[i].command); tfree_str (B->commands[i].description); } tfree (B->commands, sizeof (struct tgl_bot_command) * B->commands_num); tfree_str (B->share_text); tfree_str (B->description); tfree (B, sizeof (*B)); } /* }}} */ /* Messages {{{ */ void tglm_message_del_use (struct tgl_state *TLS, struct tgl_message *M) { M->next_use->prev_use = M->prev_use; M->prev_use->next_use = M->next_use; } void tglm_message_add_use (struct tgl_state *TLS, struct tgl_message *M) { M->next_use = TLS->message_list.next_use; M->prev_use = &TLS->message_list; M->next_use->prev_use = M; M->prev_use->next_use = M; } void tglm_message_add_peer (struct tgl_state *TLS, struct tgl_message *M) { tgl_peer_id_t id; if (!tgl_cmp_peer_id (M->to_id, TLS->our_id)) { id = M->from_id; } else { id = M->to_id; } tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P) { P = talloc0 (sizeof (*P)); P->id = id; switch (tgl_get_peer_type (id)) { case TGL_PEER_USER: TLS->users_allocated ++; break; case TGL_PEER_CHAT: TLS->chats_allocated ++; break; case TGL_PEER_GEO_CHAT: TLS->geo_chats_allocated ++; break; case TGL_PEER_ENCR_CHAT: TLS->encr_chats_allocated ++; break; } TLS->peer_tree = tree_insert_peer (TLS->peer_tree, P, rand ()); increase_peer_size (TLS); TLS->Peers[TLS->peer_num ++] = P; } if (!P->last) { P->last = M; M->prev = M->next = 0; } else { if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) { struct tgl_message *N = P->last; struct tgl_message *NP = 0; while (N && N->permanent_id.id > M->permanent_id.id) { NP = N; N = N->next; } if (N) { assert (N->permanent_id.id < M->permanent_id.id); } M->next = N; M->prev = NP; if (N) { N->prev = M; } if (NP) { NP->next = M; } else { P->last = M; } } else { struct tgl_message *N = P->last; struct tgl_message *NP = 0; M->next = N; M->prev = NP; if (N) { N->prev = M; } if (NP) { NP->next = M; } else { P->last = M; } } } } void tglm_message_del_peer (struct tgl_state *TLS, struct tgl_message *M) { tgl_peer_id_t id; if (!tgl_cmp_peer_id (M->to_id, TLS->our_id)) { id = M->from_id; } else { id = M->to_id; } tgl_peer_t *P = tgl_peer_get (TLS, id); if (M->prev) { M->prev->next = M->next; } if (M->next) { M->next->prev = M->prev; } if (P && P->last == M) { P->last = M->next; } } struct tgl_message *tglm_message_alloc (struct tgl_state *TLS, tgl_message_id_t *id) { struct tgl_message *M = talloc0 (sizeof (*M)); M->permanent_id = *id; tglm_message_insert_tree (TLS, M); TLS->messages_allocated ++; return M; } void tglm_message_insert_tree (struct tgl_state *TLS, struct tgl_message *M) { assert (M->permanent_id.id); TLS->message_tree = tree_insert_message (TLS->message_tree, M, rand ()); } void tglm_message_remove_tree (struct tgl_state *TLS, struct tgl_message *M) { assert (M->permanent_id.id); TLS->message_tree = tree_delete_message (TLS->message_tree, M); } void tglm_message_insert (struct tgl_state *TLS, struct tgl_message *M) { tglm_message_add_use (TLS, M); tglm_message_add_peer (TLS, M); } void tglm_message_insert_unsent (struct tgl_state *TLS, struct tgl_message *M) { TLS->message_unsent_tree = tree_insert_message (TLS->message_unsent_tree, M, rand ()); } void tglm_message_remove_unsent (struct tgl_state *TLS, struct tgl_message *M) { TLS->message_unsent_tree = tree_delete_message (TLS->message_unsent_tree, M); } static void __send_msg (struct tgl_message *M, void *_TLS) { struct tgl_state *TLS = _TLS; vlogprintf (E_NOTICE, "Resending message...\n"); //print_message (M); if (M->media.type != tgl_message_media_none) { assert (M->flags & TGLMF_ENCRYPTED); bl_do_message_delete (TLS, &M->permanent_id); } else { tgl_do_send_msg (TLS, M, 0, 0); } } void tglm_send_all_unsent (struct tgl_state *TLS) { tree_act_ex_message (TLS->message_unsent_tree, __send_msg, TLS); } /* }}} */ struct tgl_photo *tgl_photo_get (struct tgl_state *TLS, long long id) { struct tgl_photo P; P.id = id; return tree_lookup_photo (TLS->photo_tree, &P); } void tgl_photo_insert (struct tgl_state *TLS, struct tgl_photo *P) { TLS->photo_tree = tree_insert_photo (TLS->photo_tree, P, rand ()); } struct tgl_document *tgl_document_get (struct tgl_state *TLS, long long id) { struct tgl_document P; P.id = id; return tree_lookup_document (TLS->document_tree, &P); } void tgl_document_insert (struct tgl_state *TLS, struct tgl_document *P) { TLS->document_tree = tree_insert_document (TLS->document_tree, P, rand ()); } struct tgl_webpage *tgl_webpage_get (struct tgl_state *TLS, long long id) { struct tgl_webpage P; P.id = id; return tree_lookup_webpage (TLS->webpage_tree, &P); } void tgl_webpage_insert (struct tgl_state *TLS, struct tgl_webpage *P) { TLS->webpage_tree = tree_insert_webpage (TLS->webpage_tree, P, rand ()); } void tglp_peer_insert_name (struct tgl_state *TLS, tgl_peer_t *P) { TLS->peer_by_name_tree = tree_insert_peer_by_name (TLS->peer_by_name_tree, P, rand ()); } void tglp_peer_delete_name (struct tgl_state *TLS, tgl_peer_t *P) { TLS->peer_by_name_tree = tree_delete_peer_by_name (TLS->peer_by_name_tree, P); } tgl_peer_t *tgl_peer_get (struct tgl_state *TLS, tgl_peer_id_t id) { static tgl_peer_t U; U.id = id; return tree_lookup_peer (TLS->peer_tree, &U); } struct tgl_message *tgl_message_get (struct tgl_state *TLS, tgl_message_id_t *msg_id) { struct tgl_message M; if (msg_id->peer_type == TGL_PEER_RANDOM_ID) { msg_id = tgls_get_local_by_random (TLS, msg_id->id); } else if (msg_id->peer_type == TGL_PEER_TEMP_ID) { msg_id = tgls_get_local_by_temp (TLS, msg_id->id); } if (!msg_id) { return NULL; } M.permanent_id = *msg_id; return tree_lookup_message (TLS->message_tree, &M); } tgl_peer_t *tgl_peer_get_by_name (struct tgl_state *TLS, const char *s) { static tgl_peer_t P; P.print_name = (void *)s; tgl_peer_t *R = tree_lookup_peer_by_name (TLS->peer_by_name_tree, &P); return R; } void tgl_peer_iterator_ex (struct tgl_state *TLS, void (*it)(tgl_peer_t *P, void *extra), void *extra) { tree_act_ex_peer (TLS->peer_tree, it, extra); } int tgl_complete_user_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) { index ++; while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_USER)) { index ++; } if (index < TLS->peer_num) { *R = strdup (TLS->Peers[index]->print_name); assert (*R); return index; } else { return -1; } } int tgl_complete_chat_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) { index ++; while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_CHAT)) { index ++; } if (index < TLS->peer_num) { *R = strdup (TLS->Peers[index]->print_name); assert (*R); return index; } else { return -1; } } int tgl_complete_channel_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) { index ++; while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_CHANNEL)) { index ++; } if (index < TLS->peer_num) { *R = strdup (TLS->Peers[index]->print_name); assert (*R); return index; } else { return -1; } } int tgl_complete_encr_chat_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) { index ++; while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len) || tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_ENCR_CHAT)) { index ++; } if (index < TLS->peer_num) { *R = strdup (TLS->Peers[index]->print_name); assert (*R); return index; } else { return -1; } } int tgl_complete_peer_list (struct tgl_state *TLS, int index, const char *text, int len, char **R) { index ++; while (index < TLS->peer_num && (!TLS->Peers[index]->print_name || strncmp (TLS->Peers[index]->print_name, text, len))) { index ++; } if (index < TLS->peer_num) { *R = strdup (TLS->Peers[index]->print_name); assert (*R); return index; } else { return -1; } } int tgl_secret_chat_for_user (struct tgl_state *TLS, tgl_peer_id_t user_id) { int index = 0; while (index < TLS->peer_num && (tgl_get_peer_type (TLS->Peers[index]->id) != TGL_PEER_ENCR_CHAT || TLS->Peers[index]->encr_chat.user_id != tgl_get_peer_id (user_id) || TLS->Peers[index]->encr_chat.state != sc_ok)) { index ++; } if (index < TLS->peer_num) { return tgl_get_peer_id (TLS->Peers[index]->encr_chat.id); } else { return -1; } } void tgls_free_peer_gw (tgl_peer_t *P, void *TLS) { tgls_free_peer (TLS, P); } void tgls_free_message_gw (struct tgl_message *M, void *TLS) { tgls_free_message (TLS, M); } void tgl_free_all (struct tgl_state *TLS) { tree_act_ex_peer (TLS->peer_tree, tgls_free_peer_gw, TLS); TLS->peer_tree = tree_clear_peer (TLS->peer_tree); TLS->peer_by_name_tree = tree_clear_peer_by_name (TLS->peer_by_name_tree); tree_act_ex_message (TLS->message_tree, tgls_free_message_gw, TLS); TLS->message_tree = tree_clear_message (TLS->message_tree); tree_act_ex_message (TLS->message_unsent_tree, tgls_free_message_gw, TLS); TLS->message_unsent_tree = tree_clear_message (TLS->message_unsent_tree); tglq_query_free_all (TLS); TLS->random_id_tree = tree_clear_random_id (TLS->random_id_tree); TLS->temp_id_tree = tree_clear_temp_id (TLS->temp_id_tree); if (TLS->encr_prime) { tfree (TLS->encr_prime, 256); } if (TLS->binlog_name) { tfree_str (TLS->binlog_name); } if (TLS->auth_file) { tfree_str (TLS->auth_file); } if (TLS->downloads_directory) { tfree_str (TLS->downloads_directory); } if (TLS->app_hash) { tfree_str (TLS->app_hash); } if (TLS->app_version) { tfree_str (TLS->app_version); } if (TLS->error) { tfree_str (TLS->error); } int i; for (i = 0; i < TLS->rsa_key_num; i++) { if (TLS->rsa_key_list[i]) { tfree_str (TLS->rsa_key_list[i]); } } for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) { tgls_free_dc (TLS, TLS->DC_list[i]); } TGLC_bn_ctx_free (TLS->TGLC_bn_ctx); tgls_free_pubkey (TLS); if (TLS->ev_login) { TLS->timer_methods->free (TLS->ev_login); } if (TLS->online_updates_timer) { TLS->timer_methods->free (TLS->online_updates_timer); } tfree (TLS->Peers, TLS->peer_size * sizeof (void *)); tfree (TLS, sizeof (*TLS)); } int tgl_print_stat (struct tgl_state *TLS, char *s, int len) { return tsnprintf (s, len, "users_allocated\t%d\n" "chats_allocated\t%d\n" "encr_chats_allocated\t%d\n" "peer_num\t%d\n" "messages_allocated\t%d\n", TLS->users_allocated, TLS->chats_allocated, TLS->encr_chats_allocated, TLS->peer_num, TLS->messages_allocated ); } void tglf_fetch_int_array (int *dst, struct tl_ds_vector *src, int len) { int i; assert (len <= *src->f1); for (i = 0; i < len; i++) { dst[i] = *(int *)src->f2[i]; } } void tglf_fetch_int_tuple (int *dst, int **src, int len) { int i; for (i = 0; i < len; i++) { dst[i] = *src[i]; } } void tgls_messages_mark_read (struct tgl_state *TLS, struct tgl_message *M, int out, int seq) { while (M && M->permanent_id.id > seq) { if ((M->flags & TGLMF_OUT) == out) { if (!(M->flags & TGLMF_UNREAD)) { return; } } M = M->next; } while (M) { if ((M->flags & TGLMF_OUT) == out) { if (M->flags & TGLMF_UNREAD) { M->flags &= ~TGLMF_UNREAD; TLS->callback.marked_read (TLS, 1, &M); } else { return; } } M = M->next; } } /* void tgls_insert_random2local (struct tgl_state *TLS, long long random_id, tgl_message_id_t *msg_id) { struct random2local *X = talloc (sizeof (*X)); X->random_id = random_id; X->local_id = *msg_id; struct random2local *R = tree_lookup_random_id (TLS->random_id_tree, X); assert (!R); TLS->random_id_tree = tree_insert_random_id (TLS->random_id_tree, X, rand ()); } tgl_message_id_t *tgls_get_local_by_random (struct tgl_state *TLS, long long random_id) { struct random2local X; X.random_id = random_id; struct random2local *Y = tree_lookup_random_id (TLS->random_id_tree, &X); if (Y) { //TLS->random_id_tree = tree_delete_random_id (TLS->random_id_tree, Y); return &Y->local_id; } else { return NULL; } } void tgls_insert_temp2local (struct tgl_state *TLS, int temp_id, tgl_message_id_t *msg_id) { struct random2local *X = talloc (sizeof (*X)); X->random_id = temp_id; X->local_id = *msg_id; struct random2local *R = tree_lookup_random_id (TLS->temp_id_tree, X); assert (!R); TLS->temp_id_tree = tree_insert_random_id (TLS->temp_id_tree, X, rand ()); } }*/ tgl_message_id_t *tgls_get_local_by_random (struct tgl_state *TLS, long long random_id) { struct tgl_message M; M.random_id = random_id; struct tgl_message *N = tree_lookup_random_id (TLS->random_id_tree, &M); if (N) { return &N->permanent_id; } else { return NULL; } } tgl_message_id_t *tgls_get_local_by_temp (struct tgl_state *TLS, int temp_id) { struct tgl_message M; M.temp_id = temp_id; struct tgl_message *N = tree_lookup_temp_id (TLS->temp_id_tree, &M); if (N) { return &N->permanent_id; } else { return NULL; } } tgl_message_id_t tgl_convert_temp_msg_id (struct tgl_state *TLS, tgl_message_id_t msg_id) { struct tgl_message M; M.temp_id = msg_id.id; struct tgl_message *N = tree_lookup_temp_id (TLS->temp_id_tree, &M); if (N) { return N->permanent_id; } else { return msg_id; } } void tgls_message_change_temp_id (struct tgl_state *TLS, struct tgl_message *M, int temp_id) { if (M->temp_id == temp_id) { return; } assert (!M->temp_id); M->temp_id = temp_id; TLS->temp_id_tree = tree_insert_temp_id (TLS->temp_id_tree, M, rand ()); } void tgls_message_change_random_id (struct tgl_state *TLS, struct tgl_message *M, long long random_id) { if (M->random_id == random_id) { return; } assert (!M->random_id); M->random_id = random_id; TLS->random_id_tree = tree_insert_random_id (TLS->random_id_tree, M, rand ()); } void tglm_message_del_temp_id (struct tgl_state *TLS, struct tgl_message *M) { if (M->temp_id) { TLS->temp_id_tree = tree_delete_temp_id (TLS->temp_id_tree, M); } } void tglm_message_del_random_id (struct tgl_state *TLS, struct tgl_message *M) { if (M->random_id) { TLS->random_id_tree = tree_delete_random_id (TLS->random_id_tree, M); } } ================================================ FILE: tg-mime-types.c ================================================ #include #include #define MAX_MIME_TYPES_NUM 10000 #include "mime-types.c" static int mime_initialized; static int mime_type_number; static char *mime_type_names[MAX_MIME_TYPES_NUM]; static char *mime_type_extensions[MAX_MIME_TYPES_NUM]; static void mime_init (void) { char *start = (char *)mime_types; char *end = start + mime_types_len; mime_initialized = 1; char *c = start; while (c < end) { if (*c == '#') { while (c < end && *c != '\n') { c ++; } if (c < end) { c ++; } } else { while (*c <= ' ' && *c != '\n' && c < end) { c ++; } assert (*c > ' ' && *c != '\n' && c < end); char *name = c; while (*c > ' ' && *c != '\n' && c < end) { c ++; } assert (*c <= ' ' && *c != '\n' && c < end); *c = 0; c ++; while (1) { while (*c <= ' ' && *c != '\n' && c < end) { c ++; } if (*c == '\n' || c == end) { if (*c == '\n') { c ++; } break; } char *ext = c; while (*c > ' ' && *c != '\n' && c < end) { c ++; } assert (c != end); int br = (*c == '\n'); *c = 0; c ++; assert (mime_type_number < MAX_MIME_TYPES_NUM); mime_type_names[mime_type_number] = name; mime_type_extensions[mime_type_number] = ext; mime_type_number ++; if (br) { break; } } } } } char *tg_extension_by_mime (const char *mime_type) { if (!mime_initialized) { mime_init (); } int i; for (i = 0; i < mime_type_number; i++) { if (!strcmp (mime_type_names[i], mime_type)) { return mime_type_extensions[i]; } } return NULL; } char *tg_mime_by_filename (const char *filename) { int l = strlen (filename); const char *p = filename - 1 + l; while (p >= filename && *p != '.') { p --; } p ++; if (!mime_initialized) { mime_init (); } static char *def = "application/octet-stream"; if (strlen (p) > 10) { return def; } static char s[11]; strcpy (s, p); char *q = s; while (*q) { if (*q >= 'A' && *p <= 'Z') { *q = *q + 'z' - 'Z'; } q ++; } int i; for (i = 0; i < mime_type_number; i++) { if (!strcmp (mime_type_extensions[i], s)) { return mime_type_names[i]; } } return def; } ================================================ FILE: tg-mime-types.h ================================================ char *tg_mime_by_filename (const char *filename); char *tg_extension_by_mime (const char *mime_type); ================================================ FILE: tgl-binlog.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __BINLOG_H__ #define __BINLOG_H__ //#include "structures.h" #include "tgl.h" #include "auto/auto-types.h" #ifdef __cplusplus extern "C" { #endif void bl_do_dc_option (struct tgl_state *TLS, int flags, int id, const char *name, int l1, const char *ip, int l2, int port); void bl_do_set_working_dc (struct tgl_state *TLS, int num); void bl_do_dc_signed (struct tgl_state *TLS, int id); void bl_do_set_our_id (struct tgl_state *TLS, tgl_peer_id_t id); void bl_do_set_dh_params (struct tgl_state *TLS, int root, unsigned char prime[], int version); void bl_do_set_pts (struct tgl_state *TLS, int pts); void bl_do_set_qts (struct tgl_state *TLS, int qts); void bl_do_set_date (struct tgl_state *TLS, int date); void bl_do_set_seq (struct tgl_state *TLS, int seq); void bl_do_set_channel_pts (struct tgl_state *TLS, int id, int pts); void bl_do_set_auth_key (struct tgl_state *TLS, int num, unsigned char *buf); void bl_do_set_msg_id (struct tgl_state *TLS, struct tgl_message_id *old_id, struct tgl_message_id *new_id); void bl_do_message_delete (struct tgl_state *TLS, struct tgl_message_id *id); void bl_do_peer_delete (struct tgl_state *TLS, tgl_peer_id_t id); void bl_do_chat_add_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user, int inviter, int date); void bl_do_chat_del_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user); void bl_do_msg_update (struct tgl_state *TLS, struct tgl_message_id *id); void bl_do_reset_authorization (struct tgl_state *TLS); void bl_do_edit_message (struct tgl_state *TLS, struct tgl_message_id *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, tgl_peer_id_t *fwd_from_id, int *fwd_date, int *date, const char *message, int message_len, struct tl_ds_message_media *media, struct tl_ds_message_action *action, int *reply_id, struct tl_ds_reply_markup *reply_markup, struct tl_ds_vector *entities, int flags); void bl_do_edit_message_encr (struct tgl_state *TLS, struct tgl_message_id *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, int *date, const char *message, int message_len, struct tl_ds_decrypted_message_media *media, struct tl_ds_decrypted_message_action *action, struct tl_ds_encrypted_file *file, int flags); void bl_do_encr_chat_exchange (struct tgl_state *TLS, tgl_peer_id_t id, long long *exchange_id, const void *key, int *state); void bl_do_user (struct tgl_state *TLS, int id, long long *access_hash, const char *first_name, int first_name_len, const char *last_name, int last_name_len, const char *phone, int phone_len, const char *username, int username_len, struct tl_ds_photo *photo, struct tl_ds_user_profile_photo *profile_photo, int *last_read_in, int *last_read_out, struct tl_ds_bot_info *bot_info, int flags); void bl_do_chat (struct tgl_state *TLS, int id, const char *title, int title_len, int *user_num, int *date, int *version, struct tl_ds_vector *participants, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *admin, int *last_read_in, int *last_read_out, int flags); void bl_do_encr_chat (struct tgl_state *TLS, int id, long long *access_hash, int *date, int *admin, int *user_id, void *key, void *g_key, void *first_key_id, int *state, int *ttl, int *layer, int *in_seq_no, int *last_in_seq_no, int *out_seq_no, long long *key_fingerprint, int flags, const char *print_name, int print_name_len); void bl_do_channel (struct tgl_state *TLS, int id, long long *access_hash, int *date, const char *title, int title_len, const char *username, int username_len, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *version, char *about, int about_len, int *participants_count, int *admins_count, int *kicked_count, int *last_read_in, int flags); void bl_do_peer_delete (struct tgl_state *TLS, tgl_peer_id_t id); #ifdef __cplusplus } #endif #endif ================================================ FILE: tgl-fetch.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #ifndef __TGL_FETCH_H__ #define __TGL_FETCH_H__ #include "tgl.h" #include "auto/auto-types.h" struct tgl_user *tglf_fetch_alloc_user (struct tgl_state *TLS, struct tl_ds_user *DS_U); struct tgl_user *tglf_fetch_alloc_user_full (struct tgl_state *TLS, struct tl_ds_user_full *DS_U); struct tgl_chat *tglf_fetch_alloc_chat (struct tgl_state *TLS, struct tl_ds_chat *DS_C); struct tgl_chat *tglf_fetch_alloc_chat_full (struct tgl_state *TLS, struct tl_ds_messages_chat_full *DS_MCF); struct tgl_channel *tglf_fetch_alloc_channel (struct tgl_state *TLS, struct tl_ds_chat *DS_C); struct tgl_channel *tglf_fetch_alloc_channel_full (struct tgl_state *TLS, struct tl_ds_messages_chat_full *DS_MCF); struct tgl_secret_chat *tglf_fetch_alloc_encrypted_chat (struct tgl_state *TLS, struct tl_ds_encrypted_chat *DS_EC); struct tgl_message *tglf_fetch_alloc_message (struct tgl_state *TLS, struct tl_ds_message *DS_M, int *new_msg); struct tgl_message *tglf_fetch_alloc_message_short_buf (struct tgl_state *TLS); struct tgl_message *tglf_fetch_alloc_message_short_chat_buf (struct tgl_state *TLS); struct tgl_message *tglf_fetch_alloc_encrypted_message (struct tgl_state *TLS, struct tl_ds_encrypted_message *DS_EM); tgl_peer_id_t tglf_fetch_peer_id (struct tgl_state *TLS, struct tl_ds_peer *DS_P); long long tglf_fetch_user_photo (struct tgl_state *TLS, struct tgl_user *U, struct tl_ds_user_profile_photo *DS_UPP); void tglf_fetch_message_media (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_message_media *DS_MM); void tglf_fetch_message_action (struct tgl_state *TLS, struct tgl_message_action *M, struct tl_ds_message_action *DS_MA); //void tglf_fetch_chat_full (struct tgl_state *TLS, struct tgl_chat *C); void tglf_fetch_encrypted_message_file (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_encrypted_file *DS_EF); void tglf_fetch_message_media_encrypted (struct tgl_state *TLS, struct tgl_message_media *M, struct tl_ds_decrypted_message_media *DS_DMM); void tglf_fetch_message_action_encrypted (struct tgl_state *TLS, struct tgl_message_action *M, struct tl_ds_decrypted_message_action *DS_DMA); int tglf_fetch_user_status (struct tgl_state *TLS, struct tgl_user_status *S, struct tgl_user *U, struct tl_ds_user_status *DS_US); enum tgl_typing_status tglf_fetch_typing (struct tl_ds_send_message_action *DS_SMA); void tglf_fetch_chat_participants (struct tgl_state *TLS, struct tgl_chat *C, struct tl_ds_chat_participants *DS_CP); void tglf_fetch_int_array (int *dst, struct tl_ds_vector *src, int len); void tglf_fetch_int_tuple (int *dst, int **src, int len); int tglf_fetch_file_location (struct tgl_state *TLS, struct tgl_file_location *loc, struct tl_ds_file_location *DS_FL); void tglf_fetch_message_short (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_updates *DS_U); void tglf_fetch_message_short_chat (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_updates *DS_U); struct tgl_message *tglf_fetch_alloc_message_short (struct tgl_state *TLS, struct tl_ds_updates *DS_U); struct tgl_message *tglf_fetch_alloc_message_short_chat (struct tgl_state *TLS, struct tl_ds_updates *DS_U); struct tgl_photo *tglf_fetch_alloc_photo (struct tgl_state *TLS, struct tl_ds_photo *DS_P); struct tgl_bot_info *tglf_fetch_alloc_bot_info (struct tgl_state *TLS, struct tl_ds_bot_info *DS_BI); struct tgl_message_reply_markup *tglf_fetch_alloc_reply_markup (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_reply_markup *DS_RM); void tglf_fetch_message_entities (struct tgl_state *TLS, struct tgl_message *M, struct tl_ds_vector *DS); #endif ================================================ FILE: tgl-inner.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #ifndef __TGL_INNER_H__ #define __TGL_INNER_H__ #ifndef vlogprintf #define vlogprintf(verbosity_level,...) \ do { \ if (TLS->verbosity >= verbosity_level) { \ TLS->callback.logprintf (__VA_ARGS__); \ } \ } while (0) #endif #endif ================================================ FILE: tgl-layout.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #ifndef __TGL_LAYOUT_H__ #define __TGL_LAYOUT_H__ #define TGLDF_IMAGE 1 #define TGLDF_STICKER 2 #define TGLDF_ANIMATED 4 #define TGLDF_AUDIO 8 #define TGLDF_VIDEO 16 #define TGLMF_UNREAD 1 #define TGLMF_OUT 2 #define TGLMF_DISABLE_PREVIEW 4 #define TGLMF_MENTION 16 #define TGLMF_CREATED (1 << 8) #define TGLMF_PENDING (1 << 9) #define TGLMF_DELETED (1 << 10) #define TGLMF_ENCRYPTED (1 << 11) #define TGLMF_EMPTY (1 << 12) #define TGLMF_SERVICE (1 << 13) #define TGLMF_SESSION_OUTBOUND (1 << 14) #define TGLMF_POST_AS_CHANNEL (1 << 8) #define TGLMF_HTML (1 << 9) #define TGLMF_CREATE 0x10000 #define TGLPF_CREATED (1 << 0) #define TGLPF_CREATE 0x80000000 #define TGLPF_HAS_PHOTO (1 << 1) #define TGLPF_DELETED (1 << 2) #define TGLPF_OFFICIAL (1 << 3) #define TGLPF_KICKED (1 << 4) #define TGLPF_ADMIN (1 << 5) #define TGLPF_CREATOR (1 << 6) #define TGLPF_LEFT (1 << 7) #define TGLPF_DEACTIVATED (1 << 8) #define TGLUF_CONTACT (1 << 16) #define TGLUF_MUTUAL_CONTACT (1 << 17) #define TGLUF_BLOCKED (1 << 18) #define TGLUF_SELF (1 << 19) #define TGLUF_CREATED TGLPF_CREATED #define TGLUF_DELETED TGLPF_DELETED #define TGLUF_HAS_PHOTO TGLPF_HAS_PHOTO #define TGLUF_CREATE TGLPF_CREATE #define TGLUF_BOT (1 << 20) #define TGLUF_OFFICIAL TGLPF_OFFICIAL #define TGLUF_TYPE_MASK \ (TGLUF_CONTACT | TGLUF_MUTUAL_CONTACT | TGLUF_BLOCKED | TGLUF_SELF | TGLUF_CREATED | TGLUF_DELETED | TGLUF_OFFICIAL) #define TGLCF_CREATED TGLPF_CREATED #define TGLCF_CREATE TGLPF_CREATE #define TGLCF_HAS_PHOTO TGLPF_HAS_PHOTO #define TGLCF_KICKED TGLPF_KICKED #define TGLCF_CREATOR TGLPF_CREATOR #define TGLCF_ADMIN TGLPF_ADMIN #define TGLCF_OFFICIAL TGLPF_OFFICIAL #define TGLCF_LEFT TGLPF_LEFT #define TGLCF_DEACTIVATED TGLPF_DEACTIVATED #define TGLCF_ADMINS_ENABLED (1 << 16) #define TGLCF_TYPE_MASK \ (TGLCF_CREATED | TGLCF_KICKED | TGLCF_CREATOR | TGLCF_ADMIN | TGLCF_OFFICIAL | TGLCF_LEFT | TGLCF_DEACTIVATED | TGLCF_ADMINS_ENABLED) #define TGLECF_CREATED TGLPF_CREATED #define TGLECF_CREATE TGLPF_CREATE #define TGLECF_HAS_PHOTO TGLPF_HAS_PHOTO #define TGLECF_KICKED TGLPF_KICKED #define TGLECF_CREATOR TGLPF_CREATOR #define TGLECF_ADMIN TGLPF_ADMIN #define TGLECF_TYPE_MASK \ (TGLECF_CREATED | TGLECF_KICKED | TGLECF_CREATOR | TGLECF_ADMIN) #define TGLCHF_CREATED TGLPF_CREATED #define TGLCHF_CREATE TGLPF_CREATE #define TGLCHF_HAS_PHOTO TGLPF_HAS_PHOTO #define TGLCHF_KICKED TGLPF_KICKED #define TGLCHF_CREATOR TGLPF_CREATOR #define TGLCHF_ADMIN TGLPF_ADMIN #define TGLCHF_OFFICIAL TGLPF_OFFICIAL #define TGLCHF_LEFT TGLPF_LEFT #define TGLCHF_DEACTIVATED TGLPF_DEACTIVATED #define TGLCHF_BROADCAST (1 << 16) #define TGLCHF_EDITOR (1 << 17) #define TGLCHF_MODERATOR (1 << 18) #define TGLCHF_MEGAGROUP (1 << 19) #define TGLCHF_TYPE_MASK \ (TGLCHF_CREATED | TGLCHF_KICKED | TGLCHF_CREATOR | TGLCHF_ADMIN | TGLCHF_OFFICIAL | TGLCHF_LEFT | TGLCHF_DEACTIVATED | TGLCHF_BROADCAST | TGLCHF_EDITOR | TGLCHF_MODERATOR | TGLCHF_MEGAGROUP) #define TGLCHF_DIFF 0x20000000 #define TGL_FLAGS_UNCHANGED 0x40000000 #define TGLDCF_AUTHORIZED 1 #define TGLDCF_LOGGED_IN 8 #define TGL_PERMANENT_ID_SIZE 24 #pragma pack(push,4) typedef struct { int peer_type; int peer_id; long long access_hash; } tgl_peer_id_t; enum tgl_dc_state { st_init, st_reqpq_sent, st_reqdh_sent, st_client_dh_sent, st_init_temp, st_reqpq_sent_temp, st_reqdh_sent_temp, st_client_dh_sent_temp, st_authorized, st_error }; #define MAX_DC_SESSIONS 3 struct tgl_session { struct tgl_dc *dc; long long session_id; long long last_msg_id; int seq_no; int received_messages; struct connection *c; struct tree_long *ack_tree; struct tgl_timer *ev; }; struct tgl_dc_option { struct tgl_dc_option *next; char *ip; int port; }; struct tgl_dc { int id; //int port; int flags; int rsa_key_idx; enum tgl_dc_state state; //char *ip; //char *user; struct tgl_session *sessions[MAX_DC_SESSIONS]; char auth_key[256]; char temp_auth_key[256]; char nonce[256]; char new_nonce[256]; char server_nonce[256]; long long auth_key_id; long long temp_auth_key_id; long long temp_auth_key_bind_query_id; long long server_salt; struct tgl_timer *ev; int server_time_delta; double server_time_udelta; // ipv4, ipv6, ipv4_media, ipv6_media struct tgl_dc_option *options[4]; }; enum tgl_message_entity_type { tgl_message_entity_unknown, tgl_message_entity_mention, tgl_message_entity_hashtag, tgl_message_entity_bot_command, tgl_message_entity_url, tgl_message_entity_email, tgl_message_entity_bold, tgl_message_entity_italic, tgl_message_entity_code, tgl_message_entity_pre, tgl_message_entity_text_url }; struct tgl_message_entity { enum tgl_message_entity_type type; int start; int length; char *extra; }; enum tgl_message_media_type { tgl_message_media_none, tgl_message_media_photo, tgl_message_media_document, tgl_message_media_geo, tgl_message_media_contact, tgl_message_media_unsupported, //tgl_message_media_photo_encr, //tgl_message_media_video_encr, //tgl_message_media_audio_encr, tgl_message_media_document_encr, tgl_message_media_webpage, tgl_message_media_venue, tgl_message_media_video, tgl_message_media_audio }; enum tgl_message_action_type { tgl_message_action_none, tgl_message_action_geo_chat_create, tgl_message_action_geo_chat_checkin, tgl_message_action_chat_create, tgl_message_action_chat_edit_title, tgl_message_action_chat_edit_photo, tgl_message_action_chat_delete_photo, tgl_message_action_chat_add_users, tgl_message_action_chat_add_user_by_link, tgl_message_action_chat_delete_user, tgl_message_action_set_message_ttl, tgl_message_action_read_messages, tgl_message_action_delete_messages, tgl_message_action_screenshot_messages, tgl_message_action_flush_history, tgl_message_action_resend, tgl_message_action_notify_layer, tgl_message_action_typing, tgl_message_action_noop, tgl_message_action_commit_key, tgl_message_action_abort_key, tgl_message_action_request_key, tgl_message_action_accept_key, tgl_message_action_channel_create, tgl_message_action_migrated_to, tgl_message_action_migrated_from }; enum tgl_typing_status { tgl_typing_none, tgl_typing_typing, tgl_typing_cancel, tgl_typing_record_video, tgl_typing_upload_video, tgl_typing_record_audio, tgl_typing_upload_audio, tgl_typing_upload_photo, tgl_typing_upload_document, tgl_typing_geo, tgl_typing_choose_contact }; struct tgl_file_location { int dc; long long volume; int local_id; long long secret; }; struct tgl_photo_size { char *type; struct tgl_file_location loc; int w; int h; int size; char *data; }; struct tgl_geo { double longitude; double latitude; }; struct tgl_photo { long long id; long long access_hash; int refcnt; //int user_id; int date; char *caption; //struct tgl_geo geo; int sizes_num; struct tgl_photo_size *sizes; }; struct tgl_encr_document { long long id; long long access_hash; int refcnt; int dc_id; int size; int key_fingerprint; int flags; unsigned char *key; unsigned char *iv; int w; int h; char *caption; char *mime_type; int duration; }; struct tgl_user_status { int online; int when; struct tgl_timer *ev; }; struct tgl_bot_command { char *command; char *description; }; struct tgl_bot_info { int version; char *share_text; char *description; int commands_num; struct tgl_bot_command *commands; }; struct tgl_user { tgl_peer_id_t id; int flags; struct tgl_message *last; char *print_name; char *username; int structure_version; struct tgl_file_location photo_big; struct tgl_file_location photo_small; int last_read_in; int last_read_out; long long photo_id; struct tgl_photo *photo; void *extra; char *first_name; char *last_name; char *phone; long long access_hash; struct tgl_user_status status; int blocked; char *real_first_name; char *real_last_name; struct tgl_bot_info *bot_info; }; struct tgl_channel { tgl_peer_id_t id; int flags; struct tgl_message *last; char *print_title; char *username; int structure_version; struct tgl_file_location photo_big; struct tgl_file_location photo_small; int last_read_in; int last_read_out; long long photo_id; struct tgl_photo *photo; void *extra; long long access_hash; int date; char *title; int version; char *about; int participants_count; int admins_count; int kicked_count; int pts; }; struct tgl_chat_user { int user_id; int inviter_id; int date; }; struct tgl_chat { tgl_peer_id_t id; int flags; struct tgl_message *last; char *print_title; char *username; int structure_version; struct tgl_file_location photo_big; struct tgl_file_location photo_small; int last_read_in; int last_read_out; long long pad; struct tgl_photo *photo; void *extra; char *title; int users_num; int user_list_size; int user_list_version; struct tgl_chat_user *user_list; int date; int version; int admin_id; }; enum tgl_secret_chat_state { sc_none, sc_waiting, sc_request, sc_ok, sc_deleted }; enum tgl_secret_chat_exchange_state { tgl_sce_none, tgl_sce_requested, tgl_sce_accepted, tgl_sce_committed, tgl_sce_confirmed, tgl_sce_aborted }; struct tgl_secret_chat { tgl_peer_id_t id; int flags; struct tgl_message *last; char *print_name; char *username; int structure_version; struct tgl_file_location photo_big; struct tgl_file_location photo_small; int pad1; int pad2; long long pad; struct tgl_photo *photo; void *extra; int user_id; int admin_id; int date; int ttl; int layer; int in_seq_no; int out_seq_no; int last_in_seq_no; long long access_hash; unsigned char *g_key; enum tgl_secret_chat_state state; int key[64]; long long key_fingerprint; unsigned char first_key_sha[20]; long long exchange_id; enum tgl_secret_chat_exchange_state exchange_state; int exchange_key[64]; long long exchange_key_fingerprint; }; typedef union tgl_peer { struct { tgl_peer_id_t id; int flags; struct tgl_message *last; char *print_name; char *username; int structure_version; struct tgl_file_location photo_big; struct tgl_file_location photo_small; struct tgl_photo *photo; int last_read_in; int last_read_out; long long photo_id; void *extra; }; struct tgl_user user; struct tgl_chat chat; struct tgl_channel channel; struct tgl_secret_chat encr_chat; } tgl_peer_t; struct tgl_document { long long id; long long access_hash; int refcnt; //int user_id; int date; int size; int dc_id; struct tgl_photo_size thumb; char *caption; char *mime_type; int w; int h; int flags; int duration; }; struct tgl_message_action { enum tgl_message_action_type type; union { struct { char *title; int user_num; int *users; }; char *new_title; struct tgl_photo *photo; int user; int ttl; int layer; int read_cnt; int delete_cnt; int screenshot_cnt; enum tgl_typing_status typing; struct { int start_seq_no; int end_seq_no; }; struct { unsigned char *g_a; long long exchange_id; long long key_fingerprint; }; }; }; struct tgl_webpage { long long id; int refcnt; char *url; char *display_url; char *type; char *site_name; char *title; char *description; struct tgl_photo *photo; char *embed_url; char *embed_type; int embed_width; int embed_height; int duration; char *author; }; struct tgl_message_media { enum tgl_message_media_type type; union { struct { union { struct tgl_photo *photo; struct tgl_document *document; }; char *caption; }; struct tgl_encr_document *encr_document; struct tgl_webpage *webpage; struct tgl_geo geo; struct { char *phone; char *first_name; char *last_name; int user_id; }; struct { void *data; int data_size; }; struct { struct tgl_geo geo; char *title; char *address; char *provider; char *venue_id; } venue; }; }; struct tgl_message_reply_markup { int refcnt; int flags; int rows; int *row_start; char **buttons; }; typedef struct tgl_message_id { unsigned peer_type; unsigned peer_id; long long id; long long access_hash; } tgl_message_id_t; struct tgl_message { struct tgl_message *next_use, *prev_use; struct tgl_message *next, *prev; int temp_id; long long server_id; long long random_id; struct tgl_message_id permanent_id; int flags; tgl_peer_id_t fwd_from_id; int fwd_date; int reply_id; tgl_peer_id_t from_id; tgl_peer_id_t to_id; int date; struct tgl_message_reply_markup *reply_markup; int entities_num; struct tgl_message_entity *entities; union { struct tgl_message_action action; struct { char *message; int message_len; struct tgl_message_media media; }; }; }; #pragma pack(pop) #endif ================================================ FILE: tgl-methods-in.h ================================================ // normally you should not use these methods // use them with caution #ifndef __TGL_METHODS_IN_H__ #define __TGL_METHODS_IN_H__ /* {{{ AUTHORIZATION METHODS. NORMALLY YOU DON'T NEED THEM */ // send query to updated DCs' ips // automatically renews data on update void tgl_do_help_get_config (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // requests server to send code to specified phone number // if user is logged in elsewhere message will first appear as telegram message // and SMS will be sent some time after void tgl_do_send_code (struct tgl_state *TLS, const char *phone, int phone_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int registered, const char *hash), void *callback_extra); // request server to send code via phone call void tgl_do_phone_call (struct tgl_state *TLS, const char *phone, int phone_len, const char *hash, int hash_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // sends code from SMS to server. This step should end authorization, unless user have password int tgl_do_send_code_result (struct tgl_state *TLS, const char *phone, int phone_len, const char *hash, int hash_len, const char *code, int code_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra); // sends code from SMS, username and lastname to server. This step should end new user registration int tgl_do_send_code_result_auth (struct tgl_state *TLS, const char *phone, int phone_len, const char *hash, int hash_len, const char *code, int code_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra); /* }}} */ void tgl_do_send_msg (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); void tgl_do_check_password (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *extra, int success), void *callback_extra); void tgl_do_export_auth (struct tgl_state *TLS, int num, void (*callback) (struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_create_secret_chat (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); void tgl_do_get_difference (struct tgl_state *TLS, int sync_from_start, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_lookup_state (struct tgl_state *TLS); void tgl_do_help_get_config_dc (struct tgl_state *TLS, struct tgl_dc *D, void (*callback)(struct tgl_state *TLS, void *, int), void *callback_extra); void tgl_do_request_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E); void tgl_do_create_keys_end (struct tgl_state *TLS, struct tgl_secret_chat *U); void tgl_do_send_encr_chat_layer (struct tgl_state *TLS, struct tgl_secret_chat *E); #endif ================================================ FILE: tgl-net-inner.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __NET_H__ #define __NET_H__ struct connection_buffer { unsigned char *start; unsigned char *end; unsigned char *rptr; unsigned char *wptr; struct connection_buffer *next; }; enum conn_state { conn_none, conn_connecting, conn_ready, conn_failed, conn_stopped }; struct connection { int fd; char *ip; int port; int flags; enum conn_state state; int ipv6[4]; struct connection_buffer *in_head; struct connection_buffer *in_tail; struct connection_buffer *out_head; struct connection_buffer *out_tail; int in_bytes; int out_bytes; int packet_num; int out_packet_num; int last_connect_time; int in_fail_timer; struct mtproto_methods *methods; struct tgl_state *TLS; struct tgl_session *session; struct tgl_dc *dc; void *extra; struct event *ping_ev; struct event *fail_ev; struct event *read_ev; struct event *write_ev; double last_receive_time; }; //extern struct connection *Connections[]; int tgln_write_out (struct connection *c, const void *data, int len); void tgln_flush_out (struct connection *c); int tgln_read_in (struct connection *c, void *data, int len); int tgln_read_in_lookup (struct connection *c, void *data, int len); //void tgln_insert_msg_id (struct tgl_session *S, long long id); extern struct tgl_net_methods tgl_conn_methods; //void create_all_outbound_connections (void); //struct connection *create_connection (const char *host, int port, struct tgl_session *session, struct connection_methods *methods); //struct tgl_dc *tgln_alloc_dc (int id, char *ip, int port); //void tgln_dc_create_session (struct tgl_dc *DC, struct mtproto_methods *methods); struct connection *tgln_create_connection (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods); #define GET_DC(c) (c->session->dc) #endif ================================================ FILE: tgl-net.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include "crypto/rand.h" #include #ifdef EVENT_V2 #include #else #include #include "event-old.h" #endif #include #include #include "tgl-net-inner.h" #include "tgl-net.h" #include "tgl.h" #include "tgl-inner.h" //#include "mtproto-client.h" //#include "mtproto-common.h" #include "tree.h" #include "tools.h" #include "mtproto-client.h" #ifndef POLLRDHUP #define POLLRDHUP 0 #endif //double get_utime (int clock_id); //extern struct mtproto_methods auth_methods; static void fail_connection (struct connection *c); #define PING_TIMEOUT 10 static void start_ping_timer (struct connection *c); static void ping_alarm (evutil_socket_t fd, short what, void *arg) { struct connection *c = arg; struct tgl_state *TLS = c->TLS; vlogprintf (E_DEBUG + 2,"ping alarm\n"); assert (c->state == conn_ready || c->state == conn_connecting); if (tglt_get_double_time () - c->last_receive_time > 6 * PING_TIMEOUT) { vlogprintf (E_WARNING, "fail connection: reason: ping timeout\n"); c->state = conn_failed; fail_connection (c); } else if (tglt_get_double_time () - c->last_receive_time > 3 * PING_TIMEOUT && c->state == conn_ready) { tgl_do_send_ping (c->TLS, c); start_ping_timer (c); } else { start_ping_timer (c); } } static void stop_ping_timer (struct connection *c) { event_del (c->ping_ev); } static void start_ping_timer (struct connection *c) { static struct timeval ptimeout = { PING_TIMEOUT, 0}; event_add (c->ping_ev, &ptimeout); } static void restart_connection (struct connection *c); static void fail_alarm (evutil_socket_t fd, short what, void *arg) { struct connection *c = arg; c->in_fail_timer = 0; restart_connection (c); } static void start_fail_timer (struct connection *c) { if (c->in_fail_timer) { return; } c->in_fail_timer = 1; static struct timeval ptimeout = { 10, 0}; event_add (c->fail_ev, &ptimeout); } static struct connection_buffer *new_connection_buffer (int size) { struct connection_buffer *b = talloc0 (sizeof (*b)); b->start = talloc (size); b->end = b->start + size; b->rptr = b->wptr = b->start; return b; } static void delete_connection_buffer (struct connection_buffer *b) { tfree (b->start, b->end - b->start); tfree (b, sizeof (*b)); } int tgln_write_out (struct connection *c, const void *_data, int len) { struct tgl_state *TLS = c->TLS; vlogprintf (E_DEBUG, "write_out: %d bytes\n", len); const unsigned char *data = _data; if (!len) { return 0; } assert (len > 0); int x = 0; if (!c->out_bytes) { event_add (c->write_ev, 0); } if (!c->out_head) { struct connection_buffer *b = new_connection_buffer (1 << 20); c->out_head = c->out_tail = b; } while (len) { if (c->out_tail->end - c->out_tail->wptr >= len) { memcpy (c->out_tail->wptr, data, len); c->out_tail->wptr += len; c->out_bytes += len; return x + len; } else { int y = c->out_tail->end - c->out_tail->wptr; assert (y < len); memcpy (c->out_tail->wptr, data, y); x += y; len -= y; data += y; struct connection_buffer *b = new_connection_buffer (1 << 20); c->out_tail->next = b; b->next = 0; c->out_tail = b; c->out_bytes += y; } } return x; } int tgln_read_in (struct connection *c, void *_data, int len) { unsigned char *data = _data; if (!len) { return 0; } assert (len > 0); if (len > c->in_bytes) { len = c->in_bytes; } int x = 0; while (len) { int y = c->in_head->wptr - c->in_head->rptr; if (y > len) { memcpy (data, c->in_head->rptr, len); c->in_head->rptr += len; c->in_bytes -= len; return x + len; } else { memcpy (data, c->in_head->rptr, y); c->in_bytes -= y; x += y; data += y; len -= y; void *old = c->in_head; c->in_head = c->in_head->next; if (!c->in_head) { c->in_tail = 0; } delete_connection_buffer (old); } } return x; } int tgln_read_in_lookup (struct connection *c, void *_data, int len) { unsigned char *data = _data; if (!len || !c->in_bytes) { return 0; } assert (len > 0); if (len > c->in_bytes) { len = c->in_bytes; } int x = 0; struct connection_buffer *b = c->in_head; while (len) { int y = b->wptr - b->rptr; if (y >= len) { memcpy (data, b->rptr, len); return x + len; } else { memcpy (data, b->rptr, y); x += y; data += y; len -= y; b = b->next; } } return x; } void tgln_flush_out (struct connection *c) { } #define MAX_CONNECTIONS 100 static struct connection *Connections[MAX_CONNECTIONS]; static int max_connection_fd; static void rotate_port (struct connection *c) { switch (c->port) { case 443: c->port = 80; break; case 80: c->port = 25; break; case 25: c->port = 443; break; } } static void try_read (struct connection *c); static void try_write (struct connection *c); static void conn_try_read (evutil_socket_t fd, short what, void *arg) { struct connection *c = arg; struct tgl_state *TLS = c->TLS; vlogprintf (E_DEBUG + 1, "Try read. Fd = %d\n", c->fd); try_read (c); } static void conn_try_write (evutil_socket_t fd, short what, void *arg) { struct connection *c = arg; struct tgl_state *TLS = c->TLS; if (c->state == conn_connecting) { c->state = conn_ready; c->methods->ready (TLS, c); } try_write (c); if (c->out_bytes) { event_add (c->write_ev, 0); } } static int my_connect (struct connection *c, const char *host) { struct tgl_state *TLS = c->TLS; int v6 = TLS->ipv6_enabled; int fd = socket (v6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); if (fd < 0) { vlogprintf (E_ERROR, "Can not create socket: %s\n", strerror(errno)); start_fail_timer (c); return -1; } assert (fd >= 0 && fd < MAX_CONNECTIONS); if (fd > max_connection_fd) { max_connection_fd = fd; } int flags = -1; setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof (flags)); setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof (flags)); struct sockaddr_in addr; struct sockaddr_in6 addr6; memset (&addr, 0, sizeof (addr)); memset (&addr6, 0, sizeof (addr6)); if (v6) { addr6.sin6_family = AF_INET6; addr6.sin6_port = htons (c->port); if (inet_pton (AF_INET6, host, &addr6.sin6_addr.s6_addr) != 1) { vlogprintf (E_ERROR, "Bad ipv6 %s\n", host); close (fd); return -1; } } else { addr.sin_family = AF_INET; addr.sin_port = htons (c->port); if (inet_pton (AF_INET, host, &addr.sin_addr.s_addr) != 1) { vlogprintf (E_ERROR, "Bad ipv4 %s\n", host); close (fd); return -1; } } fcntl (fd, F_SETFL, O_NONBLOCK); if (connect (fd, (struct sockaddr *) (v6 ? (void *)&addr6 : (void *)&addr), v6 ? sizeof (addr6) : sizeof (addr)) == -1) { if (errno != EINPROGRESS) { close (fd); return -1; } } return fd; } struct connection *tgln_create_connection (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods) { struct connection *c = talloc0 (sizeof (*c)); c->TLS = TLS; c->ip = tstrdup (host); c->port = port; int fd = my_connect (c, c->ip); if (fd < 0) { vlogprintf (E_ERROR, "Can not connect to %s:%d %s\n", host, port, strerror(errno)); tfree (c, sizeof (*c)); return 0; } c->fd = fd; c->state = conn_connecting; c->last_receive_time = tglt_get_double_time (); c->flags = 0; assert (!Connections[fd]); Connections[fd] = c; c->ping_ev = evtimer_new (TLS->ev_base, ping_alarm, c); c->fail_ev = evtimer_new (TLS->ev_base, fail_alarm, c); c->write_ev = event_new (TLS->ev_base, c->fd, EV_WRITE, conn_try_write, c); struct timeval tv = {5, 0}; c->read_ev = event_new (TLS->ev_base, c->fd, EV_READ | EV_PERSIST, conn_try_read, c); event_add (c->read_ev, &tv); start_ping_timer (c); c->dc = dc; c->session = session; c->methods = methods; char byte = 0xef; assert (tgln_write_out (c, &byte, 1) == 1); tgln_flush_out (c); return c; } static void restart_connection (struct connection *c) { struct tgl_state *TLS = c->TLS; if (c->last_connect_time == time (0)) { start_fail_timer (c); return; } /*if (strcmp (c->ip, c->dc->ip)) { tfree_str (c->ip); c->ip = tstrdup (c->dc->ip); }*/ c->last_connect_time = time (0); int fd = my_connect (c, c->ip); if (fd < 0) { vlogprintf (E_WARNING, "Can not connect to %s:%d %s\n", c->ip, c->port, strerror(errno)); start_fail_timer (c); return; } c->fd = fd; c->state = conn_connecting; c->last_receive_time = tglt_get_double_time (); start_ping_timer (c); Connections[fd] = c; c->write_ev = event_new (TLS->ev_base, c->fd, EV_WRITE, conn_try_write, c); struct timeval tv = {5, 0}; c->read_ev = event_new (TLS->ev_base, c->fd, EV_READ | EV_PERSIST, conn_try_read, c); event_add (c->read_ev, &tv); char byte = 0xef; assert (tgln_write_out (c, &byte, 1) == 1); tgln_flush_out (c); } static void fail_connection (struct connection *c) { struct tgl_state *TLS = c->TLS; if (c->state == conn_ready || c->state == conn_connecting) { stop_ping_timer (c); } event_free (c->write_ev); event_free (c->read_ev); rotate_port (c); struct connection_buffer *b = c->out_head; while (b) { struct connection_buffer *d = b; b = b->next; delete_connection_buffer (d); } b = c->in_head; while (b) { struct connection_buffer *d = b; b = b->next; delete_connection_buffer (d); } c->out_head = c->out_tail = c->in_head = c->in_tail = 0; c->state = conn_failed; c->out_bytes = c->in_bytes = 0; close (c->fd); Connections[c->fd] = 0; vlogprintf (E_NOTICE, "Lost connection to server... %s:%d\n", c->ip, c->port); restart_connection (c); } //extern FILE *log_net_f; static void try_write (struct connection *c) { struct tgl_state *TLS = c->TLS; vlogprintf (E_DEBUG, "try write: fd = %d\n", c->fd); int x = 0; while (c->out_head) { int r = write (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr); if (r >= 0) { x += r; c->out_head->rptr += r; if (c->out_head->rptr != c->out_head->wptr) { break; } struct connection_buffer *b = c->out_head; c->out_head = b->next; if (!c->out_head) { c->out_tail = 0; } delete_connection_buffer (b); } else { if (errno != EAGAIN && errno != EWOULDBLOCK) { vlogprintf (E_NOTICE, "fail_connection: write_error %s\n", strerror(errno)); fail_connection (c); return; } else { break; } } } vlogprintf (E_DEBUG, "Sent %d bytes to %d\n", x, c->fd); c->out_bytes -= x; } static void try_rpc_read (struct connection *c) { assert (c->in_head); struct tgl_state *TLS = c->TLS; while (1) { if (c->in_bytes < 1) { return; } unsigned len = 0; unsigned t = 0; assert (tgln_read_in_lookup (c, &len, 1) == 1); if (len >= 1 && len <= 0x7e) { if (c->in_bytes < (int)(1 + 4 * len)) { return; } } else { if (c->in_bytes < 4) { return; } assert (tgln_read_in_lookup (c, &len, 4) == 4); len = (len >> 8); if (c->in_bytes < (int)(4 + 4 * len)) { return; } len = 0x7f; } if (len >= 1 && len <= 0x7e) { assert (tgln_read_in (c, &t, 1) == 1); assert (t == len); assert (len >= 1); } else { assert (len == 0x7f); assert (tgln_read_in (c, &len, 4) == 4); len = (len >> 8); assert (len >= 1); } len *= 4; int op; assert (tgln_read_in_lookup (c, &op, 4) == 4); if (c->methods->execute (TLS, c, op, len) < 0) { return; } } } static void try_read (struct connection *c) { struct tgl_state *TLS = c->TLS; vlogprintf (E_DEBUG, "try read: fd = %d\n", c->fd); if (!c->in_tail) { c->in_head = c->in_tail = new_connection_buffer (1 << 20); } #ifdef EVENT_V1 struct timeval tv = {5, 0}; event_add (c->read_ev, &tv); #endif int x = 0; while (1) { int r = read (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr); if (r > 0) { c->last_receive_time = tglt_get_double_time (); stop_ping_timer (c); start_ping_timer (c); } if (r >= 0) { c->in_tail->wptr += r; x += r; if (c->in_tail->wptr != c->in_tail->end) { break; } struct connection_buffer *b = new_connection_buffer (1 << 20); c->in_tail->next = b; c->in_tail = b; } else { if (errno != EAGAIN && errno != EWOULDBLOCK) { vlogprintf (E_NOTICE, "fail_connection: read_error %s\n", strerror(errno)); fail_connection (c); return; } else { break; } } } vlogprintf (E_DEBUG, "Received %d bytes from %d\n", x, c->fd); c->in_bytes += x; if (x) { try_rpc_read (c); } } static void incr_out_packet_num (struct connection *c) { c->out_packet_num ++; } static struct tgl_dc *get_dc (struct connection *c) { return c->dc; } static struct tgl_session *get_session (struct connection *c) { return c->session; } static void tgln_free (struct connection *c) { if (c->ip) { tfree_str (c->ip); } if (c->ping_ev) { event_free (c->ping_ev); } if (c->fail_ev) { event_free (c->fail_ev); } if (c->read_ev) { event_free (c->read_ev); } if (c->write_ev) { event_free (c->write_ev); } struct connection_buffer *b = c->out_head; while (b) { struct connection_buffer *d = b; b = b->next; delete_connection_buffer (d); } b = c->in_head; while (b) { struct connection_buffer *d = b; b = b->next; delete_connection_buffer (d); } if (c->fd >= 0) { Connections[c->fd] = 0; close (c->fd); } tfree (c, sizeof (*c)); } struct tgl_net_methods tgl_conn_methods = { .write_out = tgln_write_out, .read_in = tgln_read_in, .read_in_lookup = tgln_read_in_lookup, .flush_out = tgln_flush_out, .incr_out_packet_num = incr_out_packet_num, .get_dc = get_dc, .get_session = get_session, .create_connection = tgln_create_connection, .free = tgln_free }; ================================================ FILE: tgl-net.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __NET_H__ #define __NET_H__ extern struct tgl_net_methods tgl_conn_methods; #endif ================================================ FILE: tgl-queries.h ================================================ #ifndef __TGL_QUERIES_H__ #define __TGL_QUERIES_H__ #include "tgl.h" void tgl_do_get_terms_of_service (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *ans), void *callback_extra); /* {{{ WORK WITH ACCOUNT */ // sets account password // user will be requested to type his current password and new password (twice) void tgl_do_set_password (struct tgl_state *TLS, const char *hint, int hint_len, void (*callback)(struct tgl_state *TLS, void *extra, int success), void *extra); void tgl_do_set_phone_number (struct tgl_state *TLS, const char *phonenumber, int phonenumber_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); /* }}} */ /* {{{ SENDING MESSAGES */ struct tl_ds_reply_markup; // send plain text message to peer id // flags is combination of TGL_SEND_MSG_FLAG_* // reply markup can be NULL void tgl_do_send_message (struct tgl_state *TLS, tgl_peer_id_t peer_id, const char *text, int text_len, unsigned long long flags, struct tl_ds_reply_markup *reply_markup, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // sends plain text reply on message *reply_id* // message *reply_id* should be cached void tgl_do_reply_message (struct tgl_state *TLS, tgl_message_id_t *msg_id, const char *text, int text_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // sends contents of text file *file_name* as plain text message void tgl_do_send_text (struct tgl_state *TLS, tgl_peer_id_t peer_id, const char *file_name, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); void tgl_do_reply_text (struct tgl_state *TLS, tgl_message_id_t *msg_id, const char *file_name, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // send media from file *file_name* to peer *to_id* // if reply > 0 this message is sent as reply to message *reply* // *caption* is used only for photos void tgl_do_send_document (struct tgl_state *TLS, tgl_peer_id_t to_id, const char *file_name, const char *caption, int caption_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); void tgl_do_reply_document (struct tgl_state *TLS, tgl_message_id_t *msg_id, const char *file_name, const char *caption, int caption_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // forward message *msg_id* to peer *id* // message can not be encrypted and peer can not be secret chat void tgl_do_forward_message (struct tgl_state *TLS, tgl_user_or_chat_id_t id, tgl_message_id_t *msg_id, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // forward messages *ids* to peer *id* // messages can not be encrypted and peer can not be secret chat void tgl_do_forward_messages (struct tgl_state *TLS, tgl_user_or_chat_id_t id, int size, const tgl_message_id_t *msg_ids[], unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int count, struct tgl_message *ML[]), void *callback_extra); // sends contact to another user. // This contact may be or may not be telegram user void tgl_do_send_contact (struct tgl_state *TLS, tgl_peer_id_t id, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // reply on message *reply_id* with contact void tgl_do_reply_contact (struct tgl_state *TLS, tgl_message_id_t *reply_id, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // sends media from message *msg_id* to another dialog // a bit different from forwarding message with media // secret message media can be forwarded to secret chats // and non-secret - to non-secret chats and users void tgl_do_forward_media (struct tgl_state *TLS, tgl_peer_id_t id, tgl_message_id_t *msg_id, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // sends location to chat *id* void tgl_do_send_location (struct tgl_state *TLS, tgl_peer_id_t id, double latitude, double longitude, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // replies on message *reply_id* with location void tgl_do_reply_location (struct tgl_state *TLS, tgl_message_id_t *reply_id, double latitude, double longitude, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // sends broadcast (i.e. message to several users at once) // flags are same as in tgl_do_send_message void tgl_do_send_broadcast (struct tgl_state *TLS, int num, tgl_user_id_t id[], const char *text, int text_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *extra, int success, int num, struct tgl_message *ML[]), void *callback_extra); /* }}} */ /* {{{ EDITING SELF PROFILE */ // sets self profile photo // server will cut central square from this photo void tgl_do_set_profile_photo (struct tgl_state *TLS, const char *file_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // rename self account void tgl_do_set_profile_name (struct tgl_state *TLS, const char *first_name, int first_name_len, const char *last_name, int last_name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra); // sets self username void tgl_do_set_username (struct tgl_state *TLS, const char *username, int username_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra); // updates online/offline status void tgl_do_update_status (struct tgl_state *TLS, int online, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // exports card. This card can be later be used by another user to add you to dialog list. void tgl_do_export_card (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, int *card), void *callback_extra); /* }}} */ /* {{{ WORKING WITH GROUP CHATS */ // sets chat photo // server will cut central square from this photo void tgl_do_set_chat_photo (struct tgl_state *TLS, tgl_chat_id_t chat_id, const char *file_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // sets chat title void tgl_do_rename_chat (struct tgl_state *TLS, tgl_chat_id_t id, const char *new_title, int new_title_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // requests full info about chat *id*. // if *offline_mode* is set no actual query is sent void tgl_do_get_chat_info (struct tgl_state *TLS, tgl_chat_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_chat *C), void *callback_extra); // adds user *id* to chat *chat_id* // sends *limit* last messages from this chat to user void tgl_do_add_user_to_chat (struct tgl_state *TLS, tgl_chat_id_t chat_id, tgl_user_id_t id, int limit, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // deleted user *id* from chat *chat_id* // you can do it if you are admin (=creator) of chat or if you invited this user or if it is yourself void tgl_do_del_user_from_chat (struct tgl_state *TLS, tgl_chat_id_t chat_id, tgl_user_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // creates group chat with users ids // there should be at least one user other then you in chat void tgl_do_create_group_chat (struct tgl_state *TLS, int users_num, tgl_user_id_t ids[], const char *chat_topic, int chat_topic_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // receives invitation link to this chat // only chat admin can create one // prevoius link invalidated, if existed void tgl_do_export_chat_link (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *link), void *callback_extra); // joins to secret chat by link (or hash of this link) void tgl_do_import_chat_link (struct tgl_state *TLS, const char *link, int link_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // upgrades chat to channel. void tgl_do_upgrade_group (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); /* }}} */ /* {{{ WORKING WITH USERS */ // requests full info about user *id*. // if *offline_mode* is set no actual query is sent void tgl_do_get_user_info (struct tgl_state *TLS, tgl_user_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra); // adds contact to contact list by phone number // user will be named *first_name* *last_name* in contact list // force should be set to 0 void tgl_do_add_contact (struct tgl_state *TLS, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra); // deletes user *id* from contact list void tgl_do_del_contact (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // imports card exported by another user void tgl_do_import_card (struct tgl_state *TLS, int size, int *card, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra); // blocks user void tgl_do_block_user (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // unblocks blocked user void tgl_do_unblock_user (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); /* }}} */ /* {{{ WORKING WITH SECRET CHATS */ // requests creation of secret chat with user *user_id* //void tgl_do_create_encr_chat_request (struct tgl_state *TLS, int user_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); // accepts secret chat request // method can fail if another device will be first to accept it void tgl_do_accept_encr_chat_request (struct tgl_state *TLS, struct tgl_secret_chat *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); // sets ttl of secret chat void tgl_do_set_encr_chat_ttl (struct tgl_state *TLS, struct tgl_secret_chat *E, int ttl, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); // returns secret chat fingerprint int tgl_do_visualize_key (struct tgl_state *TLS, tgl_secret_chat_id_t id, unsigned char buf[16]); // requests creation of secret chat with user id void tgl_do_create_secret_chat (struct tgl_state *TLS, tgl_user_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); // cancel a working secret chat void tgl_do_discard_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); /* }}} */ /* {{{ WORKING WITH CHANNELS */ void tgl_do_get_channels_dialog_list (struct tgl_state *TLS, int limit, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]), void *callback_extra); void tgl_do_get_channel_info (struct tgl_state *TLS, tgl_peer_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_channel *C), void *callback_extra); void tgl_do_rename_channel (struct tgl_state *TLS, tgl_peer_id_t id, const char *name, int name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_set_channel_photo (struct tgl_state *TLS, tgl_peer_id_t chat_id, const char *file_name, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success), void *callback_extra); void tgl_do_channel_set_about (struct tgl_state *TLS, tgl_peer_id_t id, const char *about, int about_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_create_channel (struct tgl_state *TLS, int users_num, tgl_peer_id_t ids[], const char *chat_topic, int chat_topic_len, const char *about, int about_len, unsigned long long flags, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_channel_set_username (struct tgl_state *TLS, tgl_peer_id_t id, const char *username, int username_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_join_channel (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_leave_channel (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_channel_invite_user (struct tgl_state *TLS, tgl_peer_id_t channel_id, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_channel_kick_user (struct tgl_state *TLS, tgl_peer_id_t channel_id, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_export_channel_link (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *link), void *callback_extra); // type: // 0 - none // 1 - moderator // 2 - editor // 3 - kicked void tgl_do_channel_set_admin (struct tgl_state *TLS, tgl_peer_id_t channel_id, tgl_peer_id_t user_id, int type, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); void tgl_do_channel_get_members (struct tgl_state *TLS, tgl_peer_id_t channel_id, int limit, int offset, int type, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *UL[]), void *callback_extra); /* }}} */ /* {{{ WORKING WITH DIALOG LIST */ // receives all dialogs (except secret chats) from offset=*offset* with limit=*limit* // dialogs are sorted by last message received // if limit is > 100 there is a (small) chance of one dialog received twice void tgl_do_get_dialog_list (struct tgl_state *TLS, int limit, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]), void *callback_extra); // resolves username void tgl_do_contact_search (struct tgl_state *TLS, const char *name, int name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, tgl_peer_t *U), void *callback_extra); // requests contact list void tgl_do_update_contact_list (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *contacts[]), void *callback_extra); /* }}} */ /* {{{ WORKING WITH ONE DIALOG */ // marks all inbound messages from peer id as read void tgl_do_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // extended mark read void tgl_do_messages_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, int max_id, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra); // requests last *limit* from offset *offset* (offset = 0 means most recent) messages from dialog with peer id // if offline_mode=1 then no actual query is sent // only locally cached messages returned // also marks messages from this chat as read void tgl_do_get_history (struct tgl_state *TLS, tgl_peer_id_t id, int offset, int limit, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra); // sends typing event to chat // set status=tgl_typing_typing for default typing event void tgl_do_send_typing (struct tgl_state *TLS, tgl_peer_id_t id, enum tgl_typing_status status, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); /* }}} */ /* {{{ WORKING WITH MEDIA */ // loads photo/document/document_thumb to downloads directory // if file is presented it is not redownloaded (but if it is shortened tail will be downloaded) // returns file name in callback void tgl_do_load_photo (struct tgl_state *TLS, struct tgl_photo *photo, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); void tgl_do_load_encr_document (struct tgl_state *TLS, struct tgl_encr_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); void tgl_do_load_document (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); void tgl_do_load_video (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); void tgl_do_load_audio (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); void tgl_do_load_audio (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); void tgl_do_load_document_thumb (struct tgl_state *TLS, struct tgl_document *video, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); // loads file by location. Use only for small files! void tgl_do_load_file_location (struct tgl_state *TLS, struct tgl_file_location *FL, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *file_name), void *callback_extra); /* }}} */ /* {{{ ANOTHER MESSAGES FUNCTIONS */ // search messages with ids *from* .. *to* in dialog id // id type of id is UNKNOWN uses global search (in all dialogs) instead // if *from* or *to* is means *from*=0 and *to*=+INF // return up to *limit* entries from offset=*offset* void tgl_do_msg_search (struct tgl_state *TLS, tgl_user_or_chat_id_t id, int from, int to, int limit, int offset, const char *query, int query_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra); // deletes message *id* void tgl_do_delete_msg (struct tgl_state *TLS, tgl_message_id_t *msg_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); // gets message by *id* void tgl_do_get_message (struct tgl_state *TLS, tgl_message_id_t *msg_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra); /* }}} */ /* {{{ EXTENDED QUERIES USE WITH CAUTION */ //#ifndef DISABLE_EXTF // sends query with extended text syntax // use only for debug or when you known what are you doing // since answer is not interpreted by library in any way void tgl_do_send_extf (struct tgl_state *TLS, const char *data, int data_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, const char *data), void *callback_extra); int tglf_extf_autocomplete (struct tgl_state *TLS, const char *text, int text_len, int index, char **R, char *data, int data_len); struct paramed_type *tglf_extf_store (struct tgl_state *TLS, const char *data, int data_len); char *tglf_extf_fetch (struct tgl_state *TLS, struct paramed_type *T); //#endif /* }}} */ /* {{{ BOT */ void tgl_do_start_bot (struct tgl_state *TLS, tgl_peer_id_t bot, tgl_peer_id_t chat, const char *str, int str_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); /* }}} */ #endif ================================================ FILE: tgl-structures.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __STRUCTURES_H__ #define __STRUCTURES_H__ #include #include "tgl-layout.h" #include "tgl-fetch.h" #include "tgl.h" char *tgls_default_create_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); void tgls_free_user (struct tgl_state *TLS, struct tgl_user *U); void tgls_free_chat (struct tgl_state *TLS, struct tgl_chat *U); void tgls_free_photo (struct tgl_state *TLS, struct tgl_photo *P); void tgls_free_message (struct tgl_state *TLS, struct tgl_message *M); void tgls_free_bot_info (struct tgl_state *TLS, struct tgl_bot_info *B); void tgls_clear_message (struct tgl_state *TLS, struct tgl_message *M); struct tgl_message *tglm_message_alloc (struct tgl_state *TLS, tgl_message_id_t *id); void tglm_message_insert_tree (struct tgl_state *TLS, struct tgl_message *M); void tglm_update_message_id (struct tgl_state *TLS, struct tgl_message *M, long long id); void tglm_message_insert (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_insert_unsent (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_remove_unsent (struct tgl_state *TLS, struct tgl_message *M); void tglm_send_all_unsent (struct tgl_state *TLS); void tglm_message_remove_tree (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_add_peer (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_del_peer (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_del_use (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_add_use (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_del_temp_id (struct tgl_state *TLS, struct tgl_message *M); void tglm_message_del_random_id (struct tgl_state *TLS, struct tgl_message *M); void tglp_peer_insert_name (struct tgl_state *TLS, tgl_peer_t *P); void tglp_peer_delete_name (struct tgl_state *TLS, tgl_peer_t *P); void tglp_insert_encrypted_chat (struct tgl_state *TLS, tgl_peer_t *P); void tglp_insert_user (struct tgl_state *TLS, tgl_peer_t *P); void tglp_insert_chat (struct tgl_state *TLS, tgl_peer_t *P); void tglp_insert_channel (struct tgl_state *TLS, tgl_peer_t *P); //enum tgl_typing_status tglf_fetch_typing_buf (void); void tgls_messages_mark_read (struct tgl_state *TLS, struct tgl_message *M, int out, int seq); //void tgls_insert_random2local (struct tgl_state *TLS, long long random_id, tgl_message_id_t *local_id); //void tgls_insert_temp2local (struct tgl_state *TLS, int temp_id, tgl_message_id_t *local_id); tgl_message_id_t *tgls_get_local_by_random (struct tgl_state *TLS, long long random_id); tgl_message_id_t *tgls_get_local_by_temp (struct tgl_state *TLS, int temp_id); void tgls_message_change_temp_id (struct tgl_state *TLS, struct tgl_message *M, int temp_id); void tgls_message_change_random_id (struct tgl_state *TLS, struct tgl_message *M, long long random_id); void tgl_photo_insert (struct tgl_state *TLS, struct tgl_photo *P); struct tgl_photo *tgl_photo_get (struct tgl_state *TLS, long long id); struct tgl_document *tgl_document_get (struct tgl_state *TLS, long long id); void tgl_document_insert (struct tgl_state *TLS, struct tgl_document *P); struct tgl_webpage *tgl_webpage_get (struct tgl_state *TLS, long long id); void tgl_webpage_insert (struct tgl_state *TLS, struct tgl_webpage *P); tgl_message_id_t tgl_convert_temp_msg_id (struct tgl_state *TLS, tgl_message_id_t msg_id); static inline tgl_peer_id_t tgl_msg_id_to_peer_id (tgl_message_id_t msg_id) { tgl_peer_id_t id; id.peer_type = msg_id.peer_type; id.peer_id = msg_id.peer_id; id.access_hash = msg_id.access_hash; return id; } static inline tgl_message_id_t tgl_peer_id_to_msg_id (tgl_peer_id_t peer_id, long long msg_id) { tgl_message_id_t id; id.peer_type = peer_id.peer_type; id.peer_id = peer_id.peer_id; id.access_hash = peer_id.access_hash; id.id = msg_id; return id; } static inline tgl_message_id_t tgl_peer_id_to_random_msg_id (tgl_peer_id_t peer_id) { long long id; tglt_secure_random (&id, 8); return tgl_peer_id_to_msg_id (peer_id, id); } #endif ================================================ FILE: tgl-timers.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #include "config.h" #ifdef EVENT_V2 #include #include #include #else #include #include "event-old.h" #endif #include "tgl.h" #include static void timer_alarm (evutil_socket_t fd, short what, void *arg) { void **p = arg; ((void (*)(struct tgl_state *, void *))p[1]) (p[0], p[2]); } struct tgl_timer *tgl_timer_alloc (struct tgl_state *TLS, void (*cb)(struct tgl_state *TLS, void *arg), void *arg) { void **p = malloc (sizeof (void *) * 3); p[0] = TLS; p[1] = cb; p[2] = arg; return (void *)evtimer_new (TLS->ev_base, timer_alarm, p); } void tgl_timer_insert (struct tgl_timer *t, double p) { if (p < 0) { p = 0; } double e = p - (int)p; if (e < 0) { e = 0; } struct timeval pv = { (int)p, (int)(e * 1e6)}; event_add ((void *)t, &pv); } void tgl_timer_delete (struct tgl_timer *t) { event_del ((void *)t); } void tgl_timer_free (struct tgl_timer *t) { void *arg = event_get_callback_arg ((void *)t); free (arg); event_free ((void *)t); } struct tgl_timer_methods tgl_libevent_timers = { .alloc = tgl_timer_alloc, .insert = tgl_timer_insert, .remove = tgl_timer_delete, .free = tgl_timer_free }; ================================================ FILE: tgl-timers.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __TGL_TIMERS_H__ #define __TGL_TIMERS_H__ #include "tgl.h" extern struct tgl_timer_methods tgl_libevent_timers; #endif ================================================ FILE: tgl.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "crypto/rsa_pem.h" #include "tgl.h" #include "tools.h" #include "mtproto-client.h" #include "tgl-structures.h" //#include "net.h" #include struct tgl_state tgl_state; void tgl_set_binlog_mode (struct tgl_state *TLS, int mode) { TLS->binlog_enabled = mode; } void tgl_set_binlog_path (struct tgl_state *TLS, const char *path) { TLS->binlog_name = tstrdup (path); } void tgl_set_auth_file_path (struct tgl_state *TLS, const char *path) { TLS->auth_file = tstrdup (path); } void tgl_set_download_directory (struct tgl_state *TLS, const char *path) { if (TLS->downloads_directory) { tfree_str (TLS->downloads_directory); } TLS->downloads_directory = tstrdup (path); } void tgl_set_callback (struct tgl_state *TLS, struct tgl_update_callback *cb) { TLS->callback = *cb; } void tgl_set_rsa_key (struct tgl_state *TLS, const char *key) { assert (TLS->rsa_key_num < TGL_MAX_RSA_KEYS_NUM); TLS->rsa_key_list[TLS->rsa_key_num ++] = tstrdup (key); } void tgl_set_rsa_key_direct (struct tgl_state *TLS, unsigned long e, int n_bytes, const unsigned char *n) { assert (TLS->rsa_key_num < TGL_MAX_RSA_KEYS_NUM); TLS->rsa_key_list[TLS->rsa_key_num] = NULL; TLS->rsa_key_loaded[TLS->rsa_key_num] = TGLC_rsa_new (e, n_bytes, n); TLS->rsa_key_num ++; } int tgl_init (struct tgl_state *TLS) { assert (TLS->timer_methods); assert (TLS->net_methods); if (!TLS->callback.create_print_name) { TLS->callback.create_print_name = tgls_default_create_print_name; } if (!TLS->temp_key_expire_time) { TLS->temp_key_expire_time = 100000; } TLS->message_list.next_use = &TLS->message_list; TLS->message_list.prev_use = &TLS->message_list; if (tglmp_on_start (TLS) < 0) { return -1; } if (!TLS->app_id) { TLS->app_id = TG_APP_ID; TLS->app_hash = tstrdup (TG_APP_HASH); } return 0; } int tgl_authorized_dc (struct tgl_state *TLS, struct tgl_dc *DC) { assert (DC); return (DC->flags & 4) != 0;//DC->auth_key_id; } int tgl_signed_dc (struct tgl_state *TLS, struct tgl_dc *DC) { assert (DC); return (DC->flags & TGLDCF_LOGGED_IN) != 0; } void tgl_register_app_id (struct tgl_state *TLS, int app_id, const char *app_hash) { TLS->app_id = app_id; TLS->app_hash = tstrdup (app_hash); } struct tgl_state *tgl_state_alloc (void) { return (struct tgl_state *)talloc0 (sizeof (struct tgl_state)); } void tgl_incr_verbosity (struct tgl_state *TLS) { TLS->verbosity ++; } void tgl_set_verbosity (struct tgl_state *TLS, int val) { TLS->verbosity = val; } void tgl_enable_pfs (struct tgl_state *TLS) { TLS->enable_pfs = 1; } void tgl_set_test_mode (struct tgl_state *TLS) { TLS->test_mode ++; } void tgl_set_net_methods (struct tgl_state *TLS, struct tgl_net_methods *methods) { TLS->net_methods = methods; } void tgl_set_timer_methods (struct tgl_state *TLS, struct tgl_timer_methods *methods) { TLS->timer_methods = methods; } void tgl_set_ev_base (struct tgl_state *TLS, void *ev_base) { TLS->ev_base = ev_base; } void tgl_set_app_version (struct tgl_state *TLS, const char *app_version) { if (TLS->app_version) { tfree_str (TLS->app_version); } TLS->app_version = tstrdup (app_version); } void tgl_enable_ipv6 (struct tgl_state *TLS) { TLS->ipv6_enabled = 1; } void tgl_disable_link_preview (struct tgl_state *TLS) { TLS->disable_link_preview = 1; } void tgl_enable_bot (struct tgl_state *TLS) { TLS->is_bot = 1; } ================================================ FILE: tgl.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2014-2015 */ #ifndef __TGL_H__ #define __TGL_H__ #include "crypto/bn.h" #include "tgl-layout.h" #include #include #define TGL_MAX_DC_NUM 100 #define TG_SERVER_1 "149.154.175.50" #define TG_SERVER_2 "149.154.167.51" #define TG_SERVER_3 "149.154.175.100" #define TG_SERVER_4 "149.154.167.91" #define TG_SERVER_5 "149.154.171.5" #define TG_SERVER_IPV6_1 "2001:b28:f23d:f001::a" #define TG_SERVER_IPV6_2 "2001:67c:4e8:f002::a" #define TG_SERVER_IPV6_3 "2001:b28:f23d:f003::a" #define TG_SERVER_IPV6_4 "2001:67c:4e8:f004::a" #define TG_SERVER_IPV6_5 "2001:b28:f23f:f005::a" #define TG_SERVER_DEFAULT 2 #define TG_SERVER_TEST_1 "149.154.175.10" #define TG_SERVER_TEST_2 "149.154.167.40" #define TG_SERVER_TEST_3 "149.154.175.117" #define TG_SERVER_TEST_IPV6_1 "2001:b28:f23d:f001::e" #define TG_SERVER_TEST_IPV6_2 "2001:67c:4e8:f002::e" #define TG_SERVER_TEST_IPV6_3 "2001:b28:f23d:f003::e" #define TG_SERVER_TEST_DEFAULT 2 #define TGL_VERSION "2.1.0" #define TGL_ENCRYPTED_LAYER 17 #define TGL_SCHEME_LAYER 45 struct connection; struct mtproto_methods; struct tgl_session; struct tgl_dc; #define TGL_UPDATE_CREATED 1 #define TGL_UPDATE_DELETED 2 #define TGL_UPDATE_PHONE 4 #define TGL_UPDATE_CONTACT 8 #define TGL_UPDATE_PHOTO 16 #define TGL_UPDATE_BLOCKED 32 #define TGL_UPDATE_REAL_NAME 64 #define TGL_UPDATE_NAME 128 #define TGL_UPDATE_REQUESTED 256 #define TGL_UPDATE_WORKING 512 #define TGL_UPDATE_FLAGS 1024 #define TGL_UPDATE_TITLE 2048 #define TGL_UPDATE_ADMIN 4096 #define TGL_UPDATE_MEMBERS 8192 #define TGL_UPDATE_ACCESS_HASH 16384 #define TGL_UPDATE_USERNAME (1 << 15) /*struct tgl_allocator { void *(*alloc)(size_t size); void *(*realloc)(void *ptr, size_t old_size, size_t size); void (*free)(void *ptr, int size); void (*check)(void); void (*exists)(void *ptr, int size); };*/ struct tgl_allocator; extern struct tgl_allocator tgl_allocator_release; extern struct tgl_allocator tgl_allocator_debug; struct tgl_state; enum tgl_value_type { tgl_phone_number, // user phone number tgl_code, // telegram login code, or 'call' for phone call request tgl_register_info, // "Y/n" register?, first name, last name tgl_new_password, // new pass, confirm new pass tgl_cur_and_new_password, // curr pass, new pass, confirm new pass tgl_cur_password, // current pass tgl_bot_hash }; struct tgl_update_callback { void (*new_msg)(struct tgl_state *TLS, struct tgl_message *M); void (*marked_read)(struct tgl_state *TLS, int num, struct tgl_message *list[]); void (*logprintf)(const char *format, ...) __attribute__ ((format (__printf__, 1, 2))); void (*get_values)(struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg); void (*logged_in)(struct tgl_state *TLS); void (*started)(struct tgl_state *TLS); void (*type_notification)(struct tgl_state *TLS, struct tgl_user *U, enum tgl_typing_status status); void (*type_in_chat_notification)(struct tgl_state *TLS, struct tgl_user *U, struct tgl_chat *C, enum tgl_typing_status status); void (*type_in_secret_chat_notification)(struct tgl_state *TLS, struct tgl_secret_chat *E); void (*status_notification)(struct tgl_state *TLS, struct tgl_user *U); void (*user_registered)(struct tgl_state *TLS, struct tgl_user *U); void (*user_activated)(struct tgl_state *TLS, struct tgl_user *U); void (*new_authorization)(struct tgl_state *TLS, const char *device, const char *location); void (*chat_update)(struct tgl_state *TLS, struct tgl_chat *C, unsigned flags); void (*channel_update)(struct tgl_state *TLS, struct tgl_channel *C, unsigned flags); void (*user_update)(struct tgl_state *TLS, struct tgl_user *C, unsigned flags); void (*secret_chat_update)(struct tgl_state *TLS, struct tgl_secret_chat *C, unsigned flags); void (*msg_receive)(struct tgl_state *TLS, struct tgl_message *M); void (*our_id)(struct tgl_state *TLS, tgl_peer_id_t id); void (*notification)(struct tgl_state *TLS, const char *type, const char *message); void (*user_status_update)(struct tgl_state *TLS, struct tgl_user *U); char *(*create_print_name) (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); void (*on_failed_login) (struct tgl_state *TLS); }; struct tgl_net_methods { int (*write_out) (struct connection *c, const void *data, int len); int (*read_in) (struct connection *c, void *data, int len); int (*read_in_lookup) (struct connection *c, void *data, int len); void (*flush_out) (struct connection *c); void (*incr_out_packet_num) (struct connection *c); void (*free) (struct connection *c); struct tgl_dc *(*get_dc) (struct connection *c); struct tgl_session *(*get_session) (struct connection *c); struct connection *(*create_connection) (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods); }; struct mtproto_methods { int (*ready) (struct tgl_state *TLS, struct connection *c); int (*close) (struct tgl_state *TLS, struct connection *c); int (*execute) (struct tgl_state *TLS, struct connection *c, int op, int len); }; struct tgl_timer; struct tree_random_id; struct tree_temp_id; struct tgl_timer_methods { struct tgl_timer *(*alloc) (struct tgl_state *TLS, void (*cb)(struct tgl_state *TLS, void *arg), void *arg); void (*insert) (struct tgl_timer *t, double timeout); void (*remove) (struct tgl_timer *t); void (*free) (struct tgl_timer *t); }; #define E_ERROR 0 #define E_WARNING 1 #define E_NOTICE 2 #define E_DEBUG 6 #define TGL_LOCK_DIFF 1 #define TGL_LOCK_PASSWORD 2 #define TGL_MAX_RSA_KEYS_NUM 10 // Do not modify this structure, unless you know what you do #pragma pack(push,4) struct tgl_state { tgl_peer_id_t our_id; int encr_root; unsigned char *encr_prime; TGLC_bn *encr_prime_bn; int encr_param_version; int pts; int qts; int date; int seq; int binlog_enabled; int test_mode; int verbosity; int unread_messages; int active_queries; int max_msg_id; int started; int disable_link_preview; long long locks; struct tgl_dc *DC_list[TGL_MAX_DC_NUM]; struct tgl_dc *DC_working; int max_dc_num; int dc_working_num; int enable_pfs; int temp_key_expire_time; long long cur_uploading_bytes; long long cur_uploaded_bytes; long long cur_downloading_bytes; long long cur_downloaded_bytes; char *binlog_name; char *auth_file; char *downloads_directory; struct tgl_update_callback callback; struct tgl_net_methods *net_methods; void *ev_base; char *rsa_key_list[TGL_MAX_RSA_KEYS_NUM]; // (TGLC_rsa *) void *rsa_key_loaded[TGL_MAX_RSA_KEYS_NUM]; long long rsa_key_fingerprint[TGL_MAX_RSA_KEYS_NUM]; int rsa_key_num; TGLC_bn_ctx *TGLC_bn_ctx; struct tgl_allocator *allocator; struct tree_peer *peer_tree; struct tree_peer_by_name *peer_by_name_tree; struct tree_message *message_tree; struct tree_message *message_unsent_tree; struct tree_photo *photo_tree; struct tree_document *document_tree; struct tree_webpage *webpage_tree; struct tree_encr_document *encr_document_tree; int users_allocated; int chats_allocated; int messages_allocated; int channels_allocated; int peer_num; int peer_size; int encr_chats_allocated; int geo_chats_allocated; tgl_peer_t **Peers; struct tgl_message message_list; int binlog_fd; struct tgl_timer_methods *timer_methods; struct tree_query *queries_tree; char *base_path; struct tree_user *online_updates; struct tgl_timer *online_updates_timer; int app_id; char *app_hash; void *ev_login; char *app_version; int ipv6_enabled; struct tree_random_id *random_id_tree; struct tree_temp_id *temp_id_tree; char *error; int error_code; int is_bot; int last_temp_id; }; #pragma pack(pop) //extern struct tgl_state tgl_state; #ifdef __cplusplus extern "C" { #endif void tgl_reopen_binlog_for_writing (struct tgl_state *TLS); void tgl_replay_log (struct tgl_state *TLS); int tgl_print_stat (struct tgl_state *TLS, char *s, int len); tgl_peer_t *tgl_peer_get (struct tgl_state *TLS, tgl_peer_id_t id); tgl_peer_t *tgl_peer_get_by_name (struct tgl_state *TLS, const char *s); struct tgl_message *tgl_message_get (struct tgl_state *TLS, tgl_message_id_t *id); void tgl_peer_iterator_ex (struct tgl_state *TLS, void (*it)(tgl_peer_t *P, void *extra), void *extra); int tgl_complete_user_list (struct tgl_state *TLS, int index, const char *text, int len, char **R); int tgl_complete_chat_list (struct tgl_state *TLS, int index, const char *text, int len, char **R); int tgl_complete_encr_chat_list (struct tgl_state *TLS, int index, const char *text, int len, char **R); int tgl_complete_peer_list (struct tgl_state *TLS, int index, const char *text, int len, char **R); int tgl_complete_channel_list (struct tgl_state *TLS, int index, const char *text, int len, char **R); int tgl_secret_chat_for_user (struct tgl_state *TLS, tgl_peer_id_t user_id); int tgl_do_send_bot_auth (struct tgl_state *TLS, const char *code, int code_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra); #define TGL_PEER_USER 1 #define TGL_PEER_CHAT 2 #define TGL_PEER_GEO_CHAT 3 #define TGL_PEER_ENCR_CHAT 4 #define TGL_PEER_CHANNEL 5 #define TGL_PEER_TEMP_ID 100 #define TGL_PEER_RANDOM_ID 101 #define TGL_PEER_UNKNOWN 0 #define TGL_MK_USER(id) tgl_set_peer_id (TGL_PEER_USER,id) #define TGL_MK_CHAT(id) tgl_set_peer_id (TGL_PEER_CHAT,id) #define TGL_MK_CHANNEL(id) tgl_set_peer_id (TGL_PEER_CHANNEL,id) #define TGL_MK_GEO_CHAT(id) tgl_set_peer_id (TGL_PEER_GEO_CHAT,id) #define TGL_MK_ENCR_CHAT(id) tgl_set_peer_id (TGL_PEER_ENCR_CHAT,id) void tgl_set_binlog_mode (struct tgl_state *TLS, int mode); void tgl_set_binlog_path (struct tgl_state *TLS, const char *path); void tgl_set_auth_file_path (struct tgl_state *TLS, const char *path); void tgl_set_download_directory (struct tgl_state *TLS, const char *path); void tgl_set_callback (struct tgl_state *TLS, struct tgl_update_callback *cb); void tgl_set_rsa_key (struct tgl_state *TLS, const char *key); void tgl_set_rsa_key_direct (struct tgl_state *TLS, unsigned long e, int n_bytes, const unsigned char *n); void tgl_set_app_version (struct tgl_state *TLS, const char *app_version); static inline int tgl_get_peer_type (tgl_peer_id_t id) { return id.peer_type; } static inline int tgl_get_peer_id (tgl_peer_id_t id) { return id.peer_id; } static inline tgl_peer_id_t tgl_set_peer_id (int type, int id) { tgl_peer_id_t ID; ID.peer_id = id; ID.peer_type = type; ID.access_hash = 0; return ID; } static inline int tgl_cmp_peer_id (tgl_peer_id_t a, tgl_peer_id_t b) { return memcmp (&a, &b, 8); } void tgl_incr_verbosity (struct tgl_state *TLS); void tgl_set_verbosity (struct tgl_state *TLS, int val); void tgl_enable_pfs (struct tgl_state *TLS); void tgl_set_test_mode (struct tgl_state *TLS); void tgl_set_net_methods (struct tgl_state *TLS, struct tgl_net_methods *methods); void tgl_set_timer_methods (struct tgl_state *TLS, struct tgl_timer_methods *methods); void tgl_set_ev_base (struct tgl_state *TLS, void *ev_base); int tgl_authorized_dc (struct tgl_state *TLS, struct tgl_dc *DC); int tgl_signed_dc (struct tgl_state *TLS, struct tgl_dc *DC); int tgl_init (struct tgl_state *TLS); void tgl_dc_authorize (struct tgl_state *TLS, struct tgl_dc *DC); void tgl_dc_iterator (struct tgl_state *TLS, void (*iterator)(struct tgl_dc *DC)); void tgl_dc_iterator_ex (struct tgl_state *TLS, void (*iterator)(struct tgl_dc *DC, void *extra), void *extra); #define TGL_SEND_MSG_FLAG_DISABLE_PREVIEW 1 #define TGL_SEND_MSG_FLAG_ENABLE_PREVIEW 2 #define TGL_SEND_MSG_FLAG_DOCUMENT_IMAGE TGLDF_IMAGE #define TGL_SEND_MSG_FLAG_DOCUMENT_STICKER TGLDF_STICKER #define TGL_SEND_MSG_FLAG_DOCUMENT_ANIMATED TGLDF_ANIMATED #define TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO TGLDF_AUDIO #define TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO TGLDF_VIDEO #define TGL_SEND_MSG_FLAG_DOCUMENT_AUTO 32 #define TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO 64 #define TGL_SEND_MSG_FLAG_REPLY(x) (((unsigned long long)x) << 32) typedef tgl_peer_id_t tgl_user_id_t; typedef tgl_peer_id_t tgl_chat_id_t; typedef tgl_peer_id_t tgl_secret_chat_id_t; typedef tgl_peer_id_t tgl_user_or_chat_id_t; void tgl_insert_empty_user (struct tgl_state *TLS, int id); void tgl_insert_empty_chat (struct tgl_state *TLS, int id); void tgl_free_all (struct tgl_state *TLS); void tgl_register_app_id (struct tgl_state *TLS, int app_id, const char *app_hash); void tgl_login (struct tgl_state *TLS); void tgl_enable_ipv6 (struct tgl_state *TLS); void tgl_enable_bot (struct tgl_state *TLS); struct tgl_state *tgl_state_alloc (void); void tgl_disable_link_preview (struct tgl_state *TLS); void tgl_do_lookup_state (struct tgl_state *TLS); long long tgl_get_allocated_bytes (void); #ifdef __cplusplus } #endif #endif ================================================ FILE: tools.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE #include #include #include #include #include "crypto/rand.h" #include #include #include //#include "interface.h" #include "tools.h" #ifdef __MACH__ #include #include #endif #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 #define CLOCK_MONOTONIC 1 #endif #ifdef WIN32 #include #include int vasprintf(char ** __restrict__ ret, const char * __restrict__ format, va_list ap) { int len; /* Get Length */ len = _vsnprintf(NULL,0,format,ap); if (len < 0) return -1; /* +1 for \0 terminator. */ *ret = malloc(len + 1); /* Check malloc fail*/ if (!*ret) return -1; /* Write String */ _vsnprintf(*ret,len+1,format,ap); /* Terminate explicitly */ (*ret)[len] = '\0'; return len; } int clock_gettime(int ignored, struct timespec *spec) { __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); wintime -= 116444736000000000; //1jan1601 to 1jan1970 spec->tv_sec = wintime / 10000000; //seconds spec->tv_nsec = wintime % 10000000 *100; //nano-seconds return 0; } #endif #ifdef VALGRIND_FIXES #include "valgrind/memcheck.h" #endif #define RES_PRE 8 #define RES_AFTER 8 #define MAX_BLOCKS 1000000 static void *blocks[MAX_BLOCKS]; static void *free_blocks[MAX_BLOCKS]; static int used_blocks; static int free_blocks_cnt; static long long total_allocated_bytes; void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2), weak)); void logprintf (const char *format, ...) { va_list ap; va_start (ap, format); vfprintf (stdout, format, ap); va_end (ap); } //extern int verbosity; //static long long total_allocated_bytes; int tgl_snprintf (char *buf, int len, const char *format, ...) { va_list ap; va_start (ap, format); int r = vsnprintf (buf, len, format, ap); va_end (ap); assert (r <= len && "tsnprintf buffer overflow"); return r; } int tgl_asprintf (char **res, const char *format, ...) { va_list ap; va_start (ap, format); int r = vasprintf (res, format, ap); assert (r >= 0); va_end (ap); void *rs = talloc (strlen (*res) + 1); memcpy (rs, *res, strlen (*res) + 1); free (*res); *res = rs; return r; } void tgl_free_debug (void *ptr, int size __attribute__ ((unused))) { if (!ptr) { assert (!size); return; } total_allocated_bytes -= size; ptr -= RES_PRE; if (size != (int)((*(int *)ptr) ^ 0xbedabeda)) { logprintf ("size = %d, ptr = %d\n", size, (*(int *)ptr) ^ 0xbedabeda); } assert (*(int *)ptr == (int)((size) ^ 0xbedabeda)); assert (*(int *)(ptr + RES_PRE + size) == (int)((size) ^ 0x7bed7bed)); assert (*(int *)(ptr + 4) == size); int block_num = *(int *)(ptr + 4 + RES_PRE + size); if (block_num >= used_blocks) { logprintf ("block_num = %d, used = %d\n", block_num, used_blocks); } assert (block_num < used_blocks); if (block_num < used_blocks - 1) { void *p = blocks[used_blocks - 1]; int s = (*(int *)p) ^ 0xbedabeda; *(int *)(p + 4 + RES_PRE + s) = block_num; blocks[block_num] = p; } blocks[--used_blocks] = 0; memset (ptr, 0, size + RES_PRE + RES_AFTER); *(int *)ptr = size + 12; free_blocks[free_blocks_cnt ++] = ptr; } void tgl_free_release (void *ptr, int size) { total_allocated_bytes -= size; memset (ptr, 0, size); free (ptr); } void *tgl_realloc_debug (void *ptr, size_t old_size __attribute__ ((unused)), size_t size) { void *p = talloc (size); memcpy (p, ptr, size >= old_size ? old_size : size); if (ptr) { tfree (ptr, old_size); } else { assert (!old_size); } return p; } void *tgl_realloc_release (void *ptr, size_t old_size __attribute__ ((unused)), size_t size) { total_allocated_bytes += (size - old_size); void *p = realloc (ptr, size); ensure_ptr (p); return p; } void *tgl_alloc_debug (size_t size) { total_allocated_bytes += size; void *p = malloc (size + RES_PRE + RES_AFTER); ensure_ptr (p); *(int *)p = size ^ 0xbedabeda; *(int *)(p + 4) = size; *(int *)(p + RES_PRE + size) = size ^ 0x7bed7bed; *(int *)(p + RES_AFTER + 4 + size) = used_blocks; blocks[used_blocks ++] = p; //tcheck (); return p + 8; } void *tgl_alloc_release (size_t size) { total_allocated_bytes += size; void *p = malloc (size); ensure_ptr (p); return p; } void *tgl_alloc0 (size_t size) { void *p = talloc (size); memset (p, 0, size); return p; } char *tgl_strdup (const char *s) { int l = strlen (s); char *p = talloc (l + 1); memcpy (p, s, l + 1); return p; } char *tgl_strndup (const char *s, size_t n) { size_t l = 0; for (l = 0; l < n && s[l]; l++) { } char *p = talloc (l + 1); memcpy (p, s, l); p[l] = 0; return p; } void *tgl_memdup (const void *s, size_t n) { void *r = talloc (n); memcpy (r, s, n); return r; } int tgl_inflate (void *input, int ilen, void *output, int olen) { z_stream strm; memset (&strm, 0, sizeof (strm)); assert (inflateInit2 (&strm, 16 + MAX_WBITS) == Z_OK); strm.avail_in = ilen; strm.next_in = input; strm.avail_out = olen ; strm.next_out = output; int err = inflate (&strm, Z_FINISH); int total_out = strm.total_out; if (err != Z_OK && err != Z_STREAM_END) { logprintf ( "inflate error = %d\n", err); logprintf ( "inflated %d bytes\n", (int) strm.total_out); total_out = 0; } inflateEnd (&strm); return total_out; } void tgl_check_debug (void) { int i; for (i = 0; i < used_blocks; i++) { void *ptr = blocks[i]; int size = (*(int *)ptr) ^ 0xbedabeda; if (!(*(int *)(ptr + 4) == size) || !(*(int *)(ptr + RES_PRE + size) == (size ^ 0x7bed7bed)) || !(*(int *)(ptr + RES_PRE + 4 + size) == i)) { logprintf ("Bad block at address %p (size %d, num %d)\n", ptr, size, i); assert (0 && "Bad block"); } } for (i = 0; i < free_blocks_cnt; i++) { void *ptr = free_blocks[i]; int l = *(int *)ptr; int j = 0; for (j = 0; j < l; j++) { if (*(char *)(ptr + 4 + j)) { hexdump (ptr + 8, ptr + 8 + l + ((-l) & 3)); logprintf ("Used freed memory size = %d. ptr = %p\n", l + 4 - RES_PRE - RES_AFTER, ptr); assert (0); } } } //logprintf ("ok. Used_blocks = %d. Free blocks = %d\n", used_blocks, free_blocks_cnt); } void tgl_exists_debug (void *ptr, int size) { ptr -= RES_PRE; if (size != (int)((*(int *)ptr) ^ 0xbedabeda)) { logprintf ("size = %d, ptr = %d\n", size, (*(int *)ptr) ^ 0xbedabeda); } assert (*(int *)ptr == (int)((size) ^ 0xbedabeda)); assert (*(int *)(ptr + RES_PRE + size) == (int)((size) ^ 0x7bed7bed)); assert (*(int *)(ptr + 4) == size); int block_num = *(int *)(ptr + 4 + RES_PRE + size); if (block_num >= used_blocks) { logprintf ("block_num = %d, used = %d\n", block_num, used_blocks); } assert (block_num < used_blocks); } void tgl_exists_release (void *ptr, int size) {} void tgl_check_release (void) {} void tgl_my_clock_gettime (int clock_id, struct timespec *T) { #ifdef __MACH__ // We are ignoring MONOTONIC and hope time doesn't go back too often clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); T->tv_sec = mts.tv_sec; T->tv_nsec = mts.tv_nsec; #else assert (clock_gettime(clock_id, T) >= 0); #endif } double tglt_get_double_time (void) { struct timespec tv; tgl_my_clock_gettime (CLOCK_REALTIME, &tv); return tv.tv_sec + 1e-9 * tv.tv_nsec; } void tglt_secure_random (void *s, int l) { if (TGLC_rand_bytes (s, l) <= 0) { /*if (allow_weak_random) { TGLC_rand_pseudo_bytes (s, l); } else {*/ assert (0 && "End of random. If you want, you can start with -w"); //} } else { #ifdef VALGRIND_FIXES VALGRIND_MAKE_MEM_DEFINED (s, l); VALGRIND_CHECK_MEM_IS_DEFINED (s, l); #endif } } struct tgl_allocator tgl_allocator_debug = { .alloc = tgl_alloc_debug, .realloc = tgl_realloc_debug, .free = tgl_free_debug, .check = tgl_check_debug, .exists = tgl_exists_debug }; struct tgl_allocator tgl_allocator_release = { .alloc = tgl_alloc_release, .realloc = tgl_realloc_release, .free = tgl_free_release, .check = tgl_check_release, .exists = tgl_exists_release }; long long tgl_get_allocated_bytes (void) { return total_allocated_bytes; } struct tgl_allocator *tgl_allocator = &tgl_allocator_release; ================================================ FILE: tools.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __TOOLS_H__ #define __TOOLS_H__ #include #include #include #include #include //#include "tgl.h" #include "crypto/err.h" #include "crypto/rand.h" struct tgl_allocator { void *(*alloc)(size_t size); void *(*realloc)(void *ptr, size_t old_size, size_t size); void (*free)(void *ptr, int size); void (*check)(void); void (*exists)(void *ptr, int size); }; #define talloc tgl_allocator->alloc #define talloc0 tgl_alloc0 #define tfree tgl_allocator->free #define tfree_str tgl_free_str #define tfree_secure tgl_free_secure #define trealloc tgl_allocator->realloc #define tcheck tgl_allocator->check #define texists tgl_allocator->exists #define tstrdup tgl_strdup #define tmemdup tgl_memdup #define tstrndup tgl_strndup #define tasprintf tgl_asprintf #define tsnprintf tgl_snprintf extern struct tgl_allocator *tgl_allocator; double tglt_get_double_time (void); int tgl_inflate (void *input, int ilen, void *output, int olen); //void ensure (int r); //void ensure_ptr (void *p); static inline void out_of_memory (void) { fprintf (stderr, "Out of memory\n"); exit (1); } static inline void ensure (int r) { if (!r) { fprintf (stderr, "Crypto error\n"); TGLC_err_print_errors_fp (stderr); assert (0); } } static inline void ensure_ptr (void *p) { if (p == NULL) { out_of_memory (); } } void *tgl_alloc_debug (size_t size); void *tgl_alloc_release (size_t size); void *tgl_realloc_debug (void *ptr, size_t old_size, size_t size); void *tgl_realloc_release (void *ptr, size_t old_size, size_t size); void *tgl_alloc0 (size_t size); char *tgl_strdup (const char *s); char *tgl_strndup (const char *s, size_t n); void tgl_free_debug (void *ptr, int size); void tgl_free_release (void *ptr, int size); //void tgl_free_str (void *ptr); //void tgl_free_secure (void *ptr, int size); void tgl_check_debug (void); void tgl_exists_debug (void *ptr, int size); void tgl_check_release (void); void tgl_exists_release (void *ptr, int size); void *tgl_memdup (const void *s, size_t n); int tgl_snprintf (char *buf, int len, const char *format, ...) __attribute__ ((format (__printf__, 3, 4))); int tgl_asprintf (char **res, const char *format, ...) __attribute__ ((format (__printf__, 2, 3))); void tglt_secure_random (void *s, int l); void tgl_my_clock_gettime (int clock_id, struct timespec *T); static inline void tgl_free_str (void *ptr) { if (!ptr) { return; } tfree (ptr, strlen ((const char *)ptr) + 1); } static inline void tgl_free_secure (void *ptr, int size) { memset (ptr, 0, size); tfree (ptr, size); } static inline void hexdump (void *ptr, void *end_ptr) { int total = 0; unsigned char *bptr = (unsigned char *)ptr; while (bptr < (unsigned char *)end_ptr) { fprintf (stderr, "%02x", (int)*bptr); bptr ++; total ++; if (total == 16) { fprintf (stderr, "\n"); total = 0; } } if (total) { fprintf (stderr, "\n"); } } #endif ================================================ FILE: tree.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __TREE_H__ #define __TREE_H__ #include #include #include #include "tools.h" #pragma pack(push,4) #define DEFINE_TREE(X_NAME, X_TYPE, X_CMP, X_UNSET) \ struct tree_ ## X_NAME { \ struct tree_ ## X_NAME *left, *right;\ X_TYPE x;\ int y;\ };\ \ static struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\ struct tree_ ## X_NAME *T = talloc (sizeof (*T));\ T->x = x;\ T->y = y;\ T->left = T->right = 0;\ return T;\ }\ \ static void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\ tfree (T, sizeof (*T));\ }\ \ static void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\ if (!T) {\ *L = *R = 0;\ } else {\ int c = X_CMP (x, T->x);\ if (c < 0) {\ tree_split_ ## X_NAME (T->left, x, L, &T->left);\ *R = T;\ } else {\ tree_split_ ## X_NAME (T->right, x, &T->right, R);\ *L = T;\ }\ }\ }\ \ static struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result,unused));\ static struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\ if (!T) {\ return new_tree_node_ ## X_NAME (x, y);\ } else {\ if (y > T->y) {\ struct tree_ ## X_NAME *N = new_tree_node_ ## X_NAME (x, y);\ tree_split_ ## X_NAME (T, x, &N->left, &N->right);\ return N;\ } else {\ int c = X_CMP (x, T->x);\ assert (c);\ if (c < 0) { \ T->left = tree_insert_ ## X_NAME (T->left, x, y);\ } else { \ T->right = tree_insert_ ## X_NAME (T->right, x, y);\ } \ return T; \ }\ }\ }\ \ static struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\ if (!L || !R) {\ return L ? L : R;\ } else {\ if (L->y > R->y) {\ L->right = tree_merge_ ## X_NAME (L->right, R);\ return L;\ } else {\ R->left = tree_merge_ ## X_NAME (L, R->left);\ return R;\ }\ }\ }\ \ static struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result,unused));\ static struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ assert (T);\ int c = X_CMP (x, T->x);\ if (!c) {\ struct tree_ ## X_NAME *N = tree_merge_ ## X_NAME (T->left, T->right);\ delete_tree_node_ ## X_NAME (T);\ return N;\ } else {\ if (c < 0) { \ T->left = tree_delete_ ## X_NAME (T->left, x); \ } else { \ T->right = tree_delete_ ## X_NAME (T->right, x); \ } \ return T; \ }\ }\ \ static X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *t) __attribute__ ((unused));\ static X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\ if (!T) { return X_UNSET; } \ while (T->left) { T = T->left; }\ return T->x; \ } \ \ static X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((unused));\ static X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ int c;\ while (T && (c = X_CMP (x, T->x))) {\ T = (c < 0 ? T->left : T->right);\ }\ return T ? T->x : X_UNSET;\ }\ \ static void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) __attribute__ ((unused));\ static void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) {\ if (!T) { return; } \ tree_act_ ## X_NAME (T->left, act); \ act (T->x); \ tree_act_ ## X_NAME (T->right, act); \ }\ \ static void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) __attribute__ ((unused));\ static void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) {\ if (!T) { return; } \ tree_act_ex_ ## X_NAME (T->left, act, extra); \ act (T->x, extra); \ tree_act_ex_ ## X_NAME (T->right, act, extra); \ }\ \ static int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) __attribute__ ((unused));\ static int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \ if (!T) { return 0; }\ return 1 + tree_count_ ## X_NAME (T->left) + tree_count_ ## X_NAME (T->right); \ }\ static void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) __attribute__ ((unused));\ static void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \ if (!T) { return; }\ if (T->left) { \ assert (T->left->y <= T->y);\ assert (X_CMP (T->left->x, T->x) < 0); \ }\ if (T->right) { \ assert (T->right->y <= T->y);\ assert (X_CMP (T->right->x, T->x) > 0); \ }\ tree_check_ ## X_NAME (T->left); \ tree_check_ ## X_NAME (T->right); \ }\ static struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) __attribute__ ((unused));\ static struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \ if (!T) { return 0; }\ tree_clear_ ## X_NAME (T->left); \ tree_clear_ ## X_NAME (T->right); \ delete_tree_node_ ## X_NAME (T); \ return 0; \ } \ #define int_cmp(a,b) ((a) - (b)) #pragma pack(pop) #endif ================================================ FILE: updates.c ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #include "tgl.h" #include "updates.h" #include "mtproto-common.h" #include "tgl-binlog.h" #include "auto.h" #include "auto/auto-types.h" #include "auto/auto-skip.h" #include "auto/auto-fetch-ds.h" #include "auto/auto-free-ds.h" #include "tgl-structures.h" #include "tgl-methods-in.h" #include "tree.h" #include void tgl_do_get_channel_difference (struct tgl_state *TLS, int channel_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra); static void fetch_dc_option (struct tgl_state *TLS, struct tl_ds_dc_option *DS_DO) { vlogprintf (E_DEBUG, "id = %d, %.*s:%d\n", DS_LVAL (DS_DO->id), DS_RSTR (DS_DO->ip_address), DS_LVAL (DS_DO->port)); bl_do_dc_option (TLS, DS_LVAL (DS_DO->flags), DS_LVAL (DS_DO->id), NULL, 0, DS_STR (DS_DO->ip_address), DS_LVAL (DS_DO->port)); } int tgl_check_pts_diff (struct tgl_state *TLS, int pts, int pts_count) { vlogprintf (E_DEBUG - 1, "pts = %d, pts_count = %d\n", pts, pts_count); if (!TLS->pts) { return 1; } //assert (TLS->pts); if (pts < TLS->pts + pts_count) { vlogprintf (E_NOTICE, "Duplicate message with pts=%d\n", pts); return -1; } if (pts > TLS->pts + pts_count) { vlogprintf (E_NOTICE, "Hole in pts (pts = %d, count = %d, cur_pts = %d)\n", pts, pts_count, TLS->pts); tgl_do_get_difference (TLS, 0, 0, 0); return -1; } if (TLS->locks & TGL_LOCK_DIFF) { vlogprintf (E_DEBUG, "Update during get_difference. pts = %d\n", pts); return -1; } vlogprintf (E_DEBUG, "Ok update. pts = %d\n", pts); return 1; } int tgl_check_qts_diff (struct tgl_state *TLS, int qts, int qts_count) { vlogprintf (E_ERROR, "qts = %d, qts_count = %d\n", qts, qts_count); if (qts < TLS->qts + qts_count) { vlogprintf (E_NOTICE, "Duplicate message with qts=%d\n", qts); return -1; } if (qts > TLS->qts + qts_count) { vlogprintf (E_NOTICE, "Hole in qts (qts = %d, count = %d, cur_qts = %d)\n", qts, qts_count, TLS->qts); tgl_do_get_difference (TLS, 0, 0, 0); return -1; } if (TLS->locks & TGL_LOCK_DIFF) { vlogprintf (E_DEBUG, "Update during get_difference. qts = %d\n", qts); return -1; } vlogprintf (E_DEBUG, "Ok update. qts = %d\n", qts); return 1; } int tgl_check_channel_pts_diff (struct tgl_state *TLS, tgl_peer_t *_E, int pts, int pts_count) { struct tgl_channel *E = &_E->channel; vlogprintf (E_DEBUG - 1, "channel %d: pts = %d, pts_count = %d, current_pts = %d\n", tgl_get_peer_id (E->id), pts, pts_count, E->pts); if (!E->pts) { return 1; } //assert (TLS->pts); if (pts < E->pts + pts_count) { vlogprintf (E_NOTICE, "Duplicate message with pts=%d\n", pts); return -1; } if (pts > E->pts + pts_count) { vlogprintf (E_NOTICE, "Hole in pts (pts = %d, count = %d, cur_pts = %d)\n", pts, pts_count, E->pts); tgl_do_get_channel_difference (TLS, tgl_get_peer_id (E->id), 0, 0); return -1; } if (E->flags & TGLCHF_DIFF) { vlogprintf (E_DEBUG, "Update during get_difference. pts = %d\n", pts); return -1; } vlogprintf (E_DEBUG, "Ok update. pts = %d\n", pts); return 1; } static int do_skip_seq (struct tgl_state *TLS, int seq) { if (!seq) { vlogprintf (E_DEBUG, "Ok update. seq = %d\n", seq); return 0; } if (TLS->seq) { if (seq <= TLS->seq) { vlogprintf (E_NOTICE, "Duplicate message with seq=%d\n", seq); return -1; } if (seq > TLS->seq + 1) { vlogprintf (E_NOTICE, "Hole in seq (seq = %d, cur_seq = %d)\n", seq, TLS->seq); //vlogprintf (E_NOTICE, "lock_diff = %s\n", (TLS->locks & TGL_LOCK_DIFF) ? "true" : "false"); tgl_do_get_difference (TLS, 0, 0, 0); return -1; } if (TLS->locks & TGL_LOCK_DIFF) { vlogprintf (E_DEBUG, "Update during get_difference. seq = %d\n", seq); return -1; } vlogprintf (E_DEBUG, "Ok update. seq = %d\n", seq); return 0; } else { return -1; } } void tglu_work_update (struct tgl_state *TLS, int check_only, struct tl_ds_update *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { vlogprintf (E_DEBUG, "Update during get_difference. DROP\n"); return; } if (DS_U->pts) { assert (DS_U->pts_count); if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) { return; } } if (DS_U->qts) { if (!check_only && tgl_check_qts_diff (TLS, DS_LVAL (DS_U->qts), 1) <= 0) { return; } } if (DS_U->channel_pts) { assert (DS_U->channel_pts_count); int channel_id; if (DS_U->channel_id) { channel_id = DS_LVAL (DS_U->channel_id); } else { assert (DS_U->message); if (!DS_U->message->to_id) { return; } assert (DS_U->message->to_id); assert (DS_U->message->to_id->magic == CODE_peer_channel); channel_id = DS_LVAL (DS_U->message->to_id->channel_id); } tgl_peer_t *E = tgl_peer_get (TLS, TGL_MK_CHANNEL (channel_id)); if (!E) { return; } if (!check_only && tgl_check_channel_pts_diff (TLS, E, DS_LVAL (DS_U->channel_pts), DS_LVAL (DS_U->channel_pts_count)) <= 0) { return; } } vlogprintf (E_NOTICE, "update 0x%08x (check=%d)\n", DS_U->magic, check_only); if (check_only > 0 && DS_U->magic != CODE_update_message_i_d) { return; } switch (DS_U->magic) { case CODE_update_new_message: { //struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_U->id)); //int new = (!N || !(N->flags & TGLMF_CREATED)); int new_msg = 0; struct tgl_message *M = tglf_fetch_alloc_message (TLS, DS_U->message, &new_msg); assert (M); if (new_msg) { bl_do_msg_update (TLS, &M->permanent_id); } break; }; case CODE_update_message_i_d: { tgl_message_id_t msg_id; msg_id.peer_type = TGL_PEER_RANDOM_ID; msg_id.id = DS_LVAL (DS_U->random_id); struct tgl_message *M = tgl_message_get (TLS, &msg_id); if (M && (M->flags & TGLMF_PENDING)) { msg_id = M->permanent_id; msg_id.id = DS_LVAL (DS_U->id); bl_do_set_msg_id (TLS, &M->permanent_id, &msg_id); bl_do_msg_update (TLS, &msg_id); } } break; /* case CODE_update_read_messages: { int n = DS_LVAL (DS_U->messages->cnt); int i; for (i = 0; i < n; i++) { struct tgl_message *M = tgl_message_get (TLS, DS_LVAL (DS_U->messages->data[i])); if (M) { tgl_peer_t *P; if (M->flags & TGLMF_OUT) { P = tgl_peer_get (TLS, M->to_id); if (P && (P->flags & TGLMF_CREATED)) { if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL, (int *)&M->id, TGL_FLAGS_UNCHANGED); } else { bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (int *)&M->id, TGL_FLAGS_UNCHANGED); } } } else { if (tgl_get_peer_type (M->to_id) == TGL_PEER_USER) { P = tgl_peer_get (TLS, M->from_id); } else { P = tgl_peer_get (TLS, M->to_id); } if (P && (P->flags & TGLMF_CREATED)) { if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, NULL, (int *)&M->id, NULL, TGL_FLAGS_UNCHANGED); } else { bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (int *)&M->id, NULL, TGL_FLAGS_UNCHANGED); } } } } } } break;*/ case CODE_update_user_typing: { tgl_peer_id_t id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *U = tgl_peer_get (TLS, id); enum tgl_typing_status status = tglf_fetch_typing (DS_U->action); if (TLS->callback.type_notification && U) { TLS->callback.type_notification (TLS, (void *)U, status); } } break; case CODE_update_chat_user_typing: { tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id)); tgl_peer_id_t id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *C = tgl_peer_get (TLS, chat_id); tgl_peer_t *U = tgl_peer_get (TLS, id); enum tgl_typing_status status = tglf_fetch_typing (DS_U->action); if (U && C) { if (TLS->callback.type_in_chat_notification) { TLS->callback.type_in_chat_notification (TLS, (void *)U, (void *)C, status); } } } break; case CODE_update_user_status: { tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *U = tgl_peer_get (TLS, user_id); if (U) { tglf_fetch_user_status (TLS, &U->user.status, &U->user, DS_U->status); if (TLS->callback.status_notification) { TLS->callback.status_notification (TLS, (void *)U); } } } break; case CODE_update_user_name: { tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *UC = tgl_peer_get (TLS, user_id); if (UC && (UC->flags & TGLPF_CREATED)) { bl_do_user (TLS, tgl_get_peer_id (user_id), NULL, DS_STR (DS_U->first_name), DS_STR (DS_U->last_name), NULL, 0, DS_STR (DS_U->username), NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED); } } break; case CODE_update_user_photo: { tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *UC = tgl_peer_get (TLS, user_id); if (UC && (UC->flags & TGLUF_CREATED)) { bl_do_user (TLS, tgl_get_peer_id (user_id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, DS_U->photo, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED); } } break; case CODE_update_delete_messages: { } break; case CODE_update_chat_participants: { tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id)); tgl_peer_t *C = tgl_peer_get (TLS, chat_id); if (C && (C->flags & TGLPF_CREATED) && DS_U->participants->magic == CODE_chat_participants) { bl_do_chat (TLS, tgl_get_peer_id (chat_id), NULL, 0, NULL, NULL, DS_U->participants->version, (struct tl_ds_vector *)DS_U->participants->participants, NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED); } } break; case CODE_update_contact_registered: { tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *U = tgl_peer_get (TLS, user_id); if (TLS->callback.user_registered && U) { TLS->callback.user_registered (TLS, (void *)U); } } break; case CODE_update_contact_link: { } break; /*case CODE_update_activation: { tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_t *U = tgl_peer_get (TLS, user_id); if (TLS->callback.user_activated && U) { TLS->callback.user_activated (TLS, (void *)U); } } break;*/ case CODE_update_new_authorization: { if (TLS->callback.new_authorization) { TLS->callback.new_authorization (TLS, DS_U->device->data, DS_U->location->data); } } break; /*case CODE_update_new_geo_chat_message: { } break;*/ case CODE_update_new_encrypted_message: { struct tgl_message *M = tglf_fetch_alloc_encrypted_message (TLS, DS_U->encr_message); if (M) { bl_do_msg_update (TLS, &M->permanent_id); } } break; case CODE_update_encryption: { struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (TLS, DS_U->encr_chat); vlogprintf (E_DEBUG, "Secret chat state = %d\n", E->state); if (E->state == sc_ok) { tgl_do_send_encr_chat_layer (TLS, E); } } break; case CODE_update_encrypted_chat_typing: { tgl_peer_id_t id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_U->chat_id)); tgl_peer_t *P = tgl_peer_get (TLS, id); if (P) { if (TLS->callback.type_in_secret_chat_notification) { TLS->callback.type_in_secret_chat_notification (TLS, (void *)P); } } } break; case CODE_update_encrypted_messages_read: { tgl_peer_id_t id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_U->chat_id)); tgl_peer_t *P = tgl_peer_get (TLS, id); if (P && P->last) { struct tgl_message *M = P->last; while (M && (!(M->flags & TGLMF_OUT) || (M->flags & TGLMF_UNREAD))) { if (M->flags & TGLMF_OUT) { bl_do_edit_message_encr (TLS, &M->permanent_id, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, M->flags & ~TGLMF_UNREAD); } M = M->next; } } } break; case CODE_update_chat_participant_add: { tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id)); tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); tgl_peer_id_t inviter_id = TGL_MK_USER (DS_LVAL (DS_U->inviter_id)); int version = DS_LVAL (DS_U->version); tgl_peer_t *C = tgl_peer_get (TLS, chat_id); if (C && (C->flags & TGLPF_CREATED)) { bl_do_chat_add_user (TLS, C->id, version, tgl_get_peer_id (user_id), tgl_get_peer_id (inviter_id), time (0)); } } break; case CODE_update_chat_participant_delete: { tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id)); tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id)); int version = DS_LVAL (DS_U->version); tgl_peer_t *C = tgl_peer_get (TLS, chat_id); if (C && (C->flags & TGLPF_CREATED)) { bl_do_chat_del_user (TLS, C->id, version, tgl_get_peer_id (user_id)); } } break; case CODE_update_dc_options: { int i; for (i = 0; i < DS_LVAL (DS_U->dc_options->cnt); i++) { fetch_dc_option (TLS, DS_U->dc_options->data[i]); } } break; case CODE_update_user_blocked: { int blocked = DS_BVAL (DS_U->blocked); tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user_id))); if (P && (P->flags & TGLPF_CREATED)) { int flags = P->flags & 0xffff; if (blocked) { flags |= TGLUF_BLOCKED; } else { flags &= ~TGLUF_BLOCKED; } bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, flags); } } break; case CODE_update_notify_settings: { } break; case CODE_update_service_notification: { vlogprintf (E_ERROR, "Notification %.*s: %.*s\n", DS_RSTR (DS_U->type), DS_RSTR (DS_U->message_text)); if (TLS->callback.notification) { TLS->callback.notification (TLS, DS_U->type->data, DS_U->message_text->data); } } break; case CODE_update_privacy: vlogprintf (E_NOTICE, "privacy change update\n"); break; case CODE_update_user_phone: { tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user_id))); if (U && (U->flags & TGLPF_CREATED)) { bl_do_user (TLS, tgl_get_peer_id (U->id), NULL, NULL, 0, NULL, 0, DS_STR (DS_U->phone), NULL, 0, NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED); } } break; case CODE_update_read_history_inbox: { tgl_peer_id_t id = tglf_fetch_peer_id (TLS, DS_U->peer); tgl_peer_t *P = tgl_peer_get (TLS, id); if (P && (P->flags & TGLPF_CREATED)) { if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, DS_U->max_id, NULL, NULL, TGL_FLAGS_UNCHANGED); } else { bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, DS_U->max_id, NULL, TGL_FLAGS_UNCHANGED); } } } break; case CODE_update_read_history_outbox: { tgl_peer_id_t id = tglf_fetch_peer_id (TLS, DS_U->peer); tgl_peer_t *P = tgl_peer_get (TLS, id); if (P && (P->flags & TGLPF_CREATED)) { if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, NULL, DS_U->max_id, NULL, TGL_FLAGS_UNCHANGED); } else { bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, DS_U->max_id, TGL_FLAGS_UNCHANGED); } } } break; case CODE_update_web_page: { } break; /*case CODE_update_msg_update: { struct tgl_message *M = tgl_message_get (TLS, DS_LVAL (DS_U->id)); if (M) { bl_do_msg_update (TLS, M->id); } } break;*/ case CODE_update_read_messages_contents: break; case CODE_update_channel_too_long: { tgl_do_get_channel_difference (TLS, DS_LVAL (DS_U->channel_id), NULL, NULL); } break; case CODE_update_channel: break; case CODE_update_channel_group: break; case CODE_update_new_channel_message: { int new_msg = 0; struct tgl_message *M = tglf_fetch_alloc_message (TLS, DS_U->message, &new_msg); if (M && new_msg) { bl_do_msg_update (TLS, &M->permanent_id); } } break; case CODE_update_read_channel_inbox: break; case CODE_update_delete_channel_messages: break; case CODE_update_channel_message_views: break; case CODE_update_chat_admins: break; case CODE_update_chat_participant_admin: break; case CODE_update_new_sticker_set: break; case CODE_update_sticker_sets_order: break; case CODE_update_sticker_sets: break; case CODE_update_saved_gifs: break; case CODE_update_bot_inline_query: break; default: assert (0); } if (check_only) { return; } if (DS_U->pts) { assert (DS_U->pts_count); bl_do_set_pts (TLS, DS_LVAL (DS_U->pts)); } if (DS_U->qts) { bl_do_set_qts (TLS, DS_LVAL (DS_U->qts)); } if (DS_U->channel_pts) { assert (DS_U->channel_pts_count); int channel_id; if (DS_U->channel_id) { channel_id = DS_LVAL (DS_U->channel_id); } else { assert (DS_U->message); assert (DS_U->message->to_id); assert (DS_U->message->to_id->magic == CODE_peer_channel); channel_id = DS_LVAL (DS_U->message->to_id->channel_id); } bl_do_set_channel_pts (TLS, channel_id, DS_LVAL (DS_U->channel_pts)); } } void tglu_work_updates (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } if (!check_only && do_skip_seq (TLS, DS_LVAL (DS_U->seq)) < 0) { return; } int i; if (DS_U->users) { for (i = 0; i < DS_LVAL (DS_U->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_U->users->data[i]); } } if (DS_U->chats) { for (i = 0; i < DS_LVAL (DS_U->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_U->chats->data[i]); } } if (DS_U->updates) { for (i = 0; i < DS_LVAL (DS_U->updates->cnt); i++) { tglu_work_update (TLS, check_only, DS_U->updates->data[i]); } } if (check_only) { return; } bl_do_set_date (TLS, DS_LVAL (DS_U->date)); bl_do_set_seq (TLS, DS_LVAL (DS_U->seq)); } void tglu_work_updates_combined (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } if (!check_only && do_skip_seq (TLS, DS_LVAL (DS_U->seq_start)) < 0) { return; } int i; for (i = 0; i < DS_LVAL (DS_U->users->cnt); i++) { tglf_fetch_alloc_user (TLS, DS_U->users->data[i]); } for (i = 0; i < DS_LVAL (DS_U->chats->cnt); i++) { tglf_fetch_alloc_chat (TLS, DS_U->chats->data[i]); } for (i = 0; i < DS_LVAL (DS_U->updates->cnt); i++) { tglu_work_update (TLS, check_only, DS_U->updates->data[i]); } if (check_only) { return; } bl_do_set_date (TLS, DS_LVAL (DS_U->date)); bl_do_set_seq (TLS, DS_LVAL (DS_U->seq)); } void tglu_work_update_short_message (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) { return; } if (check_only > 0) { return; } //struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_U->id)); //int new = (!N || !(N->flags & TGLMF_CREATED)); struct tgl_message *M = tglf_fetch_alloc_message_short (TLS, DS_U); if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } assert (M); if (1) { bl_do_msg_update (TLS, &M->permanent_id); } if (check_only) { return; } bl_do_set_pts (TLS, DS_LVAL (DS_U->pts)); } void tglu_work_update_short_chat_message (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) { return; } if (check_only > 0) { return; } //struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_U->id)); //int new = (!N || !(N->flags & TGLMF_CREATED)); struct tgl_message *M = tglf_fetch_alloc_message_short_chat (TLS, DS_U); if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } assert (M); if (1) { bl_do_msg_update (TLS, &M->permanent_id); } if (check_only) { return; } bl_do_set_pts (TLS, DS_LVAL (DS_U->pts)); } void tglu_work_updates_too_long (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } vlogprintf (E_NOTICE, "updates too long... Getting difference\n"); if (check_only) { return; } tgl_do_get_difference (TLS, 0, 0, 0); } void tglu_work_update_short (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } tglu_work_update (TLS, check_only, DS_U->update); } void tglu_work_update_short_sent_message (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U, void *extra) { if (DS_U->pts) { assert (DS_U->pts_count); if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) { return; } } struct tgl_message *M = extra; if (!M) { return; } //long long random_id = M->permanent_id.id; tgl_message_id_t msg_id = M->permanent_id; msg_id.id = DS_LVAL (DS_U->id); bl_do_set_msg_id (TLS, &M->permanent_id, &msg_id); //tgls_insert_random2local (TLS, random_id, &msg_id); int f = DS_LVAL (DS_U->flags); unsigned flags = M->flags; if (f & 1) { flags |= TGLMF_UNREAD; } if (f & 2) { flags |= TGLMF_OUT; } if (f & 16) { flags |= TGLMF_MENTION; } bl_do_edit_message (TLS, &M->permanent_id, NULL, NULL, NULL, NULL, NULL, NULL, 0, DS_U->media, NULL, NULL, NULL, NULL, flags); if (check_only) { return; } bl_do_msg_update (TLS, &M->permanent_id); if (DS_U->pts) { bl_do_set_pts (TLS, DS_LVAL (DS_U->pts)); } } void tglu_work_any_updates (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U, void *extra) { if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) { return; } switch (DS_U->magic) { case CODE_updates_too_long: tglu_work_updates_too_long (TLS, check_only, DS_U); return; case CODE_update_short_message: tglu_work_update_short_message (TLS, check_only, DS_U); return; case CODE_update_short_chat_message: tglu_work_update_short_chat_message (TLS, check_only, DS_U); return; case CODE_update_short: tglu_work_update_short (TLS, check_only, DS_U); return; case CODE_updates_combined: tglu_work_updates_combined (TLS, check_only, DS_U); return; case CODE_updates: tglu_work_updates (TLS, check_only, DS_U); return; case CODE_update_short_sent_message: tglu_work_update_short_sent_message (TLS, check_only, DS_U, extra); return; default: assert (0); } } void tglu_work_any_updates_buf (struct tgl_state *TLS) { struct tl_ds_updates *DS_U = fetch_ds_type_updates (TYPE_TO_PARAM (updates)); assert (DS_U); tglu_work_any_updates (TLS, 1, DS_U, NULL); tglu_work_any_updates (TLS, 0, DS_U, NULL); free_ds_type_updates (DS_U, TYPE_TO_PARAM (updates)); } #define user_cmp(a,b) (tgl_get_peer_id ((a)->id) - tgl_get_peer_id ((b)->id)) DEFINE_TREE(user, struct tgl_user *,user_cmp,0) static void notify_status (struct tgl_user *U, void *ex) { struct tgl_state *TLS = ex; if (TLS->callback.user_status_update) { TLS->callback.user_status_update (TLS, U); } } static void status_notify (struct tgl_state *TLS, void *arg) { tree_act_ex_user (TLS->online_updates, notify_status, TLS); tree_clear_user (TLS->online_updates); TLS->online_updates = NULL; TLS->timer_methods->free (TLS->online_updates_timer); TLS->online_updates_timer = NULL; } void tgl_insert_status_update (struct tgl_state *TLS, struct tgl_user *U) { if (!tree_lookup_user (TLS->online_updates, U)) { TLS->online_updates = tree_insert_user (TLS->online_updates, U, rand ()); } if (!TLS->online_updates_timer) { TLS->online_updates_timer = TLS->timer_methods->alloc (TLS, status_notify, 0); TLS->timer_methods->insert (TLS->online_updates_timer, 0); } } static void user_expire (struct tgl_state *TLS, void *arg) { struct tgl_user *U = arg; TLS->timer_methods->free (U->status.ev); U->status.ev = 0; U->status.online = -1; U->status.when = tglt_get_double_time (); tgl_insert_status_update (TLS, U); } void tgl_insert_status_expire (struct tgl_state *TLS, struct tgl_user *U) { assert (!U->status.ev); U->status.ev = TLS->timer_methods->alloc (TLS, user_expire, U); TLS->timer_methods->insert (U->status.ev, U->status.when - tglt_get_double_time ()); } void tgl_remove_status_expire (struct tgl_state *TLS, struct tgl_user *U) { TLS->timer_methods->free (U->status.ev); U->status.ev = 0; } ================================================ FILE: updates.h ================================================ /* This file is part of tgl-library This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright Vitaly Valtman 2013-2015 */ #ifndef __UPDATES_H__ #define __UPDATES_H__ struct tl_ds_updates; struct tl_ds_update; void tgl_insert_status_update (struct tgl_state *TLS, struct tgl_user *U); void tgl_insert_status_expire (struct tgl_state *TLS, struct tgl_user *U); void tgl_remove_status_expire (struct tgl_state *TLS, struct tgl_user *U); int tgl_check_pts_diff (struct tgl_state *TLS, int pts, int pts_count); void tglu_work_update (struct tgl_state *TLS, int check_only, struct tl_ds_update *DS_U); void tglu_work_updates (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U); void tglu_work_any_updates_buf (struct tgl_state *TLS); void tglu_work_any_updates (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U, void *extra); #endif